ViewPager पेजर एडाप्टर दृश्य को अपडेट नहीं कर रहा है


597

मैं संगतता पुस्तकालय से ViewPager का उपयोग कर रहा हूं। मैंने सफलतापूर्वक कई विचार प्रदर्शित किए हैं, जिनके माध्यम से मैं पेज बना सकता हूं।

हालाँकि, मुझे यह देखने में कठिन समय है कि व्यूपार्ज को नए सेट के साथ कैसे अपडेट किया जाए।

मैंने हर तरह की चीजों को कॉल करने की कोशिश की है mAdapter.notifyDataSetChanged(), mViewPager.invalidate()यहां तक ​​कि हर बार जब मैं डेटा की एक नई सूची का उपयोग करना चाहता हूं , तो एक नया एडेप्टर बनाना।

कुछ भी मदद नहीं की है, मूल डेटा से पाठ अपरिवर्तित रहते हैं।

अद्यतन: मैंने थोड़ी परीक्षण परियोजना बनाई है और मैं विचारों को अपडेट करने में लगभग सक्षम हूं। मैं नीचे क्लास पेस्ट करूँगा।

अपडेट देखने के लिए जो दिखाई नहीं देता है, वह दूसरा दृश्य है, 'B' शेष है, इसे अपडेट बटन दबाने के बाद 'Y' प्रदर्शित करना चाहिए।

public class ViewPagerBugActivity extends Activity {

    private ViewPager myViewPager;
    private List<String> data;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        data = new ArrayList<String>();
        data.add("A");
        data.add("B");
        data.add("C");

        myViewPager = (ViewPager) findViewById(R.id.my_view_pager);
        myViewPager.setAdapter(new MyViewPagerAdapter(this, data));

        Button updateButton = (Button) findViewById(R.id.update_button);
        updateButton.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                updateViewPager();
            }
        });
    }

    private void updateViewPager() {
        data.clear();
        data.add("X");
        data.add("Y");
        data.add("Z");
        myViewPager.getAdapter().notifyDataSetChanged();
    }

    private class MyViewPagerAdapter extends PagerAdapter {

        private List<String> data;
        private Context ctx;

        public MyViewPagerAdapter(Context ctx, List<String> data) {
            this.ctx = ctx;
            this.data = data;
        }

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

        @Override
        public Object instantiateItem(View collection, int position) {
            TextView view = new TextView(ctx);
            view.setText(data.get(position));
            ((ViewPager)collection).addView(view);
            return view;
        }

        @Override
        public void destroyItem(View collection, int position, Object view) {
             ((ViewPager) collection).removeView((View) view);
        }

        @Override
        public boolean isViewFromObject(View view, Object object) {
            return view == object;
        }

        @Override
        public Parcelable saveState() {
            return null;
        }

        @Override
        public void restoreState(Parcelable arg0, ClassLoader arg1) {
        }

        @Override
        public void startUpdate(View arg0) {
        }

        @Override
        public void finishUpdate(View arg0) {
        }
    }
}

1
कृपया FragmentStatePagerAdapter के साथ एक संभावित बग के लिए stackoverflow.com/questions/12510404/… देखें ।
समिस

2
क्षमा करें यह अप करने के लिए। आपके प्रश्न ने वास्तव में मुझे धन्यवाद देने में मदद की! एक चीज जो मुझे नहीं मिलती है वह यह है कि
पेजर एडेप्टर

अपने एडॉप्टर का विस्तार करें बेस एडेप्टर इसका संदर्भ लें: stackoverflow.com/questions/13664155/…

1
जाहिरा तौर पर यदि आप एडेप्टर को फिर से अपने व्यू पेजर पर सेट करते हैं, तो यह रीसेट हो जाता है।
एपिकपांडाफॉर्क्स

मैं पेजर में समस्या आ रही है stackoverflow.com/questions/41217237/...
क्रिस

जवाबों:


856

इसे प्राप्त करने के कई तरीके हैं।

पहला विकल्प आसान है, लेकिन थोड़ा अधिक अक्षम है।

ओवरराइड getItemPositionअपने में PagerAdapterइस तरह:

public int getItemPosition(Object object) {
    return POSITION_NONE;
}

इस तरह, जब आप कॉल करते हैं notifyDataSetChanged(), तो दृश्य पेजर सभी दृश्यों को हटा देगा और उन सभी को पुनः लोड करेगा। जैसा कि पुनः लोड प्रभाव प्राप्त किया जाता है।

दूसरा विकल्प, अलवारो लुइस बस्टामेंटे (पहले alvarolb) ने सुझाव दिया , करने के लिए है setTag()में विधि instantiateItem()जब कोई नया दृश्य instantiating। फिर उपयोग करने के बजाय notifyDataSetChanged(), आप findViewWithTag()उस दृश्य को खोजने के लिए उपयोग कर सकते हैं जिसे आप अपडेट करना चाहते हैं।

दूसरा दृष्टिकोण बहुत लचीला और उच्च प्रदर्शन वाला है। मूल शोध के लिए कुडोस से अलवरोलब।


4
चारों ओर मेरे काम से बेहतर, लगता है कि कोई भी पक्ष प्रभावित नहीं होता है, धन्यवाद।
21 मई को C0deAttack

3
मुझे एक ऐसी ही समस्या है। मेरा viewPager नए searc परिणाम दिखाएगा, लेकिन कर्सर में पहली प्रविष्टि के लिए डिफ़ॉल्ट रूप से वापस नहीं आता है। क्या किसी को पता है कि डेटासेट को अपडेट करते समय स्थिति को कैसे रीसेट किया जाए?
mAndroid

1
@mAndroid आपको अधिक विवरण के साथ एक अलग प्रश्न दर्ज करना चाहिए।
रुई.राजौ

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

11
बेहतर उत्तर (सभी आइटमों को हटाए बिना) -> stackoverflow.com/a/10852046/898056
yhpark

484

मुझे नहीं लगता कि इसमें किसी तरह की कोई बग है PagerAdapter। समस्या यह है कि यह समझना कि यह कैसे काम करता है थोड़ा जटिल है। यहां बताए गए समाधानों को देखते हुए, एक गलतफहमी है और इसलिए मेरे दृष्टिकोण से तात्कालिक विचारों का एक खराब उपयोग है।

पिछले कुछ दिनों मैं के साथ काम किया गया है PagerAdapterऔर ViewPager, और मैं निम्नलिखित पाया:

notifyDataSetChanged()पर विधि PagerAdapterकेवल सूचित करेंगे ViewPagerकि अंतर्निहित पृष्ठों बदल दिया है। उदाहरण के लिए, यदि आपने गतिशील रूप से / हटाए गए पृष्ठों को बनाया है (आपकी सूची से आइटम जोड़ना या निकालना) तो ViewPagerइसका ध्यान रखना चाहिए। इस मामले में मुझे लगता है कि यह ViewPagerनिर्धारित करता है कि क्या एक नया दृश्य हटा दिया जाना चाहिए या विधियों getItemPosition()और getCount()विधियों का उपयोग करके तत्काल ।

