दृश्यदर्शी में वर्तमान फ़्रैगमेंट उदाहरण प्राप्त करना


210

नीचे मेरा कोड है जिस पर 3 Fragment classesप्रत्येक 3 टैब के साथ एम्बेडेड है ViewPager। मेरे पास एक मेनू विकल्प है। जैसा कि दिखाया गया है onOptionsItemSelected(), एक विकल्प का चयन करके, मुझे वर्तमान में दिखाई देने वाले टुकड़े को अपडेट करने की आवश्यकता है। यह अद्यतन करने के लिए कि मुझे एक विधि को कॉल करना है जो कि खंड वर्ग में है। क्या कोई सुझाव दे सकता है कि उस पद्धति को कैसे कॉल करें?

public class MainActivity  extends ActionBarActivity {

     ViewPager ViewPager;
     TabsAdapter TabsAdapter;

     @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);

            ViewPager = new ViewPager(this);
            ViewPager.setId(R.id.pager);
            setContentView(ViewPager);

            final ActionBar bar = getSupportActionBar();

            bar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);

            //Attaching the Tabs to the fragment classes and setting the tab title.
            TabsAdapter = new TabsAdapter(this, ViewPager);
            TabsAdapter.addTab(bar.newTab().setText("FragmentClass1"),
                    FragmentClass1.class, null);
            TabsAdapter.addTab(bar.newTab().setText("FragmentClass2"),
              FragmentClass2.class, null);
            TabsAdapter.addTab(bar.newTab().setText("FragmentClass3"),
              FragmentClass3.class, null);


            if (savedInstanceState != null) {
                bar.setSelectedNavigationItem(savedInstanceState.getInt("tab", 0));
            }

        }

        @Override
        public boolean onOptionsItemSelected(MenuItem item) {

            switch (item.getItemId()) {

            case R.id.addText:

           **// Here I need to call the method which exists in the currently visible Fragment class**

                    return true;

            }

            return super.onOptionsItemSelected(item);
        }


     @Override
     protected void onSaveInstanceState(Bundle outState) {
      super.onSaveInstanceState(outState);
            outState.putInt("tab", getSupportActionBar().getSelectedNavigationIndex());

     }

     public static class TabsAdapter extends FragmentPagerAdapter
      implements ActionBar.TabListener, ViewPager.OnPageChangeListener {

      private final Context mContext;
            private final ActionBar mActionBar;
            private final ViewPager mViewPager;
            private final ArrayList<TabInfo> mTabs = new ArrayList<TabInfo>();

            static final class TabInfo {
                private final Class<?> clss;
                private final Bundle args;

                TabInfo(Class<?> _class, Bundle _args) {
                    clss = _class;
                    args = _args;
                }
            }

      public TabsAdapter(ActionBarActivity activity, ViewPager pager) {
       super(activity.getSupportFragmentManager());
                mContext = activity;
                mActionBar = activity.getSupportActionBar();
                mViewPager = pager;
                mViewPager.setAdapter(this);
                mViewPager.setOnPageChangeListener(this);
            }

      public void addTab(ActionBar.Tab tab, Class<?> clss, Bundle args) {
                TabInfo info = new TabInfo(clss, args);
                tab.setTag(info);
                tab.setTabListener(this);
                mTabs.add(info);
                mActionBar.addTab(tab);
                notifyDataSetChanged();

            }

      @Override
      public void onPageScrollStateChanged(int state) {
       // TODO Auto-generated method stub

      }

      @Override
      public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
       // TODO Auto-generated method stub

      }

      @Override
      public void onPageSelected(int position) {
       // TODO Auto-generated method stub
       mActionBar.setSelectedNavigationItem(position);
      }

      @Override
      public void onTabReselected(Tab tab, FragmentTransaction ft) {
       // TODO Auto-generated method stub

      }

      @Override
      public void onTabSelected(Tab tab, FragmentTransaction ft) {
       Object tag = tab.getTag();
                for (int i=0; i<mTabs.size(); i++) {
                    if (mTabs.get(i) == tag) {
                        mViewPager.setCurrentItem(i);

                    }
                }

                tabPosition = tab.getPosition();
      }

      @Override
      public void onTabUnselected(Tab tab, FragmentTransaction ft) {
       // TODO Auto-generated method stub

      }

      @Override
      public Fragment getItem(int position) {
       TabInfo info = mTabs.get(position);
                return Fragment.instantiate(mContext, info.clss.getName(), info.args);
      }

      @Override
      public int getCount() {
       return mTabs.size();
      }

     }

    }

मान लीजिए कि updateList()मैं जिस विधि से कॉल करना चाहता हूं , उसका टुकड़ा वर्ग है :

 public class FragmentClass1{

    ArrayList<String> originalData;


    @Override
         public View onCreateView(LayoutInflater inflater, ViewGroup container,
           Bundle savedInstanceState) {

          View fragmentView = inflater.inflate(R.layout.frag1, container, false);

          originalData = getOriginalDataFromDB();

          return fragmentView;

         }


    public void updateList(String text)
    {
       originalData.add(text);
       //Here I could do other UI part that need to added
    }
}

