टुकड़े को प्रतिस्थापित नहीं किया जा रहा है, लेकिन पिछले एक के ऊपर रखा गया है


104

गतिविधि:

FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();

Fragment1 fragment = new Fragment1();
Fragment2 fragment2 = new Fragment2();

transaction.replace(R.id.Fragment1, fragment);
transaction.addToBackStack(null);
transaction.commit();

FragmentTransaction transaction2 = getSupportFragmentManager().beginTransaction();
transaction2.replace(R.id.Fragment1, fragment2);
transaction2.addToBackStack(null);
transaction2.commit();

दृश्य में कोड:

<fragment
    android:id="@+id/Fragment1"
    android:name="com.landa.fragment.Fragment1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentBottom="true"
    android:layout_alignParentLeft="true"
    android:layout_below="@+id/include1" /> 

समस्या यह है कि सामग्री को वास्तव में प्रतिस्थापित नहीं किया जाता है - यह शीर्ष पर रखा जाता है (इसलिए यह ओवरलैप हो जाता है)।

जब मैं वापस क्लिक करता हूं, तो पहला टुकड़ा ठीक से दिखाया गया है (दूसरे के बिना), लेकिन शुरू में दोनों दिखाई दे रहे हैं (मैं चाहता हूं कि केवल आखिरी दिखाई दे)।

मुझे यहां क्या समझ नहीं आ रहा है?


मेरे मामले में समस्या इस तथ्य के कारण थी कि मैं कंटेनर दृश्य की उपयुक्त आईडी का उपयोग नहीं कर रहा था, अर्थात मैं सही containerViewId( replaceविधि में) पारित नहीं कर रहा था ।
nbro

जवाबों:


145

आप यहाँ दो काम कर रहे हैं:

  1. आप उस टुकड़े को प्रतिस्थापित नहीं कर सकते हैं, जो स्टेटिक रूप से xmlलेआउट फ़ाइल में रखा गया है । आपको FrameLayoutलेआउट में एक कंटेनर (जैसे ) बनाना चाहिए और फिर प्रोग्राम का उपयोग करके टुकड़े को जोड़ना चाहिए FragmentTransaction

  2. FragmentTransaction.replaceकंटेनर की आईडी की अपेक्षा करता है जिसमें टुकड़ा है और पहले पैरामीटर के रूप में टुकड़े की आईडी नहीं है। तो आपको पहले तर्क को उस कंटेनर की आईडी के रूप में पास करना चाहिए जिसे आपने पहले टुकड़े को जोड़ा था।

आप अधिक जानकारी के लिए इस लिंक का संदर्भ ले सकते हैं ।


17
FrameLayoutकंटेनर के रूप में उपयोग करने से बेहतर है LinearLayout
मार्सेल ब्रो

3
गतिविधि में एक खाली फ्रेमलैट का उपयोग करने से मेरी समस्या भी हल हो गई
सूक्ष्म फॉक्स

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

addTobackStack(..)पहली बार अपना लेनदेन करते समय @MasterScrat Omit करें । यह खाली फ्रेमलैट कंटेनर को बैक स्टैक पर रखने से बचना होगा। आप अभी भी अपने जोड़ने वाले टुकड़े पर वापस नेविगेट करने में सक्षम होंगे।
एलेक्स मयूर

यहाँ एक शानदार वीडियो है जो आपके स्पष्टीकरण को प्रदर्शित करता है। youtube.com/watch?v=EbcdMxAIr54
SQL और Java लर्नर

32

मुझे एक समान समस्या थी लेकिन मेरा मुद्दा यह था कि मैं दो अलग-अलग फ्रैगमेंट प्रबंधकों का उपयोग कर रहा था: एक से getSupportFragmentManager()और एक से getFragmentManager()। अगर मैंने SupportFragmentManagerउसके साथ एक टुकड़ा जोड़ा और फिर टुकड़े को बदलने की कोशिश की FragmentManager, तो टुकड़ा सिर्फ शीर्ष पर जुड़ जाएगा। मुझे कोड बदलने की आवश्यकता थी ताकि उसी FragmentManagerका उपयोग किया जाए और इस मुद्दे का ध्यान रखा जाए।


17

Android डेवलपर साइट FrameLayoutरन-टाइम पर गतिशील रूप से टुकड़ों को लोड करने का सुझाव देती है । आपने अपनी xml फ़ाइल में टुकड़े-टुकड़े को हार्ड-कोड किया है। इस लिंक में बताए अनुसार इसे रन-टाइम पर हटाया नहीं जा सकता है:

http://developer.android.com/training/basics/fragments/creating.html

यह लिंक दिखाता है कि अपने प्रोग्राम के माध्यम से टुकड़े कैसे जोड़ें:

http://developer.android.com/training/basics/fragments/fragment-ui.html


7

मुझे एक ही समस्या थी और मैंने सभी उत्तर देखे, लेकिन उनमें से किसी में भी मेरी गलती नहीं थी! वर्तमान टुकड़े को बदलने की कोशिश करने से पहले, मैं इस तरह कंटेनर गतिविधि के xml में डिफ़ॉल्ट टुकड़ा दिखा रहा था:

<FrameLayout
    android:id="@+id/fragment_frame_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <fragment
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:name="....ShopFragment"
        android:id="@+id/fragment"
        tools:layout="@layout/fragment_shop" />
</FrameLayout>

उसके बाद, हालांकि मैं गुजर रहा था FrameLayoutकरने के लिए fragmentTransaction.replace(), लेकिन मैं सटीक समस्या थी। यह पिछले एक के ऊपर दूसरा टुकड़ा दिखा रहा था।

समस्या को xml से हटाने और इसे onCreate()इस तरह से प्रोग्राम के शुरू होने पर डिफ़ॉल्ट पूर्वावलोकन के लिए कंटेनर गतिविधि की विधि में प्रोग्रामेटिक रूप से दिखाने से तय होती है :

    fragmentTransaction = getFragmentManager().beginTransaction();
    fragmentTransaction.replace(R.id.fragment_frame_layout,new ShopFragment());
    fragmentTransaction.addToBackStack(null);
    fragmentTransaction.commit();

और कंटेनर गतिविधि xml:

<FrameLayout
    android:id="@+id/fragment_frame_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

4

टुकड़ों को बदलने से पहले आप बैकस्टैक को साफ कर सकते हैं:

    FragmentManager fm = getActivity().getSupportFragmentManager();

    for (int i = 0; i < fm.getBackStackEntryCount(); i++) {
        fm.popBackStack();
    }

    // replace your fragments

समस्या यह है कि उसने अपनी xml लेआउट फ़ाइल में खंडन की घोषणा की है। इसलिए इसे रन-टाइम पर हटाया / बदला नहीं जा सकता।
पूनम एंथनी

इसने मेरे लिए काम किया, बैकस्टैक को साफ़ किए बिना एक टुकड़े को बदलने की कोशिश करना किसी अन्य टुकड़े के शीर्ष पर सबसे हाल के बैकस्टैक प्रविष्टि को छोड़ने के लिए लग रहा था।
स्पीडिनोमैड्स

3
<FrameLayout
    android:id="@+id/fragment_frame_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="?android:windowBackground">
//Add fragment here
</FrameLayout>

android:background="?android:windowBackground">उस कंटेनर में जोड़ें जिसमें आपका टुकड़ा रहता है। मेरे मामले में मैंने एक जोड़ा FrameLayout, जो मदद करना चाहिए।


1

टुकड़े का उपयोग करने के बजाय एक कंटेनर का उपयोग करें

<FrameLayout
        android:id="@+id/container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:text="Hello World!" />

अब मेनऐक्टिविटी में

if(condition)
    getFragmentManager().beginTransaction().replace(R.id.container,new FirstFragment()).commit();                    
else
    getFragmentManager().beginTransaction().replace(R.id.container, new SecondFragment()).commit();

कृपया ध्यान दें कि आपके खंड वर्ग को 'android.app.Fragment' आयात करना चाहिए, सुनिश्चित करें कि आप "support.v4" या "मूल" कार्यान्वयन का उपयोग करते हैं और उन्हें मिश्रण नहीं करते हैं। मुझे यह समस्या हो रही थी क्योंकि मैंने उन्हें मिलाया था।


0

मैं सपन दिवाकर के जवाब से सहमत हूं। लेकिन मुझे यह कैसे करना है पर एक वर्कअराउंड मिला है।

सबसे पहले, अपनी गतिविधि में (जैसे activity_main), जहां आपके पास सभी लेआउट हैं, एक जोड़ें FrameLayout। यह ऊंचाई और चौड़ाई होनी चाहिए match parent। इसके अलावा, यह एक दे id

अब, आपके टुकड़े में जो वर्तमान लेआउट, कॉल onPause()और को बदलने जा रहा है onResume()। प्रारंभिक सभी आंतरिक कंटेनरों में View। और उनके सेट visibilityकरने के लिए GONEमेंonResume() और VISIBLEमेंonPause()

ध्यान दें : नहीं FrameLayoutजो आप इस टुकड़े के साथ बदल रहे हैं।

मान लीजिए आपके पास ViewPager, TabLayout, ImageViewऔर एक कस्टम <fragment>में activity_main.xml। जोड़ें, FrameLayoutजैसा कि ऊपर उल्लेख किया गया है।

में abcFragment.java, में onClick()समारोह, जोड़ने addToBackstack(null)में transaction

उदाहरण कोड:

xyzFragment में, जो abcFragment को बदलने जा रहा है (और activity_main.xml में दिखाया गया है), ऐसा करें

@Override
    public void onResume() {
        super.onResume();

    // On resume, make everything in activity_main invisible except this fragment.
    slidingTabs = getActivity().findViewById(R.id.sliding_tabs);
    viewPager = getActivity().findViewById(R.id.pager);
    miniPlayerFragment = getActivity().findViewById(R.id.mini_pager);

    slidingTabs.setVisibility(View.GONE);
    viewPager.setVisibility(View.GONE);
    miniPlayerFragment.setVisibility(View.GONE);
}