मुझे लगता है कि ViewPagerएक notifyDataSetChanged()कॉल के बाद, यह बच्चे के विचार लेता है और के साथ उनकी स्थिति की जांच करता है getItemPosition()। यदि कोई बच्चा इस विधि को देखता है POSITION_NONE, तो यह ViewPagerसमझता है कि दृश्य हटा दिया गया है, कॉल करके destroyItem()और इस दृश्य को हटा रहा है।

इस तरह, getItemPosition()हमेशा वापस लौटने के लिए ओवरराइड करना POSITION_NONEपूरी तरह से गलत है यदि आप केवल पृष्ठों की सामग्री को अपडेट करना चाहते हैं, क्योंकि पहले बनाए गए विचार नष्ट हो जाएंगे और आपके द्वारा कॉल किए जाने पर हर बार नए बनाए जाएंगे notifyDatasetChanged()। यह सिर्फ कुछ TextViewएस के लिए इतना गलत नहीं लग सकता है , लेकिन जब आपके पास जटिल विचार होते हैं, जैसे एक डेटाबेस से सूचीबद्ध सूची दृश्य, यह एक वास्तविक समस्या और संसाधनों की बर्बादी हो सकती है।

अतः दृश्य को हटाने और फिर से देखने के बिना किसी दृश्य की सामग्री को कुशलता से बदलने के लिए कई दृष्टिकोण हैं। यह उस समस्या पर निर्भर करता है जिसे आप हल करना चाहते हैं। मेरा दृष्टिकोण setTag()विधि में किसी भी तात्कालिक दृश्य के लिए instantiateItem()विधि का उपयोग करना है। इसलिए जब आप डेटा को बदलना चाहते हैं या उस दृश्य को अमान्य कर देते हैं, जिसकी आपको ज़रूरत है, तो आप उस findViewWithTag()विधि को कॉल कर सकते हैं, ViewPagerजो पहले के तात्कालिक दृश्य को पुनः प्राप्त करने और संशोधित करने / उपयोग करने के लिए है, जैसा कि आप चाहते हैं कि आप हर बार हटाना चाहते हैं / एक नया दृश्य बनाए बिना। कुछ मूल्य अद्यतन करने के लिए।

उदाहरण के लिए कल्पना करें कि आपके पास 100 TextViewएस के साथ 100 पृष्ठ हैं और आप केवल एक मूल्य को समय-समय पर अपडेट करना चाहते हैं। पहले बताए गए दृष्टिकोण के साथ, इसका मतलब है कि आप TextViewप्रत्येक अपडेट पर 100 एस हटा रहे हैं और इंस्टेंट कर रहे हैं । इसका कुछ अर्थ नहीं निकलता...


11
+1 - आपका समाधान न केवल एक आकर्षण की तरह काम करता है, मैं वास्तव में आपके द्वारा बताई गई समस्या में भाग गया जब मुझे उन पृष्ठों को अपडेट करना पड़ा, जिसमें सूची, साक्षात्कार और चित्रों के साथ एक टैब था। (OutOfErrorException और ऐसे ...) धन्यवाद!
शांगलिंग

3
@alvarolb: नमस्कार, मैं वास्तव में नहीं जानता कि आप setTagविधि के बारे में onInstantiateItemक्या सोचते हैं, क्या आप इस उत्तर को कुछ कोडिंग के साथ अपडेट करना चाहेंगे? धन्यवाद।
टावर

35
अगर आपने एक उदाहरण लिखा तो यह सही होगा।
सामी एल्तामावी

13
जैसा कि कोई कहता है: एक उदाहरण woulb की सराहना की जानी चाहिए!
14:10 पर Jey10

15
6 साल अब, कोई भी एक उदाहरण प्रदान नहीं कर सकता है।
ओसाकी

80

बदले FragmentPagerAdapterके लिए FragmentStatePagerAdapter

ओवरराइड getItemPosition()विधि और वापसी POSITION_NONE

आखिरकार, यह notifyDataSetChanged()दृश्य व्यू पेज पर सुनेगा ।


मुझे लगता है कि आप संपूर्ण getItemPosition को ठीक से लागू करने वाले हैं और टुकड़ा नहीं मिलने पर POSITION_NONE लौटाएं।
तखडुरासेल

46

अलवरोल द्वारा दिया गया उत्तर निश्चित रूप से इसे करने का सबसे अच्छा तरीका है। उनके जवाब पर निर्माण, इसे लागू करने का एक आसान तरीका स्थिति द्वारा केवल सक्रिय विचारों को संग्रहीत करना है:

SparseArray<View> views = new SparseArray<View>();

@Override
public Object instantiateItem(View container, int position) {
    View root = <build your view here>;
    ((ViewPager) container).addView(root);
    views.put(position, root);
    return root;
}

@Override
public void destroyItem(View collection, int position, Object o) {
    View view = (View)o;
    ((ViewPager) collection).removeView(view);
    views.remove(position);
    view = null;
}

फिर एक बार notifyDataSetChangedविधि को ओवरराइड करके आप विचारों को ताज़ा कर सकते हैं ...

@Override
public void notifyDataSetChanged() {
    int key = 0;
    for(int i = 0; i < views.size(); i++) {
       key = views.keyAt(i);
       View view = views.get(key);
       <refresh view with new data>
    }
    super.notifyDataSetChanged();
}

आप वास्तव में में इसी तरह के कोड का उपयोग कर सकते instantiateItemहैं और notifyDataSetChangedआपके विचार ताज़ा करने के लिए। अपने कोड में मैं ठीक उसी विधि का उपयोग करता हूं।


8
क्या आप एक पूर्ण एडाप्टर उदाहरण प्रदान कर सकते हैं? यह फ्रेगमेंट का उपयोग करके किया जा रहा है या नहीं?

9
<नए डेटा के साथ ताज़ा दृश्य> ?? इसका क्या मतलब है या तो हमें उसे यहां जोड़ना होगा या कुछ नहीं?
अकसर एम।

यह विधि सभी विचारों को अपडेट करती है। यदि आप केवल एक दृश्य को अपडेट करना चाहते हैं, तो आप अपनी स्वयं की सूचना दे सकते हैं जैसे कि इस तरह से सूचित करें: public void InformDataItemChanged (int pos) {TextView tv = (TextView) views.get (स्थिति) .findViewById (R.id.tv); tv.setText (list.get (पीओएस)); super.notifyDataSetChanged (); }
काई वांग

यह कोड क्रैश हो जाता है अगर नए पेजर का आकार पुराने आकार से कम है
एंटोन दुज़ेंको

@AntonDuzenko सही है, विचार हटाना काफी कठिन है।
MLProgrammer-CiM

28

एक ही समस्या थी। मेरे लिए इसने FragmentStatePagerAdapter को बढ़ाने, और नीचे दी गई विधियों को ओवरराइड करने का काम किया:

@Override
public Parcelable saveState() {
    return null;
}

@Override
public void restoreState(Parcelable state, ClassLoader loader) {

}

मेरे लिए भी यही एकमात्र उपाय है। मेरा मामला टुकड़े को अद्यतन नहीं कर रहा है, लेकिन टुकड़ों को गतिशील रूप से हटा या जोड़ रहा है। FragmentStatePagerAdapter के विस्तार के बिना, ViewPager कैश किए गए टुकड़े लौटाता है, जो एक गलत स्थिति है। धन्यवाद!
सिरा लैम