आप किस विधि से खंडन करना चाहते हैं?
बिराज झालवदिया

@ बिराजजलवडिया मेरी स्वयं की परिभाषित पद्धति है, जिसमें इसका एक पैरामीटर है और यह उस खंड वर्ग के उदाहरण चर का उपयोग करता है जो पहले से ही एक दृश्य बनाते समय भी आरंभीकृत किया गया है।
रिक

1
क्या आप अपने अंशों के वर्ग का नाम दे सकते हैं जो दृश्यदर्शी में हैं?
बिराज जालवदिया


दृश्य अंशों तक पहुंचने का सबसे सरल तरीका stackoverflow.com/questions/7379165/… के माध्यम से होगा , शीर्ष दो उत्तरों को देखें।
लक्सप्रोग

जवाबों:


205

एक विकल्प का चयन करके, मुझे वर्तमान में दिखाई देने वाले टुकड़े को अपडेट करना होगा।

इसे करने का एक सरल तरीका FragmentPagerAdapterकार्यान्वयन से संबंधित एक चाल है:

case R.id.addText:
     Fragment page = getSupportFragmentManager().findFragmentByTag("android:switcher:" + R.id.pager + ":" + ViewPager.getCurrentItem());
     // based on the current position you can then cast the page to the correct 
     // class and call the method:
     if (ViewPager.getCurrentItem() == 0 && page != null) {
          ((FragmentClass1)page).updateList("new item");     
     } 
return true;

कृपया अपने चर नामकरण सम्मेलन को पुनर्विचार करें, चर नाम के रूप में वर्ग का नाम बहुत भ्रामक है (इसलिए नहीं ViewPager ViewPager, ViewPager mPagerउदाहरण के लिए उपयोग करें )।


23
अगर एपीआई बदलता है, तो क्या यह टुकड़ा टैग भविष्य का सबूत है?
मार्टन २

7
@Maarten नहीं, यह सिर्फ एक सामान्य हैक है जिसका उपयोग एडेप्टर दिखाई देने के बाद से किया गया है (और इसका स्रोत कोड उपलब्ध था), यह अभी तक नहीं बदला है। यदि आप कुछ और अधिक विश्वसनीय चाहते हैं, तो आपको अन्य विकल्पों का उपयोग करने की आवश्यकता होगी, सबसे उल्लेखनीय instantiateItem()विधि को ओवरराइड करना और अपने आप को उचित टुकड़ों के संदर्भ में प्राप्त करना है।
लुक्सप्रोग

5
घंटों की हताशा और सीधे पेजों से पूछने के बाद mAdapter.getItem(position), भयानक ... कम से कम अब मुझे पता है कि अन्य 8512 परीक्षणों ने काम नहीं किया। धन्यवाद
Diolor

29
ध्यान दें कि यह काम नहीं करता है यदि आप FragmentStatePagerAdapter के बजाय FragmentPagerAdapter का उपयोग करते हैं।
शॉन लौजोन

3
@ShawnLauzon FragmentStatePagerAdapter का एक अलग कार्यान्वयन है, इस मामले में आप दृश्य अंशों को प्राप्त करने के लिए इसके इंस्टेंटइमटम () विधि को कहते हैं।
लुक्सप्रॉग

155
    public class MyPagerAdapter extends FragmentPagerAdapter {
        private Fragment mCurrentFragment;

        public Fragment getCurrentFragment() {
            return mCurrentFragment;
        }
//...    
        @Override
        public void setPrimaryItem(ViewGroup container, int position, Object object) {
            if (getCurrentFragment() != object) {
                mCurrentFragment = ((Fragment) object);
            }
            super.setPrimaryItem(container, position, object);
        }
    }

28
Google को FragmentPageAdapter.getCurrentPrimaryItem () रिटर्निंग mCurrentPrimaryItem प्रदान करना चाहिए।
यूजीन

1
मैं इस तकनीक का प्रयोग के रूप में है.मैं भी तरीकों के साथ एक PagerFragment परिभाषित onPageSelected/ onPageDeselectedऔर सब मेरी पेजर टुकड़े यह विस्तार। तब setPrimaryitemइन तरीकों को उचित रूप से कॉल कर सकते हैं जब उपयोगकर्ता एक नए पृष्ठ पर स्वाइप करता है। इसका मतलब है कि आप उन पृष्ठों में डेटा लोड करने के लिए एक लेज़ियर रणनीति को लागू कर सकते हैं जो दिखाए भी नहीं गए हैं। हालाँकि आपको यह ध्यान में रखना चाहिए कि पृष्ठ परिवर्तन के दौरान यह बेहतर लगता है यदि अगला पृष्ठ पहले से ही डेटा से आबाद है, इसलिए आलसी लोडिंग सभी डेटा onPageSelectedआदर्श नहीं हो सकते हैं।
JHH

