17

स्टैक ओवरफ़्लो के नमस्ते अच्छे प्रोग्रामर! मैंने इस समस्या के साथ एक अच्छा सप्ताह बिताया है और अब समाधान के लिए बेताब है।गलत टुकड़े गलत तरीके से संक्रमण


परिदृश्य

मैं android.app.Fragment समर्थन टुकड़े के साथ भ्रमित होने की नहीं है का उपयोग कर रहा हूँ।

मैं 6 बच्चे टुकड़े नामित किया है:

  • FragmentOne
  • FragmentTwo
  • FragmentThree
  • FragmentA
  • FragmentB
  • FragmentC

2 माता पिता टुकड़े नामित किया है:

  • FragmentNumeric
  • FragmentAlpha

मैं 1 गतिविधि नाम दिया:

  • MainActivity

वे निम्नलिखित में व्यवहार करते हैं:

  • बाल टुकड़े टुकड़े कि केवल एक दृश्य दिखाने के हैं, वे बताते हैं और न ही टुकड़े शामिल नहीं है।
  • अभिभावक टुकड़े अपने पूरे दृश्य को एक बच्चे के टुकड़े से भरते हैं। वे बच्चे के टुकड़े को अन्य बाल टुकड़ों के साथ बदलने में सक्षम हैं।
  • गतिविधि अपने अधिकांश दृश्य को पैरेंट खंड के साथ भरती है। यह इसे अन्य मूल टुकड़ों के साथ बदल सकता है। तो किसी भी समय स्क्रीन में केवल एक ही बच्चा खंड दिख रहा है।

आपका अनुमान सही किया है,

FragmentNumeric बच्चे टुकड़े FragmentOne, FragmentTwo, और FragmentThree को दर्शाता है।

FragmentAlpha बच्चे के टुकड़े FragmentA, FragmentB, और FragmentC दिखाता है।


समस्या

मैं संक्रमण/माता-पिता और बच्चे के टुकड़े चेतन करने के लिए कोशिश कर रहा हूँ। बच्चे के टुकड़े सुचारू रूप से संक्रमण की उम्मीद करते हैं। हालांकि जब मैं एक नए माता-पिता के टुकड़े में संक्रमण करता हूं, तो यह भयानक लग रहा है। बच्चे का टुकड़ा ऐसा लगता है कि यह अपने मूल खंड से एक स्वतंत्र संक्रमण चलाता है।और बच्चे का टुकड़ा ऐसा लगता है जैसे इसे पैरेंट टुकड़े से हटा दिया जाता है। इसका एक गिफ यहां https://imgur.com/kOAotvk देखा जा सकता है। ध्यान दें कि जब मैं अल्फा दिखाता हूं तो क्या होता है।

निकटतम प्रश्न & उत्तर मैं यहां देख सकता हूं: Nested fragments disappear during transition animation हालांकि सभी उत्तर असंतुष्ट हैक्स हैं।


एनिमेटर XML फ़ाइलें

मैं निम्नलिखित एनिमेटर प्रभाव (अवधि परीक्षण प्रयोजनों के लिए लंबा है):

fragment_enter.xml

<?xml version="1.0" encoding="utf-8"?> 
<set> 
    <objectAnimator xmlns:android="http://schemas.android.com/apk/res/android" 
     android:duration="4000" 
     android:interpolator="@android:anim/linear_interpolator" 
     android:propertyName="xFraction" 
     android:valueFrom="1.0" 
     android:valueTo="0" /> 
</set> 

fragment_exit.xml

<?xml version="1.0" encoding="utf-8"?> 
<set> 
    <objectAnimator xmlns:android="http://schemas.android.com/apk/res/android" 
     android:duration="4000" 
     android:interpolator="@android:anim/linear_interpolator" 
     android:propertyName="xFraction" 
     android:valueFrom="0" 
     android:valueTo="-1.0" /> 
</set> 

fragment_pop.xml