समर्थन पुस्तकालय पर अच्छी तरह से काम करता है 28.0.0
Oleksii K.

ओवरराइड क्या करना है? एडॉप्टर से जुड़ी राज्य वस्तु कैसे बनाएं?
फणी ऋत्विज

धन्यवाद दोस्त। यह समाधान केवल काम करता है
पार्थी

20

हताशा के घंटे इस समस्या को दूर करने के लिए सब से ऊपर समाधान की कोशिश कर रहा है और यह भी जैसे अन्य इसी तरह के सवाल पर कई समाधान की कोशिश कर थोड़ी देर के बाद यह , यह और यह जो सभी मेरे साथ विफल इस समस्या को हल करने के लिए और बनाने के लिए ViewPagerपुराने को नष्ट करने Fragmentऔर भरने के pagerसाथ नया Fragmentएस। मैंने निम्नलिखित समस्या का समाधान किया है:

1) निम्नानुसार ViewPagerविस्तार करने के लिए कक्षा बनाएं FragmentPagerAdapter:

 public class myPagerAdapter extends FragmentPagerAdapter {

2)ViewPager उस स्टोर के लिए एक आइटम बनाएं titleऔर fragmentनिम्न के रूप में:

public class PagerItem {
private String mTitle;
private Fragment mFragment;


public PagerItem(String mTitle, Fragment mFragment) {
    this.mTitle = mTitle;
    this.mFragment = mFragment;
}
public String getTitle() {
    return mTitle;
}
public Fragment getFragment() {
    return mFragment;
}
public void setTitle(String mTitle) {
    this.mTitle = mTitle;
}

public void setFragment(Fragment mFragment) {
    this.mFragment = mFragment;
}

}

3) इसे मेरे रूप में स्टोर करने के ViewPagerलिए मेरे FragmentManagerइंस्टेंस का कंस्ट्रक्टर बनाएं class:

private FragmentManager mFragmentManager;
private ArrayList<PagerItem> mPagerItems;

public MyPagerAdapter(FragmentManager fragmentManager, ArrayList<PagerItem> pagerItems) {
    super(fragmentManager);
    mFragmentManager = fragmentManager;
    mPagerItems = pagerItems;
}

4)adapter नए डेटा के साथ डेटा को फिर से सेट करने के लिए एक विधि बनाएं, जो पहले fragmentसे fragmentManagerही सीधे नए सूची से adapterनए को सेट करने के लिए fragmentनिम्न के रूप में स्वयं को पहले से हटाकर :

public void setPagerItems(ArrayList<PagerItem> pagerItems) {
    if (mPagerItems != null)
        for (int i = 0; i < mPagerItems.size(); i++) {
            mFragmentManager.beginTransaction().remove(mPagerItems.get(i).getFragment()).commit();
        }
    mPagerItems = pagerItems;
}

5) कंटेनर से Activityया Fragmentनए डेटा के साथ एडेप्टर को फिर से शुरू न करें। नए डेटा को विधि के माध्यम से नए डेटा के setPagerItemsसाथ सेट करें :

ArrayList<PagerItem> pagerItems = new ArrayList<PagerItem>();
pagerItems.add(new PagerItem("Fragment1", new MyFragment1()));
pagerItems.add(new PagerItem("Fragment2", new MyFragment2()));

mPagerAdapter.setPagerItems(pagerItems);
mPagerAdapter.notifyDataSetChanged();

मुझे उम्मीद है यह मदद करेगा।


@ टॉमर आपको किस समस्या का सामना करना पड़ा?
सामी एल्तामावी


9

मेरे पास एक ही मुद्दा था और मेरा समाधान FragmentPagerAdapterओवरराइडिंग के साथ उपयोग कर रहा है FragmentPagerAdapter#getItemId(int position):

@Override
public long getItemId(int position) {
    return mPages.get(position).getId();
}

डिफ़ॉल्ट रूप से, यह विधि आइटम की स्थिति लौटाती है। मुझे लगता है कि ViewPagerअगर चेक itemIdको बदल दिया गया था और अगर यह था तो केवल पृष्ठ को फिर से बनाता है। लेकिन नहीं- overriden संस्करण के रूप में एक ही स्थिति देता हैitemId भले ही पृष्ठ वास्तव में अलग हो, और ViewPager परिभाषित नहीं करता है कि पृष्ठ एक को प्रतिस्थापित किया गया है और इसे फिर से बनाने की आवश्यकता है।

इसका उपयोग करने के लिए, long id प्रत्येक पृष्ठ के लिए आवश्यक है। आम तौर पर यह अद्वितीय होने की उम्मीद है, लेकिन मेरा सुझाव है, इस मामले के लिए, कि यह सिर्फ एक ही पृष्ठ के लिए पिछले मूल्य से अलग होना चाहिए। इसलिए, यहां एडाप्टर या यादृच्छिक पूर्णांकों (विस्तृत वितरण के साथ) में निरंतर काउंटर का उपयोग करना संभव है।

मुझे लगता है कि इस विषय में समाधान के रूप में उल्लिखित टैग ऑफ व्यू का उपयोग करने के बजाय यह अधिक सुसंगत तरीका है। लेकिन शायद सभी मामलों के लिए नहीं।


1
यह है। मैंने इसे देख लिया है: बस POSITION_NONE पर्याप्त नहीं है। आपके अद्भुत जवाब के लिए धन्यवाद! :)
स्लाव

यह फ़ंक्शन भी मौजूद नहीं है PagerAdapter। यह किस वर्ग का है?
साकेत

@Saket, आप सही हैं, कक्षा हैFragmentPagerAdapter
atlascoder

6

मुझे इस समस्या का बहुत दिलचस्प निर्णय मिला। FragmentPagerAdapter का उपयोग करने के बजाय , जो सभी खंडों को याद में रखते हैं, हम FragmentStatePagerAdapter ( android.support.v4.app.FragmentStatePagerAdapter ) का उपयोग कर सकते हैं , जो उस समय खंड का पुन: लोड करता है, जब हम इसका चयन करते हैं।

दोनों एडाप्टरों के अहसास समान हैं। तो, हमें " FragmentStatePagerAdapter का विस्तार करें " पर " विस्तार FragmentPagerAdapter " की आवश्यकता है


अच्छी बात है, यह देखने के अन्य मुद्दों को हल करने में मदद करेगा पेजर के टुकड़े से संबंधित
आशु कुमार

शानदार जवाब, इससे मुझे बहुत मदद मिली।
सर्जियो मारानी

5

इस समस्या के लिए बहुत खोज के बाद, मुझे एक बहुत अच्छा समाधान मिला जो मुझे लगता है कि इस बारे में जाने का सही तरीका है। अनिवार्य रूप से, जब दृश्य को त्वरित किया जाता है और जब तक कि दृश्य नष्ट नहीं हो जाता है, तब केवल तुरंत कॉल किया जाता है (यह तब होता है जब आप POSITION_NONE को वापस लेने के लिए getItemPosition फ़ंक्शन को ओवरराइड करते हैं)। इसके बजाय, आप जो करना चाहते हैं वह बचाना है वह बनाए गए दृश्यों है और या तो उन्हें एडॉप्टर में अपडेट करना है, एक फ़ंक्शन प्राप्त करें ताकि कोई दूसरा इसे अपडेट कर सके, या एक सेट फ़ंक्शन जो एडेप्टर को अपडेट करता है (मेरा पसंदीदा)।

