ViewPager से एक खंड प्राप्त करें


248

मैं तीन अलग-अलग अंशों को होस्ट करने के लिए एक ViewPagerसाथ उपयोग कर रहा हूं FragmentStatePagerAdapter:

  • [Fragment1]
  • [Fragment2]
  • [Fragment3]

मैं प्राप्त करना चाहते हैं Fragment1से ViewPagerमेंFragmentActivity

समस्या क्या है, और मैं इसे कैसे ठीक करूं?

जवाबों:


504

मुख्य उत्तर फ्रेमवर्क द्वारा उत्पन्न किए जा रहे नाम पर निर्भर करता है। अगर वह कभी बदलता है, तो यह अब काम नहीं करेगा।

इस समाधान के बारे में, ओवरराइडिंग instantiateItem()और destroyItem()आपके Fragment(State)PagerAdapter:

public class MyPagerAdapter extends FragmentStatePagerAdapter {
    SparseArray<Fragment> registeredFragments = new SparseArray<Fragment>();

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

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

    @Override
    public Fragment getItem(int position) {
        return MyFragment.newInstance(...); 
    }

    @Override
    public Object instantiateItem(ViewGroup container, int position) {
        Fragment fragment = (Fragment) super.instantiateItem(container, position);
        registeredFragments.put(position, fragment);
        return fragment;
    }

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

    public Fragment getRegisteredFragment(int position) {
        return registeredFragments.get(position);
    }
}

यह मेरे लिए काम करता है जब उपलब्ध फ्रेगमेंट के साथ काम करता है। फ्रेगमेंट जो अभी तक तत्काल नहीं किए गए हैं, कॉल करने पर शून्य वापस आ जाएंगे getRegisteredFragment। लेकिन मैं इसका उपयोग वर्तमान से Fragmentबाहर निकालने के लिए कर रहा हूं ViewPager: adapater.getRegisteredFragment(viewPager.getCurrentItem())और यह वापस नहीं आएगा null

मैं इस समाधान के किसी भी अन्य कमियों से अवगत नहीं हूं। यदि कोई हो, तो मैं जानना चाहूंगा।


41
यह सबसे अच्छा समाधान है जो मैं भी सोच सकता हूं। केवल सुझाव शायद रैप करने के लिए किया जाएगा Fragmentएक में WeakReferenceगारंटी करने के लिए आप जा रहा कचरा एकत्र से एक को नष्ट कर दिया टुकड़ा को रोकने नहीं है? बस ऐसा करना सही लगता है ...
एलेक्स लॉकवुड

7
क्या होता है जब MyPagerAdapterजीवनचक्र (यानी घूमने) के कारण नष्ट हो जाता है, registerdFragmentsखो नहीं जाएगा? क्या Activity/ Fragmentका उपयोग करके MyPagerAdapterइसे सहेजना होगा onSaveInstanceState, और फिर इसे नए FragmentManagerरेफ के साथ अपडेट करने की आवश्यकता है ?
स्टीवन बाईले

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

6
हां, मैंने सत्यापित किया है कि getItemफिर से घुमाने पर नहीं बुलाया जाता है (किसी भी फ्रैग के लिए जो पहले से ही बनाए गए थे), क्योंकि FragmentManagerपुनर्स्थापना के बाद से यह राज्यों के Fragmentsपेजर में रहता है। यदि instantiateItemप्रत्येक Fragmentको बहाल करने के बाद कहा जाता है, तो यह समाधान वास्तव में सुरक्षित है और मेरा या स्वीकृत उत्तर की तुलना में अधिक भविष्य का प्रमाण है। मैं खुद इस पर प्रयास करने पर विचार करूंगा।
स्टीवन बाईले