@Override
public void onPause() {
    super.onPause();

    // Make everything visible again
    slidingTabs = getActivity().findViewById(R.id.sliding_tabs);
    viewPager = getActivity().findViewById(R.id.pager);
    miniPlayerFragment = getActivity().findViewById(R.id.mini_pager);

    slidingTabs.setVisibility(View.VISIBLE);
    viewPager.setVisibility(View.VISIBLE);
    miniPlayerFragment.setVisibility(View.VISIBLE);
}

हैप्पी कोडिंग!


0

आप अतिव्यापी समस्या को ठीक करने के लिए FragmentTransaction से सेटट्रांसिशन विधि का उपयोग कर सकते हैं।

transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);

0

Oncreate () में

  BaseFragmentloginpage fragment = new BaseFragmentloginpage();
            android.support.v4.app.FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
            fragmentTransaction.replace(R.id.frame, fragment);
            fragmentTransaction.isAddToBackStackAllowed();
            fragmentTransaction.commit();

अब यह हमेशा आपका डिफ़ॉल्ट टुकड़ा होगा ... यदि आप xml लेआउट में टुकड़ा जोड़ते हैं तो यह हमेशा ओवरलैप होगा, इसलिए रन समय पर टुकड़े के साथ प्रारंभिक सामग्री सेट करें


0

मैं इस समस्या को हल करने के बाद एक ही समस्या थी

  1. फ्रेम लेआउट ले लो जहां यू उर टुकड़ा की जगह ले रहे हैं

    <FrameLayout
                    android:id="@+id/fragment_place"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent" />
  2. और प्रतिस्थापन के लिए कोड

    public void selectFrag(View view) {
    Fragment fr;
    
      if(view == findViewById(R.id.button2))
    {
         fr = new FragmentTwo();
    
     }else {
         fr = new FragmentOne();
     }
     FragmentManager fm = getFragmentManager();
     FragmentTransaction fragmentTransaction = fm.beginTransaction();
     fragmentTransaction.replace(R.id.fragment_place, fr);
     fragmentTransaction.commit();

अगर आप पूरा उदाहरण चाहते हैं तो मैं आपको सिर्फ टिप्पणी भेजूंगा ......


0

मेरे पास भी यही मुद्दा था, लेकिन यह इसलिए था क्योंकि मैंने उस खंड के पृष्ठभूमि का रंग नहीं बदला था जिसे मैं अपने फ्रैमेलआउट के लिए जोड़ रहा था।

ऐसा करने की कोशिश करो, के साथ layout_heightऔर layout_widthसेट करने के लिएmatch_parent


0

मुझे एक बार यह समस्या हुई और पता चला कि ऐसा इसलिए हुआ क्योंकि मैंने गलती से उस android:backgroundविशेषता को हटा दिया था जो आपके xml कोड पर गायब है। मेरा मानना ​​है कि यह तब काम करता है जब आप एक दीवार को पेंट कर रहे हैं, android:backgroundवह रंग है जो दीवार होगी और अन्य दृश्य उस आधार रंग के शीर्ष पर रखे गए हैं। जब आप दीवार को अपने विचारों को रखने से पहले पेंट नहीं करते हैं तो वे उस दीवार में पहले से ही मौजूद होंगे, जो आपके मामले में, आपके अन्य टुकड़े में। नहीं पता है कि अगर आप हालांकि, अच्छी किस्मत में मदद मिलेगी।


0

मैंने सभी मामलों के ऊपर प्रयास किया है और समस्या को ठीक करने का प्रयास किया है लेकिन फिर भी समाधान नहीं हुआ है। मुझे नहीं पता कि इसका काम मेरे लिए क्यों नहीं है। मैं उपरोक्त उत्तरों से सहमत हूं क्योंकि बहुत से इससे सहमत हैं।

मैं सिर्फ जवाब दे रहा हूं और नीचे वह तरीका है जो मेरे लिए काम कर रहा है।

मैंने फ़ाइल android:clickable="true"पर शीर्ष पैरेंट लेआउट में यह गुण जोड़ा है fragment.xml

मुझे उम्मीद है कि किसी को मदद मिलेगी।


0

सपन दिवाकर और अन्य को धन्यवाद। इस जवाब से मुझे मदद मिली। मैंने बस इसके अंदर एक टुकड़े के बिना एक RelativeLayout बनाया, एक मूल या समूह दृश्य के रूप में RelativeLayout का उपयोग किया, उस समूह दृश्य को लेनदेन में बदलने के लिए निर्दिष्ट किया, और यह काम किया।

कोड:

getSupportFragmentManager().beginTransaction()
                            .replace(R.id.content_group_view, itemDetailFragment).commit();

एक्सएमएल:

 <RelativeLayout
         android:id="@+id/content_group_view"
         android:layout_width="match_parent"
         android:layout_height="match_parent">

 </RelativeLayout>

0

अपने फ़्रेम लेआउट आईडी की जाँच करें और इसे नीचे की तरह बदलें

fragmentTransactionChange = MainActivity.this.getSupportFragmentManager().beginTransaction();
fragmentTransactionChange.replace(R.id.progileframe, changeFragment);
fragmentTransactionChange.addToBackStack(null);
fragmentTransactionChange.commit();
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.