इसलिए, अपने MyViewPagerAdapter में एक वैरिएबल जोड़ें जैसे:

private View updatableView;

आपके तात्कालिकता में:

 public Object instantiateItem(View collection, int position) {
        updatableView = new TextView(ctx); //My change is here
        view.setText(data.get(position));
        ((ViewPager)collection).addView(view);
        return view;
    }

तो, इस तरह, आप एक फ़ंक्शन बना सकते हैं जो आपके विचार को अपडेट करेगा:

public updateText(String txt)
{
    ((TextView)updatableView).setText(txt);
}

उम्मीद है की यह मदद करेगा!


मुझे एहसास हुआ कि मैं डेटा सेट नहीं कर रहा था instantiateItemइसलिए मेरे विचार अपडेट नहीं हो रहे थे। आपके जवाब से मुझे इसका एहसास हुआ। +1
फणी ऋत्विज

5

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

मेरे टुकड़े में (पृष्ठ):

  • मैंने सभी कोड ले लिए, जो onCreateView से फ़ॉर्म को पॉप्युलेट करता है और इसे पॉपुलेटफॉर्म नामक एक फ़ंक्शन में डालता है जिसे फ्रेमवर्क के बजाय कहीं से भी कॉल किया जा सकता है। यह फ़ंक्शन getView का उपयोग करके वर्तमान दृश्य प्राप्त करने का प्रयास करता है, और यदि यह शून्य है, तो यह बस वापस आ जाता है। यह महत्वपूर्ण है कि PopulateForm में केवल वही कोड होता है जो प्रदर्शित करता है - अन्य सभी कोड जो फ़ोकसचेंज श्रोताओं को बनाता है और जैसा कि अभी भी OnCreate में है
  • एक बूलियन बनाएं, जिसे ध्वज के रूप में इस्तेमाल किया जा सकता है जो दर्शाता है कि फॉर्म को फिर से लोड किया जाना चाहिए। मेरा है mbReloadForm
  • पॉपुलरफोर्म () को कॉल करने के लिए OnResume () पर ओवरराइड करें यदि mbReloadForm सेट है।

मेरी गतिविधि में, जहां मैं पृष्ठों का लोडिंग करता हूं:

  • कुछ भी बदलने से पहले पेज 0 पर जाएं। मैं FragmentStatePagerAdapter का उपयोग कर रहा हूं, इसलिए मुझे पता है कि दो या तीन पृष्ठ सबसे अधिक प्रभावित होते हैं। पेज 0 में बदलाव से यह सुनिश्चित होता है कि मुझे केवल 0, 1 और 2 पेजों पर ही समस्या है।
  • पुरानी सूची को साफ़ करने से पहले, इसका आकार () लें। इस तरह आप जानते हैं कि बग से कितने पृष्ठ प्रभावित होते हैं। यदि> 3, इसे घटाकर 3 करें - यदि आप एक अलग पेजर एडेप्टर का उपयोग कर रहे हैं, तो आपको यह देखना होगा कि आपको (शायद सभी?) कितने पृष्ठों से निपटना है?
  • डेटा पुनः लोड करें और पृष्ठ पर कॉल करें Adapter.notifyDataSetChanged ()
  • अब प्रभावित पृष्ठों में से प्रत्येक के लिए, देखें कि पेज pager.getChildAt (i) का उपयोग करके सक्रिय है या नहीं - यह आपको बताता है कि क्या आपके पास कोई दृश्य है। यदि हां, तो pager.PopulateView () को कॉल करें। यदि नहीं, तो ReloadForm ध्वज सेट करें।

इसके बाद, जब आप पृष्ठों के दूसरे सेट को पुनः लोड करते हैं, तो बग अभी भी पुराने डेटा को प्रदर्शित करने के लिए कुछ कारण होगा। हालाँकि, वे अब ताज़ा हो जाएंगे और आपको नया डेटा दिखाई देगा - आपके उपयोगकर्ताओं को पता नहीं चलेगा कि पृष्ठ कभी गलत था क्योंकि पृष्ठ को देखने से पहले यह ताज़ा होगा।

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


5

इन सभी समाधानों ने मेरी मदद नहीं की। इस प्रकार मुझे एक कार्यशील समाधान मिला: आप setAdapterहर बार कर सकते हैं , लेकिन यह पर्याप्त नहीं है। एडॉप्टर बदलने से पहले आपको ये करना चाहिए:

FragmentManager fragmentManager = slideShowPagerAdapter.getFragmentManager();
FragmentTransaction transaction = fragmentManager.beginTransaction();
List<Fragment> fragments = fragmentManager.getFragments();
for (Fragment f : fragments) {
    transaction.remove(f);
}
transaction.commit();

और उसके बाद:

viewPager.setAdapter(adapter);

धन्यवाद! मेरे मामले में मैंने ViewPagerटुकड़े के अंदर इस्तेमाल किया , इसलिए इसे बदल दिया slideShowPagerAdapter.getFragmentManager()गया getChildFragmentManager()। शायद getFragmentManager()आपके मामले में मदद करेगा। मैंने इस्तेमाल किया FragmentPagerAdapter, नहीं FragmentStatePagerAdapter। इसके अलावा hacky तरीके के लिए stackoverflow.com/a/25994654/2914140 देखें ।
कूलमाइंड

5

एक बहुत आसान तरीका है: एक का उपयोग करें FragmentPagerAdapter, और टुकड़ों पर अपने पृष्ठांकित विचारों को लपेटें। वे अपडेट हो जाते हैं


5

शुक्रिया rar.araujo और अल्वारो लुइस बुस्टामेंट। सबसे पहले, मैं rui.araujo के तरीके का उपयोग करने की कोशिश करता हूं, क्योंकि यह आसान है। यह काम करता है लेकिन जब डेटा बदलता है, तो पृष्ठ स्पष्ट रूप से फिर से शुरू हो जाएगा। यह बुरा है इसलिए मैं अल्वारो लुइस बुस्टामेंट के रास्ते का उपयोग करने की कोशिश करता हूं। यह एकदम सही है। यहाँ कोड है:

@Override
protected void onStart() {
    super.onStart();
}

private class TabPagerAdapter extends PagerAdapter {
    @Override
    public int getCount() {
        return 4;
    }

    @Override
    public boolean isViewFromObject(final View view, final Object object) {
        return view.equals(object);
    }

    @Override
    public void destroyItem(final View container, final int position, final Object object) {
        ((ViewPager) container).removeView((View) object);
    }

    @Override
    public Object instantiateItem(final ViewGroup container, final int position) {
        final View view = LayoutInflater.from(
                getBaseContext()).inflate(R.layout.activity_approval, null, false);
        container.addView(view);
        ListView listView = (ListView) view.findViewById(R.id.list_view);
        view.setTag(position);
        new ShowContentListTask(listView, position).execute();
        return view;
    }
}