6
@ डोरी मैं इसे नहीं तोड़ता। मेरा समाधान 'getItem ()' कॉल से परिणाम का उपयोग नहीं कर रहा है। इसके बजाय, यह 'InstantiateItem ()' कॉल से संग्रहीत परिणाम का उपयोग कर रहा है। और टुकड़े का जीवनचक्र टूटा नहीं है, क्योंकि संग्रहित टुकड़ा 'नष्ट' (') कॉल पर विरल-सरणी से हटा दिया जाएगा।
बोस्टन

85

एक ViewPager के टुकड़े बाहर हथियाने के लिए यहाँ और अन्य संबंधित SO थ्रेड्स / ब्लॉग पर बहुत सारे उत्तर हैं। मेरे द्वारा देखे गए सभी लोग टूट गए हैं, और वे आम तौर पर नीचे सूचीबद्ध दो प्रकारों में से एक में आते हैं। कुछ अन्य मान्य समाधान हैं यदि आप केवल इस तरह के वर्तमान टुकड़े को हथियाना चाहते हैं लिए इस धागे पर अन्य जवाब।

अगर FragmentPagerAdapterनीचे देखें। का उपयोग कर FragmentStatePagerAdapterअपने लायक को देखकर यह । कब्जाने वाले अनुक्रमणिकाएं जो कि FragmentStateAdapter में वर्तमान एक नहीं हैं, यह उतनी उपयोगी नहीं है कि इसकी प्रकृति के अनुसार ये पूरी तरह से फाड़ दिए जाएंगे।

UNHAPPY पैट्स

गलत: टुकड़ों की अपनी आंतरिक सूची बनाए रखें, FragmentPagerAdapter.getItem()जिसे कहा जाता है

  • आमतौर पर एक का उपयोग कर SparseArray याMap
  • ऐसे कई उदाहरणों में से एक नहीं, जिन्हें मैंने जीवनचक्र की घटनाओं के लिए देखा है, इसलिए यह समाधान नाजुक है। जैसा getItemकि केवल पहली बार किसी पृष्ठ को स्क्रॉल किया जाता है (या प्राप्त किया जाता है यदि आपका ViewPager.setOffscreenPageLimit(x)> 0) में ViewPager, यदि होस्टिंग Activity/ Fragmentको मार दिया जाता है या फिर से चालू किया जाता है, तो आंतरिक SpaseArrayको मिटा दिया जाएगा जब कस्टम FragmentPagerActivity को फिर से बनाया जाएगा, लेकिन पर्दे के पीछे ViewPagers आंतरिक टुकड़े निर्मित हो जाएगा, और getItemहोगा नहीं अनुक्रमित से किसी के लिए कहा जा, तो इंडेक्स से एक टुकड़ा प्राप्त करने की क्षमता हमेशा के लिए खो दिया जाएगा। आप बाहर बचत और के माध्यम से इन टुकड़ा संदर्भ बहाल करके इस खाते के लिए कर सकते हैं FragmentManager.getFragment()और putFragmentलेकिन यह शुरू होता है गंदा IMHO मिलता है।

गलत: अपने स्वयं के टैग आईडी का मिलान करें जो कि हुड के तहत उपयोग किया जाता हैFragmentPagerAdapter और पृष्ठ फ्रैगमेंट को पुनः प्राप्त करने के लिए इसका उपयोग किया जाता हैFragmentManager

  • यह बेहतर इस हद तक के रूप में यह पहला आंतरिक-सरणी समाधान में हारी-टुकड़ा संदर्भ समस्या के साथ तालमेल बिठाता है, लेकिन के रूप में ठीक ही ऊपर और कहीं और नेट पर जवाब में बताया - यह अपने एक के रूप में hacky का मानना है निजी आंतरिक विधि करने के लिए ViewPagerहै कि कर सकता है किसी भी समय या किसी भी OS संस्करण के लिए परिवर्तन।

इस समाधान के लिए पुनर्निर्मित विधि है

private static String makeFragmentName(int viewId, long id) {
    return "android:switcher:" + viewId + ":" + id;
}

एक खुश पेट: ViewPager.instantiateItem()

getItem()उपरोक्त लेकिन गैर-जीवनचक्र को तोड़ने के लिए एक समान दृष्टिकोणinstantiateItem() इसके बजाय हुक करने के लिए है getItem()क्योंकि पूर्व को हर बार कहा जाएगा कि सूचकांक बनाया / एक्सेस किया गया है। इस जवाब को देखें

एक खुश पेट: अपने खुद के निर्माण FragmentViewPager

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

/**
 * @param containerViewId the ViewPager this adapter is being supplied to
 * @param id pass in getItemId(position) as this is whats used internally in this class
 * @return the tag used for this pages fragment
 */
public static String makeFragmentName(int containerViewId, long id) {
    return "android:switcher:" + containerViewId + ":" + id;
}

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

/**
 * @return may return null if the fragment has not been instantiated yet for that position - this depends on if the fragment has been viewed
 * yet OR is a sibling covered by {@link android.support.v4.view.ViewPager#setOffscreenPageLimit(int)}. Can use this to call methods on
 * the current positions fragment.
 */
public @Nullable Fragment getFragmentForPosition(int position)
{
    String tag = makeFragmentName(mViewPager.getId(), getItemId(position));
    Fragment fragment = getSupportFragmentManager().findFragmentByTag(tag);
    return fragment;
}

यह एक सरल समाधान है और वेब पर हर जगह पाए जाने वाले अन्य दो समाधानों में मुद्दों को हल करता है


6
यह काम करेगा, लेकिन इसके लिए ViewPager वर्ग को अपने स्रोत कोड में कॉपी करना होगा। एक ViewPager के पेजर-एडेप्टर के 'InstantiateItem ()' और 'ruItem ()' पर निर्भर होकर काम करेगा और टुकड़ों के जीवनचक्र का सम्मान करेगा (ये 2 तरीके तब भी कहे जाते हैं जब टुकड़े सहेजे गए इंस्टेंस-स्टेट से होते हैं)। आप सही हैं, 'getItem ()' पर भरोसा करना एक अच्छा विचार नहीं है और निजी एपीआई का उपयोग करना न तो है।
बोस्टन

+1 i मैं सहमत हूं कि यह भी एक समाधान है और ऊपर संपादित किया गया है। अंतर केवल इतना है कि उपरोक्त एक से अधिक उपयोग के मामले में काम करता है, instantiateItem()जो कि तब होता है जब आप एक ऐसे टुकड़े तक पहुंचना चाहते हैं जो जीवन चक्र की घटना के बाद अभी तक दौरा नहीं किया गया है और जीवनचक्र घटना से पहले दौरा किया गया था । एक छोटा सा अंतर जो मुझे पता है लेकिन इसका एक कारण है कि मेरे कार्यक्रम में एक सूक्ष्म बग पैदा हुआ इसलिए मुझे इस पर ध्यान देना चाहिए।
डोरी

यदि setOffscreenPageLimit = 1 (डिफ़ॉल्ट), FragmentStatePageAdapter, मेमोरी के अंदर और बाहर अंशों को स्वैप करना शुरू कर देगा, क्योंकि व्यूज़ एक्सेस किए जाते हैं। GetItem () को पुनः प्राप्त पृष्ठों / टुकड़ों का एक नया उदाहरण प्राप्त करने के लिए एक कॉल द्वारा बनाया जाएगा। इस तरह के पुनर्विचार पर, सिस्टम को नए बनाए जाने के बजाय पहले से निर्मित उदाहरणों को फिर से शुरू करने का निर्देश देने का एक तरीका है?
carl

यदि पृष्ठ सीमा के बाहर इसे एक नया बनाना होगा - लेकिन सहेजे गए स्थिति में गुजर रहा है। यदि आप पुराने को अपने आस-पास रखना चाहते हैं तो आप पृष्ठ संख्या
Dori

@ डोरी getItemId(pos)अंदर नहीं हैFragmentStatePagerAdapter
Jemshit Iskenderov

70

अपने FragmentPagerAdapter में अगले तरीके जोड़ें:

public Fragment getActiveFragment(ViewPager container, int position) {
String name = makeFragmentName(container.getId(), position);
return  mFragmentManager.findFragmentByTag(name);
}

private static String makeFragmentName(int viewId, int index) {
    return "android:switcher:" + viewId + ":" + index;
}

getActiveFragment (0) को काम करना है।

यहाँ ViewPager https://gist.github.com/jacek-marchwicki/d6320ba9a910c514424d में लागू किया गया समाधान है । यदि कुछ विफल हो जाता है तो आपको अच्छा क्रैश लॉग दिखाई देगा।


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

12
मैं इस पद्धति का उपयोग कर रहा था, लेकिन मेरा मानना ​​है कि जब मैंने एपीआई 17 (?) में स्थानांतरित किया तो यह काम करना बंद कर दिया। मैं एक अन्य विधि की सिफारिश करूंगा, और इसे पसंद करूंगा यदि Google ने बस एक एपीआई प्रकाशित किया जो कि एक ViewPager से एक टुकड़ा प्राप्त करने के लिए, अपनी स्थिति को देखते हुए।
gcl1

मुझे दूसरा टुकड़ा कहने में समस्या है, विधि एक नया बना
वासिल वेलेव

2
चूँकि कुछ API संस्करण मेकफ्रैगमेंटनाम विधि को निजी स्टेटिक स्ट्रिंग मेकफ्रैगनाम में परिवर्तित किया गया था (int viewId, long id) {वापसी "android: switcher:" + viewId + ":" + id; } तो getActiveFragment विधि अब इस तरह दिखना चाहिए (दूसरे तर्क के लिए स्थिति के बजाय getItemId का उपयोग करें) सार्वजनिक Fragment getActiveFragment (ViewPager कंटेनर, int स्थिति) {स्ट्रिंग नाम = makeFemmentName (container.getId (), getItemId (स्थिति)); वापसी mFragmentManager.findFragmentByTag (नाम); }
यूजीन पोपोविच

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

38

एक और सरल उपाय:

    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);
        }
    }