3
ifबयान क्यों ? टुकड़ा बस equalsवस्तु की विधि को कहते हैं , जो उथले तुलना है। तो हमेशा फोन क्यों नहीं करते mCurrentFragment = ((Fragment) object);?
ओवरक्लोवर

कोशिश की और यह ठीक काम करता है, बस getCurrentFragment () को विशिष्ट फ्रैगमेंट में
डालना

113

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

@Override
public Fragment getItem(int index) {
    Fragment myFragment = MyFragment.newInstance();
    mPageReferenceMap.put(index, myFragment);
    return myFragment;
}

"निष्क्रिय" खंड पृष्ठों के संदर्भ को रखने से बचने के लिए, आपको FragmentStatePagerAdapter के विध्वंस (...) विधि को लागू करने की आवश्यकता है:

@Override
public void destroyItem (ViewGroup container, int position, Object object) {
    super.destroyItem(container, position, object);
    mPageReferenceMap.remove(position);
}

और जब आपको वर्तमान में दिखाई देने वाले पृष्ठ तक पहुंचने की आवश्यकता हो, तो आप कॉल करें:

int index = mViewPager.getCurrentItem();
MyAdapter adapter = ((MyAdapter)mViewPager.getAdapter());
MyFragment fragment = adapter.getFragment(index);

जहाँ MyAdapter की getFragment (int) विधि इस तरह दिखती है:

public MyFragment getFragment(int key) {
    return mPageReferenceMap.get(key);
}

आशा है कि यह मदद कर सकता है!


क्या आप स्पष्ट रूप से बता सकते हैं? मुझे अपने कोड में इस FragmentStatePagerAdapter वर्ग को रखने की आवश्यकता कहां है? BTW मैं 3 टुकड़े वर्गों, नहीं MyFragmentClass है।
रिक

7
इससे भी बेहतर अगर आप getItem के बजाय InstantPItem में mPageReferenceMap अपडेट करें क्योंकि यह ओरिएंटेशन चेंज के बाद भी काम करता है। '@ ऑवरराइड पब्लिक ऑब्जेक्ट इंस्टेंटइइट इट (व्यूग्रुप कंटेनर, इंट पोजिशन) {फ्रैगमेंट फ्रैमेंट = (फ्रैगमेंट) Super.instantiateItem (कंटेनर, पोजिशन); mPageReferenceMap.put (स्थिति, टुकड़ा); टुकड़ा लौटना; } '
pmellaaho

MPageReferenceMap किस प्रकार का है?
डोरुआ एड्रियन

10
यह उत्तर वास्तव में बुरा है! जब तक यह स्वयं इसे संभाल नहीं लेता तब तक आपको व्यूपेजर का कैश मैन्युअल रूप से नहीं रखना चाहिए। ViewPager तय करता है कि टुकड़ा कब आवंटित किया जाना चाहिए या नहीं, क्या रोकना है और कब, हर टुकड़े पर एक संदर्भ रखने से कुछ बेकार ओवरहेड जुड़ जाएगा और मेमोरी के लिए अनुकूलित नहीं है।
Livio

3
मैंने इस दृष्टिकोण की कोशिश की, लेकिन दुर्भाग्य से यह काम नहीं करता है जब गतिविधि फिर से बनाई जाती है। एंड्रॉइड एन और बाद में, आप मल्टीविंडो सुविधा का उपयोग करते समय इसे देख सकते हैं। जब आपका ऐप खुला हो, तो 'recents' बटन को दबाए रखें (वर्ग एक)। गतिविधि और खंड सहेजे गए हैं। InstanceState, एडेप्टर को फिर से बनाया गया है (इसलिए mPageReferenceMap अब खाली है), लेकिन getItem को फिर से नहीं बुलाया जाता है। नक्शा खाली रहता है ताकि एडॉप्टर .getFragment (इंडेक्स) क्रैश हो जाए।
मार्टिन कोनिसक

102

यह एकमात्र तरीका है जो मुझे उस विशेष खंड वर्गों के उदाहरण चर के लिए NullPointerException नहीं मिलता है। यह उन लोगों के लिए मददगार हो सकता है जो एक ही चीज में फंस गए हैं। OnOptionsItemSelected () में, मैंने नीचे का तरीका कोडित किया है:

if(viewPager.getCurrentItem() == 0) {
    FragmentClass1 frag1 = (FragmentClass1)viewPager
                            .getAdapter()
                            .instantiateItem(viewPager, viewPager.getCurrentItem());
    frag1.updateList(text); 
} else if(viewPager.getCurrentItem() == 1) {
    FragmentClass2 frag2 = (FragRecentApps)viewPager
                            .getAdapter()
                            .instantiateItem(viewPager, viewPager.getCurrentItem());
    frag2.updateList(text);
}

3
मुझे लगता है कि यह सबसे सही उत्तर है - FragmentStatePagerAdapterकिसी भी कोड को ओवरराइड किए बिना डिजाइन के साथ संरेखित करें । वास्तव में, यह एक फ़ंक्शन के रूप में सरल होना चाहिए जो केवल वापस लौटाता है viewPager.getAdapter().instantiateItem(viewPager, viewPager.getCurrentItem())
जॉन पेंग