और जब डेटा बदलता है:

for (int i = 0; i < 4; i++) {
    View view = contentViewPager.findViewWithTag(i);
    if (view != null) {
        ListView listView = (ListView) view.findViewById(R.id.list_view);
        new ShowContentListTask(listView, i).execute();
    }
}

4

बस के मामले में किसी को भी FragmentStatePagerAdapter का उपयोग कर रहे हैं आधारित एडेप्टर (जो ViewPager को मेरे उद्देश्य के लिए अधिकतम 2 पर, प्रदर्शन उद्देश्य के लिए आवश्यक न्यूनतम पृष्ठ बनाने देगा), @ rui.araujo के आपके एडेप्टर में ओवरइटिंग getItemPosition का जवाब महत्वपूर्ण अपशिष्ट का कारण नहीं होगा, लेकिन यह अभी भी है। सुधारा जा सकता है।

छद्म कोड में:

public int getItemPosition(Object object) {
    YourFragment f = (YourFragment) object;
    YourData d = f.data;
    logger.info("validate item position on page index: " + d.pageNo);

    int dataObjIdx = this.dataPages.indexOf(d);

    if (dataObjIdx < 0 || dataObjIdx != d.pageNo) {
        logger.info("data changed, discard this fragment.");
        return POSITION_NONE;
    }

    return POSITION_UNCHANGED;
}

व्यूपेजर के अंदर, आइटम की पिछली स्थिति को जानना काफी आसान था, सबसे सही कार्यान्वयन केवल नई स्थिति लौटाता है getItemPosition()जब डेटासेट बदल जाता है, और व्यूपेजर को पता चलेगा कि वे बदले गए हैं या नहीं। दुख की बात है, ViewPager ने ऐसा नहीं किया।
विंसस्लिंग जूल 25'14

3

मुझे इसी तरह की समस्या थी जिसमें मेरे चार पृष्ठ थे और एक पृष्ठ अन्य तीनों पर अद्यतित था। मैं वर्तमान पृष्ठ से सटे पृष्ठ पर विजेट्स (सीकबर्स, टेक्स्ट व्यू आदि) को अपडेट करने में सक्षम था। अंतिम दो पृष्ठों में कॉल करते समय अनइंस्टॉल किए गए विजेट होंगे mTabsAdapter.getItem(position)

मेरी समस्या को हल करने के लिए, मैंने setSelectedPage(index)कॉल करने से पहले उपयोग कियाgetItem(position) । यह पृष्ठ को तुरंत बदल देगा, जिससे मैं प्रत्येक पृष्ठ पर मूल्यों और विगेट्स को बदल सकता हूं।

सभी अद्यतन के बाद मैं setSelectedPage(position)बाद में उपयोग करेगा notifyDataSetChanged()

आप मुख्य अद्यतन पृष्ठ पर ListView में एक मामूली झिलमिलाहट देख सकते हैं, लेकिन ध्यान देने योग्य कुछ भी नहीं। मैंने इसका परीक्षण नहीं किया है, लेकिन यह मेरी तात्कालिक समस्या को हल करता है।


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

3

मैं सिर्फ इस जवाब को पोस्ट कर रहा हूं अगर कोई और इसे उपयोगी पाता है। ठीक उसी काम को करने के लिए, मैंने बस कम्पैटिबिलिटी लाइब्रेरी से ViewPager और PagerAdapter का सोर्स कोड लिया और इसे अपने कोड के भीतर संकलित किया (आपको सभी त्रुटियों को छांटने और खुद को आयात करने की आवश्यकता है, लेकिन यह निश्चित रूप से किया जा सकता है)।

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


2

मुझे लगता है, मुझे ViewPager का लॉजिक मिल गया है।

यदि मुझे पृष्ठों के एक सेट को ताज़ा करने और नए डेटासेट के आधार पर प्रदर्शित करने की आवश्यकता है, तो मैं InformDataSetChanged () कहता हूं । फिर, ViewPager एक वस्तु के रूप में वहां से गुजरते हुए, ItItemPosition () को कई कॉल करता है । यह फ़्रैगमेंट या तो एक पुराने डेटासेट से हो सकता है (जिसे मैं त्यागना चाहता हूं) या किसी नए से (जिसे मैं प्रदर्शित करना चाहता हूं)। इसलिए, मैं getItemPosition () को ओवरराइड करता हूं और वहां मुझे किसी तरह यह निर्धारित करना होगा कि मेरा फ्रैगमेंट पुराने डेटासेट से है या नए से।

मेरे मामले में मेरे पास बाएं फलक पर शीर्ष वस्तुओं की सूची और दाईं ओर एक स्वाइप दृश्य (ViewPager) के साथ 2-फलक लेआउट है। इसलिए, मैं अपने पेजर एडेप्टर के अंदर अपने वर्तमान शीर्ष आइटम के लिए एक लिंक संग्रहीत करता हूं और प्रत्येक तात्कालिक पेज फ्रैगमेंट के अंदर भी। जब सूची में चयनित शीर्ष आइटम बदलता है, तो मैं पेजर एडेप्टर में नए शीर्ष आइटम को संग्रहीत करता हूं और InformDataSetChanged () कहता हूं । और ओवरराइड getItemPosition () में मैं अपने अंश से शीर्ष आइटम की तुलना अपने एडेप्टर से करता हूं। और केवल अगर वे समान नहीं हैं, तो मैं POSITION_NONE वापस करता हूं। उसके बाद, PagerAdapter ने उन सभी अंशों को फिर से बहाल किया जो POSITION_NONE को लौटाए हैं।

ध्यान दें। संदर्भ के बजाय शीर्ष आइटम आईडी संग्रहीत करना बेहतर विचार हो सकता है।

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

public class SomeFragment extends Fragment {
  private TopItem topItem;
}

public class SomePagerAdapter extends FragmentStatePagerAdapter {
  private TopItem topItem;

  public void changeTopItem(TopItem newTopItem) {
    topItem = newTopItem;
    notifyDataSetChanged();
  }

  @Override
  public int getItemPosition(Object object) {
    if (((SomeFragment) object).getTopItemId() != topItem.getId()) {
      return POSITION_NONE;
    }
    return super.getItemPosition(object);
  }
}

सभी पिछले शोधकर्ताओं के लिए धन्यवाद!


2

नीचे दिए गए कोड ने मेरे लिए काम किया।

एक वर्ग बनाएं जो नीचे के रूप में FragmentPagerAdapter वर्ग का विस्तार करता है।