1
यह मेरे वर्तमान टुकड़े की जरूरतों के लिए एकदम सही लगता है।
danny117

यदि आप सभी की जरूरत है वर्तमान में चयनित Fragment प्राप्त करने के लिए, यह आप सभी की जरूरत है - विधि setPrimaryItem संलग्न पर सेट है और भी वर्तमान आइटम के रूप में Fragment के आंतरिक सेट करने के लिए हर अद्यतन पर।
ग्रीम

1
यह एक अच्छा समाधान की तरह लगता है, लेकिन जैसा setPrimaryItem()कि मुझे इसका उपयोग नहीं करने के बाद कहा जाता ViewPager.OnPageChangeListener#onPageSelected()है :-(
हार्डिस्सम

21

मुझे पता है कि इसके कुछ जवाब हैं, लेकिन शायद यह किसी की मदद करेगा। जब मुझे Fragmentअपने से प्राप्त करने की आवश्यकता होती है तो मैंने अपेक्षाकृत सरल समाधान का उपयोग किया है ViewPager। अपने Activityया Fragmentधारण करने में ViewPager, आप प्रत्येक कोड के माध्यम से इस कोड का उपयोग कर सकते हैं Fragment

FragmentPagerAdapter fragmentPagerAdapter = (FragmentPagerAdapter) mViewPager.getAdapter();
for(int i = 0; i < fragmentPagerAdapter.getCount(); i++) {
    Fragment viewPagerFragment = fragmentPagerAdapter.getItem(i);
    if(viewPagerFragment != null) {
        // Do something with your Fragment
        // Check viewPagerFragment.isResumed() if you intend on interacting with any views.
    }
}
  • आप अपने की स्थिति पता है Fragmentमें ViewPager, तुम बस फोन कर सकते हैं getItem(knownPosition)

  • आप अपने की स्थिति पता नहीं है Fragmentमें ViewPager, आप अपने बच्चों को हो सकता है Fragmentsकी तरह एक विधि के साथ एक इंटरफ़ेस को लागू getUniqueId()है, और उपयोग है कि उन्हें अलग करने के लिए। या आप सभी के माध्यम से चक्र कर सकते हैं Fragmentsऔर वर्ग प्रकार की जांच कर सकते हैं , जैसे किif(viewPagerFragment instanceof FragmentClassYouWant)