39

FragmentStatePagerAdapter के पास सार्वजनिक विधि है जिसका नाम InstantiateItem है जो निर्दिष्ट पैरामीटर मानों के आधार पर आपके टुकड़े को लौटाता है, इस विधि में दो पैरामीटर ViewGroup (ViewPager) और स्थिति है।

public Object instantiateItem(ViewGroup container, int position);

निर्दिष्ट स्थिति के टुकड़े प्राप्त करने के लिए इस विधि का उपयोग किया,

Fragment fragment = (Fragment) adaper.instantiateItem(mViewPager, position);

5
लेकिन यह वर्तमान में पहले से ही खंडित टुकड़े को वापस नहीं करता है, लेकिन इसके बजाय एक नया एक, नहीं? इस प्रकार नाम "इन्स्टैंटेज" ...
Ixx

1
@ XXX यह कोई नया टुकड़ा नहीं बनाता है। मुझे लगता है कि यहां विधि नाम गलत है।
बग्स हैपन

15

मुझे इसकी बहुत देर हो चुकी है, लेकिन मेरे पास इसे करने के सरल तरीके हैं,

// 0 कब्जे पर टुकड़ा करने के लिए

((mFragment) viewPager.getAdapter().instantiateItem(viewPager, 0)).yourMethod();

10

यहां बहुत सारे उत्तर हैं जो वास्तव में मूल तथ्य को संबोधित नहीं करते हैं जो कि वास्तव में ऐसा करने के लिए कोई रास्ता नहीं है, और इस तरह से कि आप भविष्य में किसी बिंदु पर खुद को पैर में गोली नहीं मारते हैं।

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

केवल एक चीज के बारे में जो मैं काम करने में सक्षम हूं, कोड की प्रतिलिपि बना रहा है FragmentStatePagerAdapterऔर एक विधि जोड़ रहा है जो टुकड़े को लौटाता है, एक स्थिति दी गई है ( mFragments.get(pos))। ध्यान दें कि यह विधि मानती है कि टुकड़ा वास्तव में उपलब्ध है (अर्थात यह किसी बिंदु पर दिखाई दे रहा था)।

यदि आप विशेष रूप से साहसी हैं, तो आप निजी mFragmentsसूची के तत्वों का उपयोग करने के लिए प्रतिबिंब का उपयोग कर सकते हैं , लेकिन फिर हम एक वर्ग में वापस आ गए हैं (सूची का नाम समान रहने की गारंटी नहीं है)।


1
"जब राज्य को बचाया / बहाल किया जाता है तो अच्छी तरह से काम नहीं करता है" से निपटने के लिए, मैं saveState () विधि को ओवरराइड करता हूं। ताकि गतिविधि रुकने पर पेजर किसी भी टुकड़े को न बचाए। यह काम करता हैं।
एंटोनीप

2
यह सिर्फ अंतर्निहित मुद्दे को ठीक किए बिना, पैचवर्क में जोड़ता है। मैं तर्क नहीं दे रहा हूं कि यह काम नहीं करता है - बस यह एक अच्छा कार्यान्वयन नहीं है।
मेल्लवार

8
getSupportFragmentManager().getFragments().get(viewPager.getCurrentItem());

उदाहरण के लिए ऊपर की रेखा से उस टुकड़े तक ले जाएं, जिस टुकड़े के साथ आप काम करना चाहते हैं। पूरी तरह से ठीक काम करता है।

viewPager

टुकड़े को प्रबंधित करने वाला पेजर उदाहरण है।


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

@progNewbie हाँ जिसे अतिरिक्त वर्कअराउंड कोड की आवश्यकता होगी।
गौरव पंगम

नीचे दिए गए @progNewbie एवगेनी का जवाब मुझे लगता है कि स्थिति को संभाल
लेगा

7

एक विकल्प का चयन करके, मुझे वर्तमान में दिखाई देने वाले टुकड़े को अपडेट करना होगा।

वर्तमान में दृश्यमान टुकड़ा के लिए एक संदर्भ पाने के लिए, मान लें कि आपके लिए एक संदर्भ है ViewPagerके रूप में mPager। फिर निम्न चरणों का संदर्भ मिलेगा currentFragment:

  1. PageAdapter adapter = mPager.getAdapter();
  2. int fragmentIndex = mPager.getCurrentItem();
  3. FragmentStatePagerAdapter fspa = (FragmentStatePagerAdapter)adapter;
  4. Fragment currentFragment = fspa.getItem(fragmentIndex);

केवल कास्ट यूज्ड लाइन 3 आमतौर पर मान्य है। FragmentStatePagerAdapterएक ViewPager के लिए एक उपयोगी एडाप्टर है।


7