public class Adapter extends FragmentPagerAdapter {

private int tabCount;
private Activity mActivity;
private Map<Integer, String> mFragmentTags;
private FragmentManager mFragmentManager;
private int container_id;
private ViewGroup container;
private List<Object> object;

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

public Adapter(FragmentManager fm, int numberOfTabs , Activity mA) {
    super(fm);
    mActivity = mA;
    mFragmentManager = fm;
    object = new ArrayList<>();
    mFragmentTags = new HashMap<Integer, String>();
    this.tabCount = numberOfTabs;
}

@Override
public Fragment getItem(int position) {
    switch (position) {
        case 0:
            return Fragment0.newInstance(mActivity);
        case 1:
            return Fragment1.newInstance(mActivity);
        case 2:
            return Fragment2.newInstance(mActivity);
        default:
            return null;
    }}


@Override
public Object instantiateItem(ViewGroup container, int position) {
    Object object = super.instantiateItem(container, position);
    if (object instanceof Fragment) {
        Log.e("Already defined","Yes");
        Fragment fragment = (Fragment) object;
        String tag = fragment.getTag();
        Log.e("Fragment Tag","" + position + ", " + tag);
        mFragmentTags.put(position, tag);
    }else{
        Log.e("Already defined","No");
    }
    container_id = container.getId();
    this.container = container;
    if(position == 0){
        this.object.add(0,object);
    }else if(position == 1){
        this.object.add(1,object);
    }else if(position == 2){
        this.object.add(2,object);
    }
    return object;
}

@Override
public void destroyItem(ViewGroup container, int position, Object object) {
    super.destroyItem(container, position, object);
    if (object instanceof Fragment) {
        Log.e("Removed" , String.valueOf(position));
    }
}

@Override
public int getItemPosition (Object object)
{   int index = 0;
    if(this.object.get(0) == object){
        index = 0;
    }else if(this.object.get(1) == object){
        index = 1;
    }else if(this.object.get(2) == object){
        index = 2;
    }else{
        index = -1;
    }
    Log.e("Index" , "..................." + String.valueOf(index));
    if (index == -1)
        return POSITION_NONE;
    else
        return index;
}

public String getFragmentTag(int pos){
    return "android:switcher:"+R.id.pager+":"+pos;
}

public void NotifyDataChange(){
    this.notifyDataSetChanged();
}

public int getcontainerId(){
    return container_id;
}

public ViewGroup getContainer(){
    return this.container;
}

public List<Object> getObject(){
    return this.object;
}

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

फिर आपके द्वारा बनाए गए प्रत्येक Fragment के अंदर, एक UpdateFragment विधि बनाएं। इस पद्धति में आप उन चीजों को बदलते हैं जिन्हें आपको टुकड़े में बदलने की आवश्यकता होती है। उदाहरण के लिए, मेरे मामले में, Fragment0 में GLSurfaceView शामिल था जो कि .ply फ़ाइल के लिए एक पथ के आधार पर एक 3D ऑब्जेक्ट प्रदर्शित करता है, इसलिए मेरी अद्यतन विधि के अंदर मैं इस प्लाई फ़ाइल का पथ परिवर्तित करता हूं।

तब एक ViewPager उदाहरण बनाएँ,

viewPager = (ViewPager) findViewById(R.id.pager);

और एक Adpater उदाहरण,

adapter = new Adapter(getSupportFragmentManager(), 3, this);

तो यह करो,

viewPager.setAdapter(adapter);
viewPager.setOffscreenPageLimit(1);

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

adapter.NotifyDataChange();

adapter.destroyItem(adapter.getContainer(), 0, adapter.getObject().get(0)); // destroys page 0 in the viewPager.

fragment0 = (Fragment0) getSupportFragmentManager().findFragmentByTag(adapter.getFragmentTag(0)); // Gets fragment instance used on page 0.

fragment0.updateFragment() method which include the updates on this fragment

adapter.instantiateItem(adapter.getContainer(), 0); // re-initialize page 0.

यह समाधान अल्वारो लुइस बस्टामांटे द्वारा सुझाई गई तकनीक पर आधारित था।


1

1. पहले आपको अपने पेजरडेप्टर क्लास में getItemposition विधि सेट करनी होगी। 2. आपको अपने व्यू पेजर की सटीक स्थिति को पढ़ना होगा। फिर उस स्थिति को अपने नए एक के डेटा स्थान के रूप में भेजना होगा। सेटऑनपेज के अंदर 4. अपडेट बटन ऑनक्लियर ओपनर पर क्लिक करें। श्रोता

वह प्रोग्राम कोड थोड़ा सा है जिसे मैंने केवल विशेष स्थिति तत्व को सेट करने के लिए संशोधित किया है

public class MyActivity extends Activity {

private ViewPager myViewPager;
private List<String> data;
public int location=0;
public Button updateButton;
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    data = new ArrayList<String>();
    data.add("A");
    data.add("B");
    data.add("C");
    data.add("D");
    data.add("E");
    data.add("F");

    myViewPager = (ViewPager) findViewById(R.id.pager);
    myViewPager.setAdapter(new MyViewPagerAdapter(this, data));

      updateButton = (Button) findViewById(R.id.update);

    myViewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
        @Override
        public void onPageScrolled(int i, float v, int i2) {
             //Toast.makeText(MyActivity.this, i+"  Is Selected  "+data.size(), Toast.LENGTH_SHORT).show();
        }

        @Override
        public void onPageSelected( int i) {
          // here you will get the position of selected page
            final int k = i;
             updateViewPager(k);

        }

        @Override
        public void onPageScrollStateChanged(int i) {

        }
    });
}

private void updateViewPager(final int i) {  
    updateButton.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {

            Toast.makeText(MyActivity.this, i+"  Is Selected  "+data.size(), Toast.LENGTH_SHORT).show();
            data.set(i, "Replaced "+i);         
            myViewPager.getAdapter().notifyDataSetChanged();
        }
    });

}

private class MyViewPagerAdapter extends PagerAdapter {

    private List<String> data;
    private Context ctx;

    public MyViewPagerAdapter(Context ctx, List<String> data) {
        this.ctx = ctx;
        this.data = data;
    }

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

    @Override
    public int getItemPosition(Object object) {
        return POSITION_NONE;
    }

    @Override
    public Object instantiateItem(View collection, int position) {          

        TextView view = new TextView(ctx);
        view.setText(data.get(position));
        ((ViewPager)collection).addView(view);            
        return view;
    }

    @Override
    public void destroyItem(View collection, int position, Object view) {
         ((ViewPager) collection).removeView((View) view);
    }

    @Override
    public boolean isViewFromObject(View view, Object object) {
        return view == object;
    }

    @Override
    public Parcelable saveState() {
        return null;
    }

    @Override
    public void restoreState(Parcelable arg0, ClassLoader arg1) {
    }

    @Override
    public void startUpdate(View arg0) {
    }

    @Override
    public void finishUpdate(View arg0) {
    }
}
}

1

मेरे लिए क्या काम हो रहा था viewPager.getAdapter().notifyDataSetChanged();

और अनुकूलक में दृश्य के अंदर अद्यतन करने के लिए अपने कोड डाल getItemPositionतो जैसे

@Override
public int getItemPosition(Object object) {

    if (object instanceof YourViewInViewPagerClass) { 
        YourViewInViewPagerClass view = (YourViewInViewPagerClass)object;
        view.setData(data);
    }

    return super.getItemPosition(object);
}

इसके बारे में जाने का सबसे सही तरीका नहीं हो सकता है, लेकिन यह काम किया ( return POSITION_NONEचाल मेरे लिए एक दुर्घटना का कारण बना तो यह एक विकल्प नहीं था)


1