!!! संपादित करें !!!

मुझे पता चला है कि getItemकेवल FragmentPagerAdapterतब कॉल किया जाता है जब प्रत्येक Fragmentको पहली बार बनाने की आवश्यकता होती है , उसके बाद, यह प्रतीत होता है कि Fragmentsपुनर्नवीनीकरण का उपयोग कर रहे हैं FragmentManager। इस तरह, नए एस FragmentPagerAdapterबनाने के कई कार्यान्वयन । मेरी उपरोक्त विधि का उपयोग करते हुए, इसका मतलब है कि हम हर बार नए एस बनाएंगे , जिसे हम सभी वस्तुओं के माध्यम से जाते हैं । इसके कारण, मैंने एक बेहतर दृष्टिकोण पाया है, इसके बजाय प्रत्येक प्राप्त करने के लिए (स्वीकृत उत्तर का उपयोग करके)। यह एक अधिक संपूर्ण समाधान है, और मेरे लिए अच्छा काम कर रहा है। FragmentgetItemFragmentgetItemFragmentPagerAdapterFragmentManagerFragment

FragmentPagerAdapter fragmentPagerAdapter = (FragmentPagerAdapter) mViewPager.getAdapter();
for(int i = 0; i < fragmentPagerAdapter.getCount(); i++) {
    String name = makeFragmentName(mViewPager.getId(), i);
    Fragment viewPagerFragment = getChildFragmentManager().findFragmentByTag(name);
    // OR Fragment viewPagerFragment = getFragmentManager().findFragmentByTag(name);
    if(viewPagerFragment != null) {

        // Do something with your Fragment
        if (viewPagerFragment.isResumed()) {
            // Interact with any views/data that must be alive
        }
        else {
            // Flag something for update later, when this viewPagerFragment
            // returns to onResume
        }
    }
}

और आपको इस विधि की आवश्यकता होगी।

private static String makeFragmentName(int viewId, int position) {
    return "android:switcher:" + viewId + ":" + position;
}

1
आप बस पाते हैं FagmentByTag (), लेकिन हम TAG को खंड के साथ कहां सेट कर सकते हैं ??
विंसस्लिंग

@vince ViewPagerखुद उन टैग्स को सेट करता है। यह समाधान नाजुक है क्योंकि यह "छिपे हुए" नामकरण सम्मेलन को जानने पर निर्भर करता है ViewPager। बोस्टन के उत्तर की सड़कें एक अधिक व्यापक समाधान है, जिसका उपयोग मैं अब अपनी परियोजना (इस दृष्टिकोण के बजाय) में करता हूं।
स्टीवन बाईले