इसे करने का सबसे अच्छा तरीका है, बस कॉलिंगग्रैगमेंटनैम फ्रेगमेंट = (कॉलिंगफ्रैगमेंटनाम) viewPager .getAdapter () .instantiateItem (viewPager, viewPager.getCurrentItem ()); यह आपके कॉलिंग फ़्रैगमेंट को फिर से इंस्टेंट कर देगा, ताकि यह शून्य पॉइंटर अपवाद को न फेंके और उस टुकड़े के किसी भी तरीके को कॉल न कर सके।


6

वर्तमान टुकड़ा:

यह तब काम करता है जब आपने खंड टैब्बर टेम्प्लेट के साथ एक प्रोजेक्ट बनाया था।

Fragment f = mSectionsPagerAdapter.getItem(mViewPager.getCurrentItem());

ध्यान दें कि यह डिफ़ॉल्ट वर्जित गतिविधि टेम्पलेट कार्यान्वयन के साथ काम करता है।


30
यह getItem () के आपके कार्यान्वयन पर निर्भर करता है - यह खंड के एक नए उदाहरण को वापस कर सकता है, जो कि शायद आप क्या चाहते हैं।
टॉम

यह आप कैसे करते हैं। यदि आपके पास अभी भी डिफ़ॉल्ट कॉन्फ़िगरेशन है जब आप टुकड़े परियोजना के साथ एक टैबोर बनाते हैं। इसका कोई हल नहीं था। इसलिए मुझे लगा कि इससे मदद मिलेगी।
हसन

3

मैंने निम्नलिखित का उपयोग किया है:

 int index = vpPager.getCurrentItem();
 MyPagerAdapter adapter = ((MyPagerAdapter)vpPager.getAdapter());
 MyFragment suraVersesFragment = (MyFragment)adapter.getRegisteredFragment(index);

1
यह यहाँ पाए गए उत्तर से एक कस्टम पेजर कार्यान्वयन पर निर्भर करता है: stackoverflow.com/questions/8785221/…
टॉम रेडमैन

1
यह वही है जो मैं करने की कोशिश कर रहा था, लेकिन यह जानने के बिना कि कौन से तरीकों को ओवरराइड करना है, घंटों बर्बाद होगा - धन्यवाद!
ब्रॉन डेविस

2

FragmentStatePagerAdapterएक निजी उदाहरण चर है जिसे mCurrentPrimaryItemप्रकार कहा जाता है Fragment। केवल एक ही आश्चर्य हो सकता है कि एंड्रॉइड देवियों ने इसे एक गटर से क्यों नहीं आपूर्ति की। यह चर setPrimaryItem()विधि में त्वरित है । तो, इस चर को इस तरह से ओवरराइड करें कि आप इस चर का संदर्भ प्राप्त कर सकें। मैं बस अपनी खुद की घोषणा करने mCurrentPrimaryItemऔर setPrimaryItem()अपने ओवरराइड की सामग्री की नकल करने के साथ समाप्त हुआ ।

आपके कार्यान्वयन में FragmentStatePagerAdapter:

private Fragment mCurrentPrimaryItem = null;

@Override
public void setPrimaryItem(ViewGroup container, int position, Object object) {
    Fragment fragment = (Fragment)object;
    if (fragment != mCurrentPrimaryItem) {
        if (mCurrentPrimaryItem != null) {
            mCurrentPrimaryItem.setMenuVisibility(false);
            mCurrentPrimaryItem.setUserVisibleHint(false);
        }
        if (fragment != null) {
            fragment.setMenuVisibility(true);
            fragment.setUserVisibleHint(true);
        }
        mCurrentPrimaryItem = fragment;
    }
}

public TasksListFragment getCurrentFragment() {
    return (YourFragment) mCurrentPrimaryItem;
}

2

आप परिभाषित कर सकते हैं PagerAdapterइस तरह तो आप किसी भी प्राप्त करने में सक्षम हो जाएगा Fragmentमें ViewPager

private class PagerAdapter extends FragmentPagerAdapter {
    private final List<Fragment> mFragmentList = new ArrayList<>();

    public PagerAdapter(FragmentManager fm) {
        super(fm);
    }

    @Override
    public Fragment getItem(int position) {
        return mFragmentList.get(position);
    }

    @Override
    public int getCount() {
        return mFragmentList.size();
    }

    public void addFragment(Fragment fragment) {
        mFragmentList.add(fragment);
    }
}

करंट पाने के लिए Fragment

Fragment currentFragment = mPagerAdapter.getItem(mViewPager.getCurrentItem());

2

जब हम viewPager का उपयोग करते हैं, तो गतिविधि में टुकड़े के उदाहरण तक पहुंचने का एक अच्छा तरीका तत्काल है। (viewpager, index)। // इंडेक्स- जिस खंड का आप उदाहरण चाहते हैं।

उदाहरण के लिए मैं 1 इंडेक्स के टुकड़े उदाहरण तक पहुँच रहा हूँ-

Fragment fragment = (Fragment) viewPageradapter.instantiateItem(viewPager, 1);

if (fragment != null && fragment instanceof MyFragment) {      
 ((MyFragment) fragment).callYourFunction();

}

1

मेरे पास एक ही मुद्दा था और इस कोड का उपयोग करके इसे हल किया।