आप गतिशील रूप से सभी टुकड़ों को अपडेट कर सकते हैं, आप तीन चरणों में देख सकते हैं।

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

public class MyPagerAdapter extends FragmentPagerAdapter {
private static int NUM_ITEMS = 3;
private Map<Integer, String> mFragmentTags;
private FragmentManager mFragmentManager;

public MyPagerAdapter(FragmentManager fragmentManager) {
    super(fragmentManager);
    mFragmentManager = fragmentManager;
    mFragmentTags = new HashMap<Integer, String>();
}

// Returns total number of pages
@Override
public int getCount() {
    return NUM_ITEMS;
}

// Returns the fragment to display for that page
@Override
public Fragment getItem(int position) {
    switch (position) {
        case 0:
            return FirstFragment.newInstance();
        case 1:
            return SecondFragment.newInstance();
        case 2:
            return ThirdFragment.newInstance();
        default:
            return null;
    }
}

// Returns the page title for the top indicator
@Override
public CharSequence getPageTitle(int position) {
    return "Page " + position;
}

@Override
public Object instantiateItem(ViewGroup container, int position) {
    Object object = super.instantiateItem(container, position);
    if (object instanceof Fragment) {
        Fragment fragment = (Fragment) object;
        String tag = fragment.getTag();
        mFragmentTags.put(position, tag);
    }
    return object;
}

public Fragment getFragment(int position) {
    Fragment fragment = null;
    String tag = mFragmentTags.get(position);
    if (tag != null) {
        fragment = mFragmentManager.findFragmentByTag(tag);
    }
    return fragment;
}}

अब आपकी गतिविधि में:

public class MainActivity extends AppCompatActivity implements ViewPager.OnPageChangeListener{

MyPagerAdapter mAdapterViewPager;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    ViewPager viewPager = (ViewPager) findViewById(R.id.vpPager);
    mAdapterViewPager = new MyPagerAdapter(getSupportFragmentManager());
    viewPager.setAdapter(mAdapterViewPager);
    viewPager.addOnPageChangeListener(this);
}

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

}

@Override
public void onPageSelected(int position) {

    Fragment fragment = mAdapterViewPager.getFragment(position);
    if (fragment != null) {
        fragment.onResume();
    }
}

@Override
public void onPageScrollStateChanged(int state) {

}}

अंत में आपके टुकड़े में, ऐसा कुछ:

public class YourFragment extends Fragment {

// newInstance constructor for creating fragment with arguments
public static YourFragment newInstance() {

    return new YourFragment();
}

// Store instance variables based on arguments passed
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
}

// Inflate the view for the fragment based on layout XML
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    return inflater.inflate(R.layout.fragment, container, false);
}


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

    //to refresh your view
    refresh();

}}

आप यहाँ पूरा कोड देख सकते हैं ।

धन्यवाद अलवारो लुइस बुस्टामेंट।


1

हमेशा लौटते हुए POSITION_NONE सरल है लेकिन थोड़ा अक्षम तरीका है क्योंकि इससे उन सभी पेजों की तात्कालिकता पैदा होती है जो पहले से ही तात्कालिक हैं।

मैंने एक पुस्तकालय बनाया है ArrayPagerAdapter में आइटम को गतिशील रूप से बदलने के लिए ।

आंतरिक रूप से, यह लाइब्रेरी के एडेप्टर POSITION_NONEपर लौटते हैंgetItemPosiition() केवल आवश्यक होने ही ।

आप इस लायब्रेरी का उपयोग करके आइटम को गतिशील रूप से बदल सकते हैं।

@Override
protected void onCreate(Bundle savedInstanceState) {
        /** ... **/
    adapter = new MyStatePagerAdapter(getSupportFragmentManager()
                            , new String[]{"1", "2", "3"});
    ((ViewPager)findViewById(R.id.view_pager)).setAdapter(adapter);
     adapter.add("4");
     adapter.remove(0);
}

class MyPagerAdapter extends ArrayViewPagerAdapter<String> {

    public MyPagerAdapter(String[] data) {
        super(data);
    }

    @Override
    public View getView(LayoutInflater inflater, ViewGroup container, String item, int position) {
        View v = inflater.inflate(R.layout.item_page, container, false);
        ((TextView) v.findViewById(R.id.item_txt)).setText(item);
        return v;
    }
}

थिल्स लाइब्रेरी भी Fragments द्वारा बनाए गए पृष्ठों का समर्थन करती है।


1

यह मेरे जैसे उन सभी लोगों के लिए है, जिन्हें किसी सेवा (या अन्य बैकग्राउंड थ्रेड) से व्यूपेयर को अपडेट करने की आवश्यकता है और किसी भी प्रस्ताव पर काम नहीं किया गया है: मुझे लॉग इन करने के बाद थोड़ा सा एहसास हुआ, कि InformDataSetChanged () विधि कभी नहीं लौटती है। getItemPosition (ऑब्जेक्ट ऑब्जेक्ट) को आगे की प्रक्रिया के बिना एक सभी छोर कहा जाता है। तब मुझे माता-पिता PagerAdapter वर्ग (उपवर्गों के डॉक्स में नहीं है) के डॉक्स में पाया गया, "डेटा सेट परिवर्तन मुख्य थ्रेड पर होने चाहिए और InformDataSetChanged ()" पर कॉल के साथ समाप्त होना चाहिए। तो, इस मामले में काम कर समाधान था (FragmentStatePagerAdapter और getItemPosition (ऑब्जेक्ट ऑब्जेक्ट) का उपयोग करके POSITION_NONE) सेट करने के लिए:

और उसके बाद Call को InformDataSetChanged ():

runOnUiThread(new Runnable() {
         @Override
         public void run() {
             pager.getAdapter().notifyDataSetChanged();
         }
     });

1

आप इस तरह Viewpager पर पेजर परिवर्तन जोड़ सकते हैं

myPager.setPageTransformer(true, new MapPagerTransform());

नीचे के कोड में मैंने पेजर स्क्रॉल करते समय रनटाइम पर अपना रंग बदल दिया

public class MapPagerTransform implements ViewPager.PageTransformer {


    public void transformPage(View view, float position) {
     LinearLayout  showSelectionLL=(LinearLayout)view.findViewById(R.id.showSelectionLL);

     if (position < 0) {

                showSelectionLL.setBackgroundColor(Color.WHITE);
     }else if (position >0){

                showSelectionLL.setBackgroundColor(Color.WHITE);
     }else {
                showSelectionLL.setBackgroundColor(Color.RED);
     }
   }
}

1

मुझे पता है कि देर से बांध लेकिन फिर भी यह किसी की मदद कर सकता है। मैं केवल अभियोगी उत्तर को बढ़ा रहा हूं और मैंने इस पर टिप्पणी भी जोड़ दी है।

कुंआ,

जवाब ही कहता है कि यह अक्षम है

तो जब यह आवश्यक हो तो आप इसे ताज़ा कर सकते हैं

private boolean refresh;

public void refreshAdapter(){
    refresh = true;
    notifyDataSetChanged();
}

@Override
public int getItemPosition(@NonNull Object object) {
    if(refresh){
        refresh = false;
        return POSITION_NONE;
    }else{
        return super.getItemPosition(object);
    }
}