यह महान काम करता है! लेकिन मैंने "if (viewPagerFragment.isResumed ())" सशर्त को हटा दिया क्योंकि मुझे अपने ListFragment पृष्ठों को ऑफ-स्क्रीन करने की आवश्यकता है। फिर जब उपयोगकर्ता ListFragment पृष्ठ पर वापस जाता है, तो यह सभी नए डेटा के साथ अपडेट किया जाता है।
JDJ

10

मेरे मामले के लिए, उपरोक्त समाधानों में से किसी ने भी काम नहीं किया।

हालाँकि जब से मैं एक फ्रेगमेंट में चाइल्ड फ्रैगमेंट मैनेजर का उपयोग कर रहा हूं, निम्नलिखित का उपयोग किया गया था:

Fragment f = getChildFragmentManager().getFragments().get(viewPager.getCurrentItem());

यह केवल तभी काम करेगा जब प्रबंधक में आपके टुकड़े व्यूपेजर आइटम के अनुरूप हों।


जब गतिविधि या खंड को फिर से बनाया जाता है तो व्यू पेजर से पुराने अंशों को प्राप्त करने का यह सही उत्तर है।
स्मेट

7

ViewPager से वर्तमान दृश्यमान टुकड़ा प्राप्त करने के लिए । मैं इस सरल कथन का उपयोग कर रहा हूं और यह ठीक काम कर रहा है।

      public Fragment getFragmentFromViewpager()  
      {
         return ((Fragment) (mAdapter.instantiateItem(mViewPager, mViewPager.getCurrentItem())));
      }

3