<?xml version="1.0" encoding="utf-8"?> 
<set> 
    <objectAnimator xmlns:android="http://schemas.android.com/apk/res/android" 
     android:duration="4000" 
     android:interpolator="@android:anim/linear_interpolator" 
     android:propertyName="xFraction" 
     android:valueFrom="0" 
     android:valueTo="1.0" /> 
</set> 

fragment_push.xml

<?xml version="1.0" encoding="utf-8"?> 
<set> 
    <objectAnimator xmlns:android="http://schemas.android.com/apk/res/android" 
     android:duration="4000" 
     android:interpolator="@android:anim/linear_interpolator" 
     android:propertyName="xFraction" 
     android:valueFrom="-1.0" 
     android:valueTo="0" /> 
</set> 

fragment_nothing.xml

<?xml version="1.0" encoding="utf-8"?> 
<set> 
    <objectAnimator xmlns:android="http://schemas.android.com/apk/res/android" 
     android:duration="4000" /> 
</set> 

MainActivity.kt

विचारणीय बातें: पहले माता-पिता टुकड़ा, FragmentNumeric, इसलिए गतिविधि के साथ अपने हमेशा तैयार प्रभाव में प्रवेश करने और बाहर निकलने के प्रभाव की वजह से कुछ भी नहीं बाहर निकलने है नहीं है नहीं है। मैं भी इसके साथ FragmentTransaction#add उपयोग कर रहा हूँ, जहां के रूप में FragmentAlpha जल्दी से दिखा अपने पहले बच्चे टुकड़ा के मामले में FragmentTransaction#replace

class MainActivity : AppCompatActivity { 

    fun showFragmentNumeric(){ 
     this.fragmentManager.beginTransaction() 
       .setCustomAnimations(R.animator.fragment_nothing, 
            R.animator.fragment_nothing, 
            R.animator.fragment_push, 
            R.animator.fragment_pop) 
       .add(this.contentId, FragmentNumeric(), "FragmentNumeric") 
       .addToBackStack("FragmentNumeric") 
       .commit() 
} 

    fun showFragmentAlpha(){ 
     this.fragmentManager.beginTransaction() 
       .setCustomAnimations(R.animator.fragment_enter, 
            R.animator.fragment_exit, 
            R.animator.fragment_push, 
            R.animator.fragment_pop) 
       .replace(this.contentId, FragmentAlpha(), "FragmentAlpha") 
       .addToBackStack("FragmentAlpha") 
       .commit() 
    } 

    override fun onCreate(savedInstanceState: Bundle?) { 
     super.onCreate(savedInstanceState) 
     if (savedInstanceState == null) { 
      showFragmentNumeric() 
     } 
    } 
} 

FragmentNumeric

गतिविधि के रूप में एक ही बात करता है उपयोग कर रहा है।

class FragmentNumeric : Fragment { 

    fun showFragmentOne(){ 
      this.childFragmentManager.beginTransaction() 
        .setCustomAnimations(R.animator.fragment_nothing, 
             R.animator.fragment_nothing, 
             R.animator.fragment_push, 
             R.animator.fragment_pop) 
        .add(this.contentId, FragmentOne(), "FragmentOne") 
        .addToBackStack("FragmentOne") 
        .commit() 
    } 

    fun showFragmentTwo(){ 
     this.childFragmentManager.beginTransaction() 
       .setCustomAnimations(R.animator.fragment_enter, 
            R.animator.fragment_exit, 
            R.animator.fragment_push, 
            R.animator.fragment_pop) 
       .replace(this.contentId, FragmentTwo(), "FragmentTwo") 
       .addToBackStack("FragmentTwo") 
       .commit() 
    } 


    fun showFragmentThree(){ 
     this.childFragmentManager.beginTransaction() 
       .setCustomAnimations(R.animator.fragment_enter, 
            R.animator.fragment_exit, 
            R.animator.fragment_push, 
            R.animator.fragment_pop) 
       .replace(this.contentId, FragmentThree(), "FragmentThree") 
       .addToBackStack("FragmentThree") 
       .commit() 
    } 