1

ViewPager को गतिशील दृश्य परिवर्तन का समर्थन करने के लिए डिज़ाइन नहीं किया गया था।

इस से संबंधित एक अन्य बग की खोज करते समय मुझे इसकी पुष्टि हो गई थी https://issuetracker.google.com/issues/36956111 और विशेष रूप से https://issuetracker.google.com/issues/36956111#comment56 पर

यह प्रश्न थोड़ा पुराना है, लेकिन Google ने हाल ही में ViewPager2 के साथ इस समस्या को हल किया है । यह एक मानक द्वारा हस्तनिर्मित (अचयनित और संभावित छोटी गाड़ी) समाधानों को बदलने की अनुमति देगा। यह कुछ उत्तरों के रूप में अनावश्यक रूप से विचारों को फिर से बनाने से रोकता है।

ViewPager2 उदाहरणों के लिए, आप https://github.com/googlesamples/android-viewpager2 की जाँच कर सकते हैं

यदि आप ViewPager2 का उपयोग करना चाहते हैं, तो आपको अपनी build.gradle फ़ाइल में निम्न निर्भरता को जोड़ना होगा:

  dependencies {
     implementation 'androidx.viewpager2:viewpager2:1.0.0-beta02'
  }

तब आप अपने ViewPager को अपनी xml फ़ाइल में बदल सकते हैं:

    <androidx.viewpager2.widget.ViewPager2
        android:id="@+id/pager"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1" />

उसके बाद, आपको अपनी गतिविधि में ViewPager2 द्वारा ViewPager को बदलना होगा

ViewPager2 को RecyclerView.Adcape या FragmentStateAdapter की आवश्यकता होती है, आपके मामले में यह एक RecyclerView.Adcape हो सकता है।

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;

import java.util.ArrayList;

public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {

    private Context context;
    private ArrayList<String> arrayList = new ArrayList<>();

    public MyAdapter(Context context, ArrayList<String> arrayList) {
        this.context = context;
        this.arrayList = arrayList;
    }

    @NonNull
    @Override
    public MyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(context).inflate(R.layout.list_item, parent, false);
        return new MyViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull MyViewHolder holder, int position) {
        holder.tvName.setText(arrayList.get(position));
    }

    @Override
    public int getItemCount() {
        return arrayList.size();
    }

    public class MyViewHolder extends RecyclerView.ViewHolder {
        TextView tvName;

        public MyViewHolder(@NonNull View itemView) {
            super(itemView);
            tvName = itemView.findViewById(R.id.tvName);
        }
    }
} 

उस स्थिति में जब आप एक TabLayout का उपयोग कर रहे थे, आप TabLayoutMediator का उपयोग कर सकते हैं:

        TabLayoutMediator tabLayoutMediator = new TabLayoutMediator(tabLayout, viewPager, true, new TabLayoutMediator.OnConfigureTabCallback() {
            @Override
            public void onConfigureTab(@NotNull TabLayout.Tab tab, int position) {
                // configure your tab here
                tab.setText(tabs.get(position).getTitle());
            }
        });

        tabLayoutMediator.attach();

तब आप अपने एडॉप्टर के डेटा को संशोधित करके और अधिसूचित डेटासेट विधि को कॉल करके अपने विचारों को ताज़ा कर पाएंगे



0

मुझे लगता है कि मैंने डेटा सेट परिवर्तनों को सूचित करने का एक सरल तरीका बनाया है:

सबसे पहले, जिस तरह से InstantiateItem फ़ंक्शन काम करता है, उसे थोड़ा बदलें:

    @Override
    public Object instantiateItem(final ViewGroup container, final int position) {
        final View rootView = mInflater.inflate(...,container, false);
        rootView.setTag(position);
        updateView(rootView, position);
        container.addView(rootView, LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
        mViewPager.setObjectForPosition(rootView, position);
        return rootView;
    }

"अपडेट व्यू" के लिए, उस सभी डेटा के साथ दृश्य को भरें जिसे आप भरना चाहते हैं (सेटटेक्स्ट, सेटबिटमैप, ...)।

इस तरह से काम करता है को नष्ट करने के लिए सत्यापित करें:

    @Override
    public void destroyItem(final ViewGroup container, final int position, final Object obj) {
        final View viewToRemove = (View) obj;
        mViewPager.removeView(viewToRemove);
    }

अब, मान लीजिए कि आपको डेटा बदलने की आवश्यकता है, इसे करें, और फिर पेजर एडेप्टर पर अगले फ़ंक्शन को कॉल करें:

    public void notifyDataSetChanged(final ViewPager viewPager, final NotifyLocation fromPos,
            final NotifyLocation toPos) {
        final int offscreenPageLimit = viewPager.getOffscreenPageLimit();
        final int fromPosInt = fromPos == NotifyLocation.CENTER ? mSelectedPhotoIndex
                : fromPos == NotifyLocation.MOST_LEFT ? mSelectedPhotoIndex - offscreenPageLimit
                        : mSelectedPhotoIndex + offscreenPageLimit;
        final int toPosInt = toPos == NotifyLocation.CENTER ? mSelectedPhotoIndex
                : toPos == NotifyLocation.MOST_LEFT ? mSelectedPhotoIndex - offscreenPageLimit
                        : mSelectedPhotoIndex + offscreenPageLimit;
        if (fromPosInt <= toPosInt) {
            notifyDataSetChanged();
            for (int i = fromPosInt; i <= toPosInt; ++i) {
                final View pageView = viewPager.findViewWithTag(i);
                mPagerAdapter.updateView(pageView, i);
            }
        }
    }

public enum NotifyLocation {
    MOST_LEFT, CENTER, MOST_RIGHT
}

उदाहरण के लिए, यदि आप उन सभी विचारों को सूचित करना चाहते हैं जो दृश्यदर्शी द्वारा दिखाए जा रहे हैं कि कुछ बदल गया है, तो आप कॉल कर सकते हैं:

notifyDataSetChanged(mViewPager,NotifyLocation.MOST_LEFT,NotifyLocation.MOST_RIGHT);

बस।


0

किटकैट पर यह क्या है इसके लिए, ऐसा लगता है कि adapter.notifyDataSetChanged()नए विचारों को दिखाने के लिए setOffscreenPageLimitपर्याप्त है , बशर्ते कि आप पर्याप्त रूप से उच्च हैं। मैं करने के द्वारा वांछित व्यवहार प्राप्त करने में सक्षम हूँ viewPager.setOffscreenPageLimit(2)


0

मैं वास्तव में उपयोग notifyDataSetChanged()पर ViewPagerऔर CirclePageIndicatorऔर उसके बाद मैं फोन destroyDrawingCache()पर ViewPagerऔर यह काम करता .. अन्य समाधान में से कोई भी मेरे लिए काम किया।


मूल प्रश्न लगभग 2 साल पुराना है, मुझे यकीन है कि अब तक एंड्रॉइड एपीआई में कई अंतर हैं कि यहां उत्तर एंड्रॉइड एपीआई के सभी संस्करणों के लिए सही नहीं हो सकते हैं।
C0deAttack
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.