मैंने पहले सभी अंशों की एक सूची बनाकर इसे संभाला (List<Fragment> fragments; जो मैं उपयोग करने जा रहा था, फिर उन्हें पेजर में जोड़ा गया जिससे वर्तमान में देखे गए टुकड़े को संभालना आसान हो गया।

इसलिए:

@Override
onCreate(){
    //initialise the list of fragments
    fragments = new Vector<Fragment>();

    //fill up the list with out fragments
    fragments.add(Fragment.instantiate(this, MainFragment.class.getName()));
    fragments.add(Fragment.instantiate(this, MenuFragment.class.getName()));
    fragments.add(Fragment.instantiate(this, StoresFragment.class.getName()));
    fragments.add(Fragment.instantiate(this, AboutFragment.class.getName()));
    fragments.add(Fragment.instantiate(this, ContactFragment.class.getName()));


    //Set up the pager
    pager = (ViewPager)findViewById(R.id.pager);
    pager.setAdapter(new MyFragmentPagerAdapter(getSupportFragmentManager(), fragments));
    pager.setOffscreenPageLimit(4);
}

तो फिर यह कहा जा सकता है:

public Fragment getFragment(ViewPager pager){   
    Fragment theFragment = fragments.get(pager.getCurrentItem());
    return theFragment;
}

इसलिए मैं इसे एक बयान में चक सकता था जो केवल तभी चलेगा जब यह सही टुकड़े पर था

Fragment tempFragment = getFragment();
if(tempFragment == MyFragmentNo2.class){
    MyFragmentNo2 theFrag = (MyFragmentNo2) tempFragment;
    //then you can do whatever with the fragment
    theFrag.costomFunction();
}

लेकिन यह सिर्फ मेरे हैक और स्लेश दृष्टिकोण है, लेकिन यह मेरे लिए काम किया है, मैं इसका इस्तेमाल करते हैं मेरे वर्तमान में प्रदर्शित टुकड़ा करने के लिए परिवर्तन relevent जब वापस बटन धक्का दिया है।


1
मेरे लिए सबसे अच्छा जवाब
सोनू कुमार

3

यह ऊपर स्टीवन के उत्तर पर आधारित है। यह उस खंड का वास्तविक उदाहरण लौटाएगा जो पहले से ही मूल गतिविधि से जुड़ा हुआ है।

FragmentPagerAdapter fragmentPagerAdapter = (FragmentPagerAdapter) mViewPager.getAdapter();
    for(int i = 0; i < fragmentPagerAdapter.getCount(); i++) {

        Fragment viewPagerFragment = (Fragment) mViewPager.getAdapter().instantiateItem(mViewPager, i);
        if(viewPagerFragment != null && viewPagerFragment.isAdded()) {

            if (viewPagerFragment instanceof FragmentOne){
                FragmentOne oneFragment = (FragmentOne) viewPagerFragment;
                if (oneFragment != null){
                    oneFragment.update(); // your custom method
                }
            } else if (viewPagerFragment instanceof FragmentTwo){
                FragmentTwo twoFragment = (FragmentTwo) viewPagerFragment;

                if (twoFragment != null){
                    twoFragment.update(); // your custom method
                }
            }
        }
    }

2

मुझे ऐसा करने का एक सरल, साफ तरीका नहीं मिला। हालाँकि, ViewPager विजेट सिर्फ एक और ViewGroup है, जो आपके टुकड़ों को होस्ट करता है। ViewPager के पास तत्काल बच्चों के रूप में ये टुकड़े हैं। तो आप बस उन पर पुनरावृति कर सकते हैं (.getChildCount () और .getChildAt ()) का उपयोग करके, और देखें कि क्या आप जिस खंड का उदाहरण देख रहे हैं वह वर्तमान में ViewPager में लोड है और इसका संदर्भ प्राप्त करें। उदा। आप अंशों को अलग बताने के लिए कुछ स्थिर यूनिक आईडी फ़ील्ड का उपयोग कर सकते हैं।

ध्यान दें कि ViewPager ने आपके द्वारा खोजे जा रहे टुकड़े को लोड नहीं किया हो सकता है क्योंकि यह ListView जैसे वर्चुअलाइज़िंग कंटेनर है।


1
आपके उत्तर के लिए धन्यवाद, मैं इसे adpter.getItem () के साथ पुनः प्राप्त करता हूं; मैं Android प्रोग्रामिंग में एक नया आदमी हूँ। वास्तव में आपकी बहुत सराहना करते हैं। अब मैं ListFragment को पुनः प्राप्त कर सकता हूं और मैं इसमें footerView जोड़ना चाहता हूं, जबकि मैं अपनी गतिविधि में ऐसा करता हूं तो logcat प्रिंट: "java.lang.IllegalStateException: सामग्री दृश्य अभी तक नहीं बनाया गया है।" इसके साथ।
क्यूं किन

1
FragmentActivity में onAttachFragment () विधि है, ViewPager सफ़ेद टुकड़ा सामग्री के लिए इस काम को खुराक दें?
वासिल वेलेव

2

FragmentPagerAdapter टुकड़ों का कारखाना है। यदि स्मृति अभी भी इसका उपयोग करती है तो उसकी स्थिति के आधार पर एक टुकड़ा खोजने के लिए:

public Fragment findFragmentByPosition(int position) {
    FragmentPagerAdapter fragmentPagerAdapter = getFragmentPagerAdapter();
    return getSupportFragmentManager().findFragmentByTag(
            "android:switcher:" + getViewPager().getId() + ":"
                    + fragmentPagerAdapter.getItemId(position));
}

V4 समर्थन एपीआई के लिए नमूना कोड।


यह onresume () में अशक्त लौट रहा है। किसी भी विचार क्यों और कुदाल इसे ठीक करने के लिए?
सीमा

2

आप नहीं है कॉल करने की जरूरत है getItem()या बाद में किसी अन्य विधि एक के संदर्भ पाने के लिए Fragmentकी मेजबानी के अंदर ViewPager। यदि आप अंदर कुछ डेटा अपडेट करना चाहते हैं Fragmentतो इस दृष्टिकोण का उपयोग करें: ViewPager को गतिशील रूप से अपडेट करें?

कुंजी के अंदर नया डेटा सेट करना है Adaperऔर कॉल करना है notifyDataSetChanged()जो बदले में आपको कॉल करेगा getItemPosition(), आपके संदर्भ को पास करेगा Fragmentऔर आपको इसे अपडेट करने का मौका देगा। अन्य सभी तरीकों से आपको अपने आप को या किसी अन्य हैक का संदर्भ रखने की आवश्यकता होती है जो एक अच्छा समाधान नहीं है।

@Override
public int getItemPosition(Object object) {
    if (object instanceof UpdateableFragment) {
        ((UpdateableFragment) object).update(xyzData);
    }
    //don't return POSITION_NONE, avoid fragment recreation. 
    return super.getItemPosition(object);
}

मुझे यहाँ समझ में नहीं आता, आपको getItemPosition () का उपयोग करने के लिए एक फ़्रैगमेंट के संदर्भ की आवश्यकता है, इसलिए आप getItemPosition, एह का उपयोग नहीं कर सकते हैं?

getItemPosition()आपके एडॉप्टर में एक विधि है। आप इसे सीधे नहीं कहेंगे। आपके पास अपने एडॉप्टर का एक संदर्भ है इसलिए आप कॉल करते हैं adapter.notifyDataSetChanged()जो बदले getItemPosition()में आपके Fragmentएस के संदर्भ को पास करके आपके एडेप्टर को कॉल करेगा । आप कार्रवाई में एक पूर्ण कार्यान्वयन यहाँ देख सकते हैं stackoverflow.com/questions/19891828/...
एम WaJeEh

मैंने उस पर पढ़ा है, और मुझे अभी भी नहीं मिला है। आप अभी भी उन टुकड़े के लिए एक सीधा संदर्भ की आवश्यकता होगी ताकि उनके खिलाफ कॉल करें, है ना? आप उल्लेख करते हैं कि हैक के रूप में लेकिन मुझे कोई विकल्प नहीं दिखता है; adapter.getItem (i) स्पष्ट रूप से काम नहीं करने वाला है।

2
ठीक है मैंने और अधिक स्पष्ट करने के लिए अपना उत्तर अपडेट कर दिया है। बेशक एक संदर्भ को अद्यतन करने की आवश्यकता है, Fragmentलेकिन एक संदर्भ कैसे प्राप्त किया जाए यह बहस में सक्षम है। अन्य समाधानों को FragmentManagerएक स्ट्रिंग के समान उपयोग करने "android:switcher:"+idया सभी टुकड़ों को स्वयं को फिर से बनाने के लिए लौटने POSITION_NONEसे संदर्भ मिलता है getItemosition()
एम-वाजेह

धन्यवाद, यह बहुत अधिक समझ में आता है और मेरे अनुभव से मेल खाता है (इसलिए मैं कुछ गलत नहीं कर सकता, हा)।

2

FragmentPagerAdapterआपके ViewPager एडेप्टर वर्ग में विस्तारित होना चाहिए ।
यदि आप उपयोग करते हैं FragmentStatePagerAdapterतो आप Fragmentइसके द्वारा अपना पता नहीं लगा पाएंगेID

public static String makeFragmentName(int viewPagerId, int index) {
  return "android:switcher:" + viewPagerId + ":" + index;
}

इस विधि का उपयोग कैसे करें: -

Fragment mFragment = ((FragmentActivity) getContext()).getSupportFragmentManager().findFragmentByTag(
       AppMethodUtils.makeFragmentName(mViewPager.getId(), i)
);
InterestViewFragment newFragment = (InterestViewFragment) mFragment;


1

सबसे अच्छा समाधान है कि हम उस कोड का उपयोग करें जिसे हमने कोडपाथ में बनाया है जिसे स्मार्टफ्रैगमेंटस्टैटपेगर एडेप्टर कहा जाता है । उस गाइड के बाद, यह टुकड़ों को पुनः प्राप्त करता है और वर्तमान में व्यूपेजर से चयनित टुकड़ा को काफी आसान बना देता है। यह एडॉप्टर के भीतर एम्बेडेड टुकड़ों की मेमोरी को प्रबंधित करने का एक बेहतर काम भी करता है।


0

सबसे आसान और सबसे संक्षिप्त तरीका। यदि आपके सभी टुकड़े ViewPagerअलग-अलग वर्गों के हैं, तो आप उन्हें निम्नलिखित के रूप में पुनः प्राप्त और अलग कर सकते हैं:

public class MyActivity extends Activity
{

    @Override
    public void onAttachFragment(Fragment fragment) {
        super.onAttachFragment(fragment);
        if (fragment.getClass() == MyFragment.class) {
            mMyFragment = (MyFragment) fragment;
        }
    }

}

यह भी गलत है, क्योंकि जब आप ViewPager का उपयोग करते हैं तो कई टुकड़े होते हैं। वर्तमान पृष्ठ टुकड़ा है, और इसके बाईं ओर एक है और इसके दाईं ओर एक है। यह उपयोगकर्ता को उन दोनों के बीच स्लाइड करने की अनुमति देता है बिना केवल उन्हें आरंभ करने के लिए जब उपयोगकर्ता उन तक पहुंचता है।
एंड्रॉयड डेवलपर

0

मैंने इसे थोड़ा अलग दृष्टिकोण के साथ लागू किया।

मेरा कस्टम FragmentAdapter.getItem विधि ने नया MyFragment () नहीं लौटाया, लेकिन FragmentAdapter कंस्ट्रक्टर में बनाए गए MyFragment का उदाहरण है।

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


0

/Values/integers.xml में पूर्णांक संसाधन आईडी बनाएँ

<integer name="page1">1</integer>
<integer name="page2">2</integer>
<integer name="page3">3</integer>

फिर पेजर एडेप्टर getItem फ़ंक्शन में:

public Fragment getItem(int position) {

        Fragment fragment = null;

        if (position == 0) {
            fragment = FragmentOne.newInstance();
            mViewPager.setTag(R.integer.page1,fragment);

        }
        else if (position == 1) {

            fragment = FragmentTwo.newInstance();
            mViewPager.setTag(R.integer.page2,fragment);

        } else if (position == 2) {

            fragment = FragmentThree.newInstance();
            mViewPager.setTag(R.integer.page3,fragment);

        }

        return fragment;
        }

फिर गतिविधि में खंडित संदर्भ प्राप्त करने के लिए इस फ़ंक्शन को लिखें:

private Fragment getFragmentByPosition(int position) {
    Fragment fragment = null;

    switch (position) {
        case 0:
            fragment = (Fragment) mViewPager.getTag(R.integer.page1);
            break;

        case 1:

            fragment = (Fragment) mViewPager.getTag(R.integer.page2);
            break;

        case 2:
            fragment = (Fragment) mViewPager.getTag(R.integer.page3);
            break;
            }

            return fragment;
    }

उपरोक्त फ़ंक्शन को कॉल करके फ़्रेग्मेंट संदर्भ प्राप्त करें और फिर उसे अपने कस्टम फ़्रेग्मेंट में डालें:

Fragment fragment = getFragmentByPosition(position);

        if (fragment != null) {
                    FragmentOne fragmentOne = (FragmentOne) fragment;
                    }

0

अंश प्रबंधक में अंशों पर पुनरावृति करने का आसान तरीका। व्यूपेजर ढूंढें, जिसमें अनुभाग स्थिति तर्क है, जिसे सार्वजनिक स्थैतिक प्लेसहोल्डरफ्रैगमेंट न्यूइंस्टेंस (इंट सेक्शननंबर) में रखा गया है ।

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

0

खुशबू में

public int getArgument(){
   return mPage;
{
public void update(){

}

FragmentActivity में

List<Fragment> fragments = getSupportFragmentManager().getFragments();
for(Fragment f:fragments){
    if((f instanceof PageFragment)&&(!f.isDetached())){
          PageFragment pf = (PageFragment)f;   
          if(pf.getArgument()==pager.getCurrentItem())pf.update();
    }
}

0

TabLayout में Fragment के लिए कई टैब हैं। आप टैग के टुकड़े को टुकड़े के सूचकांक का उपयोग करके पा सकते हैं।

पूर्व के लिए। Fragment1 के लिए सूचकांक 0 है, इसलिए findFragmentByTag()विधि में, Viewpager के लिए टैग पास करें। टुकड़े टुकड़े का उपयोग करने के बाद आप जोड़ सकते हैं, टुकड़े को बदल सकते हैं।

String tag = "android:switcher:" + R.id.viewPager + ":" + 0; Fragment1 f = (Fragment1) getSupportFragmentManager().findFragmentByTag(tag);


-1

एडॉप्टर के लिए ठीक है FragmentStatePagerAdapter I एक समाधान के लिए धन देता है

आपके FragmentActivity में:

ActionBar mActionBar = getSupportActionBar(); 
mActionBar.addTab(mActionBar.newTab().setText("TAB1").setTabListener(this).setTag(Fragment.instantiate(this, MyFragment1.class.getName())));
mActionBar.addTab(mActionBar.newTab().setText("TAB2").setTabListener(this).setTag(Fragment.instantiate(this, MyFragment2.class.getName())));
mActionBar.addTab(mActionBar.newTab().setText("TAB3").setTabListener(this).setTag(Fragment.instantiate(this, MyFragment3.class.getName())));

viewPager = (STViewPager) super.findViewById(R.id.viewpager);
mPagerAdapter = new MyPagerAdapter(getSupportFragmentManager(), mActionBar);
viewPager.setAdapter(this.mPagerAdapter);

और अपनी कक्षा FragmentActivity में एक मेथोड बनाएं - ताकि वह विधि आपको अपने Fragment तक पहुंच प्रदान करे, आपको बस उसे उस टुकड़े की स्थिति देने की आवश्यकता है जो आप चाहते हैं:

public Fragment getActiveFragment(int position) {
String name = MyPagerAdapter.makeFragmentName(position);
return getSupportFragmentManager().findFragmentByTag(name);
}

आपके एडॉप्टर में:

public class MyPagerAdapter extends FragmentStatePagerAdapter {

private final ActionBar actionBar;
private final FragmentManager fragmentManager;

public MyPagerAdapter(FragmentManager fragmentManager, com.actionbarsherlock.app.ActionBarActionBar mActionBar) {super(fragmentManager);
this.actionBar = mActionBar;
this.fragmentManager = fragmentManager;
}

@Override
public Fragment getItem(int position) {
getSupportFragmentManager().beginTransaction().add(mTchatDetailsFragment, makeFragmentName(position)).commit();
return (Fragment)this.actionBar.getTabAt(position);
}

@Override
public int getCount() {
return this.actionBar.getTabCount();
}

@Override
public CharSequence getPageTitle(int position) {
return this.actionBar.getTabAt(position).getText();
}

private static String makeFragmentName(int viewId, int index) {
return "android:fragment:" + index;
}

}

-1
Fragment yourFragment = yourviewpageradapter.getItem(int index);

indexएडॉप्टर में टुकड़े करने की जगह है जैसे आपने fragment1पहले 0 के रूप में पूर्वव्यापी fragment1पास indexऔर इतने पर आराम के लिए जोड़ा

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