    override fun onViewCreated(view: View?, savedInstanceState: Bundle?) { 
     super.onViewCreated(view, savedInstanceState) 
     if (savedInstanceState == null) { 
      if (this.childFragmentManager.backStackEntryCount <= 1) { 
       showFragmentOne() 
      } 
     } 
    } 
} 

अन्य टुकड़े

FragmentAlpha FragmentNumeric के रूप में एक ही पैटर्न पीछा कर रहा है, टुकड़े ए, बी और सी क्रमशः के साथ टुकड़े एक, दो और तीन की जगह।

बच्चे के टुकड़े सिर्फ निम्नलिखित एक्सएमएल व्यू दिखा रहे हैं और अपने पाठ को सेट कर रहे हैं और बटन को श्रोता रूप से या तो पैरेंट खंड या गतिविधि से किसी फ़ंक्शन को कॉल करने के लिए गतिशील रूप से क्लिक करें।

view_child_example।एक्सएमएल

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:background="@color/background" 
    android:clickable="true" 
    android:focusable="true" 
    android:orientation="vertical"> 

    <TextView 
     android:id="@+id/view_child_example_header" 
     style="@style/Header" 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content" /> 


    <Button 
     android:id="@+id/view_child_example_button" 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content" /> 
</LinearLayout> 

चाकू और कुछ ठेके मैं बच्चे के टुकड़े अपने माता पिता के टुकड़े और होस्टिंग गतिविधियों के लिए कॉलबैक है नीचे की तरह कुछ कर रही द्वारा उपयोग करते हुए:

FragmentOne बटन क्लिक श्रोता सेट करने के लिए:

(parentFragment as FragmentNumeric).showFragmentTwo() 

FragmentTwo बटन क्लिक श्रोता सेट करने के लिए:

(parentFragment as FragmentNumeric).showFragmentThree() 

FragmentThree अलग है, यह सेट हो जाएगा करने के लिए क्लिक करें श्रोता:

(activity as MainActivity).showFragmentAlpha() 

है किसी को भी इस समस्या के लिए एक समाधान है?


अद्यतन 1

मैं एक उदाहरण परियोजना का अनुरोध किया के रूप में जोड़ दिया है: https://github.com/zafrani/NestedFragmentTransitions

मेरा मूल वीडियो में एक से और उस में एक अंतर माता पिता टुकड़ा नहीं रह गया है एक दृश्य का उपयोग करता है xFraction संपत्ति के साथ। तो ऐसा लगता है कि एंटर एनीमेशन में ओवरलैपिंग प्रभाव नहीं है। यह अभी भी माता-पिता से बच्चे के टुकड़े को हटा देता है और उन्हें एक तरफ एनिमेट करता है। एनीमेशन पूर्ण होने के बाद, फ्रैगमेंट थ्री को तुरंत फ्रैगमेंट ए के साथ बदल दिया जाता है।

अद्यतन 2

दोनों माता पिता और बच्चे टुकड़ा देखा गया xFraction संपत्ति का उपयोग कर रहे हैं। माता-पिता एनिमेटिंग करते समय बच्चों की एनीमेशन को दबाने की कुंजी है।

+3

प्रश्न पहले से ही स्पष्ट है, लेकिन चूंकि आपको लगता है कि इस मुद्दे को दिखाते हुए एक स्वच्छ प्रोजेक्ट है, तो यह अच्छा होगा अगर आप इसे कहीं भी अपलोड कर सकें। – natario

+0

कृपया गिफ अपडेट करें, ऐसा लगता है कि यह गुम है। युपीडी। क्षमा करें, मेरे बुरे, छवि मिली। – GensaGames

+0

@natario मैंने एक जिथब लिंक जोड़ा है। – zafrani

उत्तर

4

मुझे लगता है कि मुझे Fragment # onCreateAnimator का उपयोग करके इसे हल करने का कोई तरीका मिला है। संक्रमण का एक gif यहां देखा जा सकता है: https://imgur.com/94AvrW4