MyFragment fragment = (MyFragment) thisActivity.getFragmentManager().findFragmentById(R.id.container);

बस अपने टुकड़े के नाम के साथ MyFragment नाम बदलें और अपने टुकड़े कंटेनर की आईडी जोड़ें।


1

यह स्वीकृत उत्तर की तुलना में अधिक भविष्य का प्रमाण है:

public class MyFragmentPagerAdapter extends FragmentPagerAdapter {

    /* ------------------------------------------------------------------------------------------ */
    // region Private attributes :

    private Context _context;
    private FragmentManager _fragmentManager;
    private Map<Integer, String> _fragmentsTags = new HashMap<>();

    // endregion
    /* ------------------------------------------------------------------------------------------ */



    /* ------------------------------------------------------------------------------------------ */
    // region Constructor :

    public MyFragmentPagerAdapter(Context context, FragmentManager fragmentManager) {

        super(fragmentManager);

        _context = context;
        _fragmentManager = fragmentManager;
    }

    // endregion
    /* ------------------------------------------------------------------------------------------ */



    /* ------------------------------------------------------------------------------------------ */
    // region FragmentPagerAdapter methods :

    @Override
    public int getCount() { return 2; }

    @Override
    public Fragment getItem(int position) {

        if(_fragmentsTags.containsKey(position)) {

            return _fragmentManager.findFragmentByTag(_fragmentsTags.get(position));
        }
        else {

            switch (position) {

                case 0 : { return Fragment.instantiate(_context, Tab1Fragment.class.getName()); }
                case 1 : { return Fragment.instantiate(_context, Tab2Fragment.class.getName()); }
            }
        }

        return null;
    }

    @Override
    public Object instantiateItem(ViewGroup container, int position) {

        // Instantiate the fragment and get its tag :
        Fragment result = (Fragment) super.instantiateItem(container, position);
        _fragmentsTags.put(position, result.getTag());

        return result;
    }

    // endregion
    /* ------------------------------------------------------------------------------------------ */
}

आपको इसके बजाय WeakHashMap का उपयोग करना चाहिए।
प्रकाश नादर

1

प्रश्न में परिदृश्य बेहतर है कि प्रत्येक फ्रैगमेंट द्वारा अपने स्वयं के मेनू आइटम को जोड़कर और आधिकारिक दस्तावेजों में वर्णित सीधे onOptionsItemSelected () से निपटने के लिए सेवा की जाती है । अनचाही चाल से बचना बेहतर है।


यह उत्तर वास्तव में ऐसा करने के लिए अधिक विवरण का उपयोग कर सकता है। मेनू आइटम को जोड़ने से ViewPagerसमस्या कैसे हल होती है?
सुरगाछ

@Suragch ViewPager समस्या मौजूद है यदि मेनू ईवेंट्स को गतिविधि के भीतर संभाला जाता है जो टुकड़ों को होस्ट करता है और मौजूद नहीं है यदि इवेंट्स को केवल टुकड़े के भीतर संभाला जाता है। लिंक दिखाता है कि एक टुकड़ा अपने मेनू आइटम को कैसे जोड़ सकता है।
Y2i

1

सभी टिप्पणियों और उत्तरों को पढ़ने के बाद मैं इस समस्या के लिए एक इष्टतम समाधान बताने जा रहा हूं। सबसे अच्छा विकल्प @ रिक का समाधान है, इसलिए मेरा सुधार उसके आधार पर है।

इसके बजाय प्रत्येक FragmentClass की तरह पूछने के लिए