मैंने परीक्षण के लिए पीआर बनाया है, अब तक यह काम कर रहा है क्योंकि मैं कॉन्फ़िगरेशन में बदलाव की उम्मीद करता हूं और बैक बटन का समर्थन करता हूं।यहाँ लिंक दोनों जनक एवं बाल टुकड़े के लिए https://github.com/zafrani/NestedFragmentTransitions/pull/1/files#diff-c120dd82b93c862b01c2548bdcafcb20R25

BaseFragment है (onCreateAnimator के लिए यह कर रहा है)

override fun onCreateAnimator(transit: Int, enter: Boolean, nextAnim: Int): Animator { 
    if (isConfigChange) { 
     resetStates() 
     return nothingAnim() 
    } 

    if (parentFragment is ParentFragment) { 
     if ((parentFragment as BaseFragment).isPopping) { 
      return nothingAnim() 
     } 
    } 

    if (parentFragment != null && parentFragment.isRemoving) { 
     return nothingAnim() 
    } 

    if (enter) { 
     if (isPopping) { 
      resetStates() 
      return pushAnim() 
     } 
     if (isSuppressing) { 
      resetStates() 
      return nothingAnim() 
     } 
     return enterAnim() 
    } 

    if (isPopping) { 
     resetStates() 
     return popAnim() 
    } 

    if (isSuppressing) { 
     resetStates() 
     return nothingAnim() 
    } 

    return exitAnim() 
} 

बूलियन्स विभिन्न परिदृश्यों कि पीआर में देखने के लिए आसान होता है में स्थापित किया जा रहा है।

एनीमेशन कार्य हैं:

private fun enterAnim(): Animator { 
     return AnimatorInflater.loadAnimator(activity, R.animator.fragment_enter) 
    } 

    private fun exitAnim(): Animator { 
     return AnimatorInflater.loadAnimator(activity, R.animator.fragment_exit) 
    } 

    private fun pushAnim(): Animator { 
     return AnimatorInflater.loadAnimator(activity, R.animator.fragment_push) 
    } 

    private fun popAnim(): Animator { 
     return AnimatorInflater.loadAnimator(activity, R.animator.fragment_pop) 
    } 

    private fun nothingAnim(): Animator { 
     return AnimatorInflater.loadAnimator(activity, R.animator.fragment_nothing) 
    } 

बैठाना किसी एक बेहतर तरीका पाता सवाल खुला छोड़ देंगे।

0

आपको इतने तार वाले परिणाम मिल रहे हैं, क्योंकि आप अपने टुकड़े के लिए बाहर निकलने वाले एनिमेशन का उपयोग कर रहे हैं। असल में, हमारे पास हर बार फ्रैगमेंट एनीमेशन के साथ ऐसे मुद्दे होते हैं, और आखिर में जब हम संक्रमण को पूर्ववत करते हैं, तो हम स्वयं का उपयोग करने के लिए स्रोत फ्रैगमेंट एनीमेशन से चले जाते हैं।

1) इस व्यवहार को सत्यापित करने के लिए, आप केवल खंड के लिए निकास एनीमेशन को हटा सकते हैं, और सब कुछ ठीक रहेगा। ज्यादातर मामलों में यह पर्याप्त होना चाहिए, कारण बाहर निकलने एनीमेशन बहुत विशिष्ट और केवल एक टुकड़ा प्रबंध के लिए इस्तेमाल किया (आप में नहीं मामला है, बच्चे के साथ)

getFragmentManager().beginTransaction() 
       .setCustomAnimations(R.animator.enter_anim_frag1, 
            0, 
            R.animator.enter_anim_frag2, 
            0) 
       .replace(xxx, Xxx1, Xxx2) 
       .addToBackStack(null) 
       .commit() 

2) एक अन्य विकल्प, सुइट हो सकता है, यह आवेदन संरचना के बारे में सोचना है और एनीमेशन के साथ टुकड़े टुकड़े को बदलने से बचने की कोशिश करें। यदि आपको प्रतिस्थापित करने की आवश्यकता है, तो एनीमेशन का उपयोग न करें, और आप कोई एनीमेशन (प्रवेश और निकास दोनों सहित) जोड़ सकते हैं, लेकिन केवल जोड़ने के साथ।

संबंधित मुद्दे