if(FragmentClass1){
   ...
if(FragmentClass2){
   ...
}

अपना खुद का इंटरफ़ेस बनाएं, और निर्माता आपके बच्चे के टुकड़े को इसे लागू करते हैं, कुछ ऐसा

public interface MyChildFragment {
    void updateView(int position);
}

फिर, आप अपने आंतरिक अंशों को आरंभ करने और अद्यतन करने के लिए कुछ ऐसा कर सकते हैं।

Fragment childFragment = (Fragment) mViewPagerDetailsAdapter.instantiateItem(mViewPager,mViewPager.getCurrentItem());

if (childFragment != null) {
   ((MyChildFragment) childFragment).updateView();
}

PS सावधान रहें कि आप उस कोड को कहाँ रखते हैं, यदि आप सिस्टम में वास्तव में इसे बनाने से पहले insatiateItem को कॉल करते हैं, तो यह savedInstanceStateआपके बच्चे के टुकड़े का बना देगा

public void onCreate(@Nullable Bundle savedInstanceState){
      super(savedInstanceState)
}

आपके ऐप को क्रैश कर देगा।

सौभाग्य


1

उन्होंने जो जवाब दिया, उसके आधार पर उन्होंने बताया:

"जब हम viewPager का उपयोग करते हैं, तो गतिविधि में फ्रैगमेंट इंस्टेंस तक पहुंचने का एक अच्छा तरीका तत्काल है। (viewpp, index)। // इंडेक्स- उस टुकड़े का इंडेक्स जिसमें से आप उदाहरण चाहते हैं।"

अगर आप कोटलिन में ऐसा करना चाहते हैं

val fragment =  mv_viewpager.adapter!!.instantiateItem(mv_viewpager, 0) as Fragment
                if ( fragment is YourFragmentFragment)
                 {
                    //DO somthign 
                 }

0 से 0 का टुकड़ा उदाहरण के लिए

// ================================================ ========================= // // #################### ######## ############################# // // = का उपयोग करता है। ================================================== ===================== //

यहाँ के बारे में एक अकेला दृष्टि पाने के लिए एक पूर्ण उदाहरण है

यहाँ .xml फ़ाइल में मेरा veiewPager है

   ...
    <android.support.v4.view.ViewPager
                android:id="@+id/mv_viewpager"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_margin="5dp"/>
    ...

और घर गतिविधि जहां मैं टैब सम्मिलित करता हूं

...
import kotlinx.android.synthetic.main.movie_tab.*

class HomeActivity : AppCompatActivity() {

    lateinit var  adapter:HomeTabPagerAdapter

    override fun onCreate(savedInstanceState: Bundle?) {
       ...
    }



    override fun onCreateOptionsMenu(menu: Menu) :Boolean{
            ...

        mSearchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
          ...

            override fun onQueryTextChange(newText: String): Boolean {

                if (mv_viewpager.currentItem  ==0)
                {
                    val fragment =  mv_viewpager.adapter!!.instantiateItem(mv_viewpager, 0) as Fragment
                    if ( fragment is ListMoviesFragment)
                        fragment.onQueryTextChange(newText)
                }
                else
                {
                    val fragment =  mv_viewpager.adapter!!.instantiateItem(mv_viewpager, 1) as Fragment
                    if ( fragment is ListShowFragment)
                        fragment.onQueryTextChange(newText)
                }
                return true
            }
        })
        return super.onCreateOptionsMenu(menu)
    }
        ...

}

1

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

मैं instantiateItem(...)वर्तमान फ्रैगमेंट प्राप्त करने के लिए विधि का उपयोग करता हूं :

val currentFragment = adapter?.instantiateItem(viewPager, viewPager.currentItem)

या स्थिति पर किसी भी अन्य टुकड़ा पाने के लिए:

val position = 0
val myFirstFragment: MyFragment? = (adapter?.instantiateItem(viewPager, position) as? MyFragment)

से प्रलेखन :

दिए गए पद के लिए पृष्ठ बनाएँ। एडेप्टर यहाँ दिए गए कंटेनर में दृश्य जोड़ने के लिए ज़िम्मेदार है, हालांकि यह केवल यह सुनिश्चित करना चाहिए कि यह उस समय तक किया जाता है जब वह फिनिशपैड (व्यूग्रुप) से लौटता है।


0

मेरी गतिविधि में मेरे पास है:

int currentPage = 0;//start at the first tab
private SparseArray<Fragment> fragments;//list off fragments
viewPager.setOnPageChangeListener(new OnPageChangeListener() {

@Override
public void onPageSelected(int pos) {
        currentPage = pos;//update current page
}

@Override
public void onPageScrolled(int arg0, float arg1, int arg2) {}
@Override
public void onPageScrollStateChanged(int arg0) {}
});



@Override
public void onAttachFragment(Fragment fragment) {
    super.onAttachFragment(fragment);
    if(fragment instanceof Fragment1)
        fragments.put(0, fragment);
    if(fragment instanceof Fragment2)
        fragments.put(2, fragment);
    if(fragment instanceof Fragment3)
        fragments.put(3, fragment);
    if(fragment instanceof Fragment4)
        fragments.put(4, fragment);
}

Then I have the following method for getting the current fragment

public Fragment getCurrentFragment() {
    return fragments.get(currentPage);
}

0
final ViewPager.OnPageChangeListener onPageChangeListener =
    new ViewPager.OnPageChangeListener() {
      @Override public void onPageSelected(int position) {
        switch (position) {
          case 0:
            FragmentClass1 frag1 =
                (FragmentClass1) viewPager.getAdapter()
                    .instantiateItem(viewPager, viewPager.getCurrentItem());
            frag1.updateList("Custom text");
            break;
          case 1:
            break;
          case 2:
            break;
        }
      }

      @Override
      public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

      }

      @Override public void onPageScrollStateChanged(int state) {
      }
    };


 viewPager.addOnPageChangeListener(onPageChangeListener);

viewPager.setAdapter(adapter);


viewPager.post(new Runnable() {
  @Override public void run() {
    onPageChangeListener.onPageSelected(viewPager.getCurrentItem());
  }
});

कभी-कभी टुकड़ा एक अशक्त वस्तु को भेज सकता है, इसलिए आप पहले लोड पर समस्या को हल करने के लिए एक नया Runnable चला सकते हैं।

शुक्रिया रिक


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

0

अपने FragmentPagerAdapter से setPrimaryItem को ओवरराइड करें: ऑब्जेक्ट दृश्य टुकड़ा है:

 @Override
        public void setPrimaryItem(ViewGroup container, int position, Object object) {
            if (mCurrentFragment != object) {
                mCurrentFragment = (LeggiCapitoloFragment) object;
            }
            super.setPrimaryItem(container, position, object);
        }

0

बस पेजर से वर्तमान आइटम प्राप्त करें और फिर अपने एडाप्टर को उस स्थिति के टुकड़े से पूछें।

 int currentItem = viewPager.getCurrentItem();
    Fragment item = mPagerAdapter.getItem(currentItem);
    if (null != item && item.isVisible()) {
       //do whatever want to do with fragment after doing type checking
        return;
    }

3
क्या होगा अगर getItemएक नया उदाहरण बनाया जाए
प्रकाश नादर

0

वर्तमान टुकड़ा प्राप्त करने के लिए - सार्वजनिक शून्य पर ViewPager में स्थिति प्राप्त करें onPageSelected (अंतिम int स्थिति) और फिर

public PlaceholderFragment getFragmentByPosition(Integer pos){
    for(Fragment f:getChildFragmentManager().getFragments()){
        if(f.getId()==R.viewpager && f.getArguments().getInt("SECTNUM") - 1 == pos) {
            return (PlaceholderFragment) f;
        }
    }
    return null;
}

SECTNUM - सार्वजनिक स्थैतिक प्लेसहोल्डरफ्रैगमेंट newInstance (int sectionNumber) में निर्दिष्ट स्थिति तर्क ; खुशबू का

getChildFragmentManager () या getFragmentManager () - कैसे बनाया गया है पर निर्भर करता है


0

आप फ्रैगमेंट में एक ब्रॉडकास्टर को लागू कर सकते हैं और कहीं से भी आशय भेज सकते हैं। टुकड़े का रिसीवर विशिष्ट कार्रवाई के लिए सुन सकता है और उदाहरण की विधि को लागू कर सकता है।

एक चेतावनी यह सुनिश्चित कर रही है कि दृश्य घटक पहले से ही त्वरित है (और कुछ कार्यों के लिए, जैसे कि एक सूची को स्क्रॉल करना, सूची दृश्य पहले ही प्रदान किया जाना चाहिए)।


0

यह सबसे सरल हैक है:

fun getCurrentFragment(): Fragment? {
    return if (count == 0) null
    else instantiateItem(view_pager, view_pager.currentItem) as? Fragment
}

(कोटलिन कोड)

बस कॉल करें instantiateItem(viewPager, viewPager.getCurrentItem()और इसे कास्ट करें Fragment। आपका आइटम पहले से ही इंस्टेंट होगा। यह सुनिश्चित करने के लिए कि आप एक चेक जोड़ सकते हैं getCount

दोनों के साथ काम करता है FragmentPagerAdapterऔर FragmentStatePagerAdapter!


0

यदि आपका पेजर फ्रैगमेंट के अंदर है तो इसका उपयोग करें:

private fun getPagerCurrentFragment(): Fragment? {
    return childFragmentManager.findFragmentByTag("android:switcher:${R.id.myViewPagerId}:${myViewPager.currentItem}")
}

R.id.myViewPagerIdXml लेआउट के अंदर आपके ViewPager की आईडी कहां है।


यह केवल सामान्य FragmentPageAdapter के साथ काम करता है और FragmentStatePageAdapter के साथ नहीं।
प्रोग्न्यूबी

0

आप अंशों को रजिस्टर अंशों के रूप में घोषित कर सकते हैं

class DashboardPagerAdapter(fm: FragmentManager?) : FragmentStatePagerAdapter(fm!!) {
    // CURRENT FRAGMENT
    val registeredFragments = SparseArray<Fragment>()

    override fun instantiateItem(container: ViewGroup, position: Int): Any {
        val fragment = super.instantiateItem(container, position) as Fragment
        registeredFragments.put(position, fragment)
        return fragment
    }

    override fun getItem(position: Int): Fragment {
        return when (position) {
            0 -> HomeFragment.newInstance()
            1 -> ConverterDashboardFragment.newInstance()
            2 -> CartFragment.newInstance()
            3 -> CustomerSupportFragment.newInstance()
            4 -> ProfileFragment.newInstance()
            else -> ProfileFragment.newInstance()
        }
    }

    override fun getCount(): Int {
        return 5
    }

}

तब आप इसका उपयोग कर सकते हैं

adapter?.let {
    val cartFragment = it.registeredFragments[2] as CartFragment?
    cartFragment?.myCartApi(true)
}

यदि आप इस तरह से जाने का निर्णय लेते हैं, तो आपको भी नष्ट करना लागू करना चाहिए () और पंजीकृत उदाहरणों से नष्ट उदाहरण को हटा दें, अन्य बुद्धिमानों के पास आपके पास मेमोरी रिसाव होगा।
डेफिनेरा

यह अच्छी सलाह है। उत्तर में संपादन करने के लिए आपका स्वागत है।
हमजा खान

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.