ভিউপেজার পেজারআডাপ্টার ভিউ আপডেট করে না


597

আমি সামঞ্জস্য লাইব্রেরি থেকে ভিউপ্যাজারটি ব্যবহার করছি। আমি সফলতার সাথে এটি বেশ কয়েকটি মতামত প্রদর্শন করেছি যা আমি প্রকাশ করতে পারি।

যাইহোক, ভিউপিজারকে নতুন সেট দর্শন দিয়ে কীভাবে আপডেট করবেন তা নির্ধারণ করতে আমার বেশ কষ্ট হচ্ছে।

আমি কল করার মত সমস্ত ধরণের জিনিস চেষ্টা করেছি mAdapter.notifyDataSetChanged(), mViewPager.invalidate()এমনকি প্রতিবারই আমি কোনও নতুন তালিকার তালিকা ব্যবহার করতে চাইছি এমনকি একেবারে নতুন অ্যাডাপ্টার তৈরি করেছি।

কিছুই সাহায্য করেনি, পাঠ্যদর্শনগুলি মূল তথ্য থেকে অপরিবর্তিত রয়েছে।

আপডেট: আমি একটি সামান্য পরীক্ষা প্রকল্প তৈরি করেছি এবং আমি প্রায় ভিউগুলি আপডেট করতে সক্ষম হয়েছি। আমি নিচের ক্লাসটি পেস্ট করব।

তবে আপডেটটি যা দেখা যাচ্ছে তা দ্বিতীয় দর্শন, 'বি' থেকে যায়, আপডেট বোতাম টিপে এটি 'ওয়াই' প্রদর্শন করা উচিত display

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
ফ্রেগমেন্টস্টেটপেজারএডাপ্টার সহ একটি সম্ভাব্য বাগের জন্য দয়া করে স্ট্যাকওভারফ্লো.com/ প্রশ্নগুলি / 12510404/… দেখুন ।
সামিস

2
এটি ড্রেজ করার জন্য দুঃখিত আপনার প্রশ্ন আমাকে সত্যিই সাহায্য করেছে ধন্যবাদ! একটি জিনিস যা আমি পাই না তা হল
পেজারএডাপ্টারের

: আপনার অ্যাডাপ্টারের BaseAdapter এই পড়ুন প্রসারিত করুন stackoverflow.com/questions/13664155/...

1
সম্ভবত আপনি যদি নিজের ভিউ পেজারে অ্যাডাপ্টারটি আবার সেট করেন তবে এটি পুনরায় সেট হয়।
এপিকপান্ডাফোরস

উত্তর:


856

এটি অর্জনের বিভিন্ন উপায় রয়েছে।

প্রথম বিকল্পটি সহজ, তবে কিছুটা অদক্ষ।

getItemPositionআপনার PagerAdapterমত ওভাররাইড :

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

এইভাবে, আপনি কল করার সময় notifyDataSetChanged(), ভিউ পেজার সমস্ত দর্শন সরিয়ে ফেলবে এবং সেগুলি পুনরায় লোড করবে। পুনরায় লোডের প্রভাবটি পাওয়া যায়।

দ্বিতীয় বিকল্পটি, আলভারো লুইস বুস্তামেন্টে (পূর্বে আলভারলব) দ্বারা প্রস্তাবিত , নতুন দৃষ্টিভঙ্গিটি ইনস্ট্যান্ট করার সময় setTag()পদ্ধতিটি instantiateItem()। তারপরে ব্যবহার notifyDataSetChanged()না করে findViewWithTag()আপনি যে ভিউটি আপডেট করতে চান তা সন্ধান করতে ব্যবহার করতে পারেন ।

দ্বিতীয় পদ্ধতির খুব নমনীয় এবং উচ্চ পারফরম্যান্ট। মূল গবেষণার জন্য কুডোস থেকে আলভারলব।


4
আমার চারপাশের কাজের চেয়ে ভাল, মনে হয় কোনও দিকই প্রভাব ফেলেনি, ধন্যবাদ।
C0deAttack

3
আমি একই সমস্যা আছে। আমার ভিউপেজারটি নতুন সয়ারের ফলাফলগুলি প্রদর্শন করবে তবে কার্সারে প্রথম প্রবেশে ডিফল্ট হবে না। ডেটাসেট আপডেট করার সময় কেউ কীভাবে অবস্থানটি পুনরায় সেট করতে জানে?
এম এন্ড্রয়েড

1
@ এমএন্ড্রয়েড আপনার আরও বিশদ সহ একটি পৃথক প্রশ্ন ফাইল করা উচিত।
rui.araujo

1
POSITION_NONE ফিরিয়ে দেওয়া দৃশ্যত সামগ্রিক প্রয়োগে প্রচুর অদক্ষতা যুক্ত করেছে কারণ এটি অ্যান্ড্রয়েডকে কোয়েড পজিশনের সাথে সম্পর্কিত দৃষ্টিভঙ্গি মুছে ফেলতে বাধ্য করে। এরপরে প্রদর্শনের আগে ভিউটি আবার তৈরি করতে হবে। হালনাগাদ আপডেট না হওয়া সমস্যা সমাধান করে, তবে জটিল লেআউটের জন্য সম্ভবত সেরা সমাধান নয়।
wufoo

11
সর্বোত্তম উত্তর (সমস্ত আইটেম সরিয়ে না দিয়ে) -> স্ট্যাকওভারফ্লো.com
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 টি পৃষ্ঠা সহ 100 পৃষ্ঠা রয়েছে TextViewএবং আপনি কেবল সময়ে সময়ে একটি মান আপডেট করতে চান। পদ্ধতির আগে ব্যাখ্যা করা হয়েছে, এর অর্থ আপনি 100 সরিয়ে এবং ইনস্ট্যান্ট করছেনTextView প্রতিটি আপডেটে টি । এটা জানার জন্য না...


11
+1 - আপনার সমাধানটি কেবল মনোমুগ্ধের মতোই কাজ করে না আমি যখন এখানে বর্ণিত ঠিক ত্রুটিযুক্ত সমস্যার জন্য দৌড়ে এসেছি তখন যখন আমাকে পৃষ্ঠাগুলি আপডেট করতে হয়েছিল যাতে তালিকাগুলি, পাঠ্যদর্শন এবং চিত্রগুলির সাথে একটি ট্যাব রয়েছে। (আউটঅফেরর এক্সপ্রেশনস এবং এই জাতীয় ...) আপনাকে ধন্যবাদ!
schlingel

3
@ আলভারোলব: হ্যালো, আমি setTagপদ্ধতিতে আপনি কীভাবে বোঝাতে চাইছেন তা সত্যিই আমি জানি না onInstantiateItem, আপনি কি কিছু কোডিং দিয়ে উত্তরটি আপডেট করতে চান? ধন্যবাদ।
হুই টাওয়ার

35
আপনি একটি উদাহরণ লিখলে এটি নিখুঁত হবে।
সামি এলটামাভি

13
যেমন কেউ বলেছেন: একটি উদাহরণ woolb প্রশংসা করা হবে!
Jey10

15
এখন 6 বছর, কেউ উদাহরণ দিতে পারে না।
ওসাকি

80

পরিবর্তন FragmentPagerAdapterকরার জন্য FragmentStatePagerAdapter

ওভাররাইড getItemPosition()পদ্ধতি এবং ফিরুন POSITION_NONE

শেষ পর্যন্ত, এটি notifyDataSetChanged()ভিউ পেজারে শুনবে ।


আমি মনে করি আপনি পুরো getItemPosition সঠিকভাবে প্রয়োগ করবেন এবং খণ্ডটি পাওয়া না গেলে POSITION_NONE ফিরিয়ে দেবেন বলে মনে করি।
tkhdurasel

46

Alvarolb দ্বারা দেওয়া উত্তর অবশ্যই এটি করার সর্বোত্তম উপায়। তার উত্তরের ভিত্তিতে, এটি বাস্তবায়নের সহজ উপায় হ'ল সক্রিয় দৃষ্টিভঙ্গি অবস্থানের দ্বারা সঞ্চিত করা:

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
<নতুন ডেটা দিয়ে দেখুন রিফ্রেশ> ?? এর অর্থ কী তা হয় আমাদের এখানে যোগ দেখাতে হবে বা কিছুই না?
আর্কর্ষ এম

এই পদ্ধতিটি সমস্ত দর্শন আপডেট করে। আপনি যদি কেবলমাত্র একটি ভিউ আপডেট করতে চান, তবে আপনি নিজের নোটিফাইড ডেটা আইটেম চেঞ্জ করা পদ্ধতিটি এভাবে লিখতে পারেন: পাবলিক অকার্যকর notifyDataItemChanged (int pos) {TextView tv = (TextView) view.get (pos) .findViewById (R.id.tv); tv.setText (list.get (POS)); super.notifyDataSetChanged (); }
কাই ওয়াং

নতুন পেজারের আকার পুরনো আকারের চেয়ে কম হলে এই কোডটি ক্র্যাশ হয়ে যায়
আন্তন ডুজেনকো


28

একই সমস্যা ছিল। আমার জন্য এটি ফ্রেগমেন্টস্টেটপেজারএডাপ্টার প্রসারিত এবং নীচের পদ্ধতিগুলিকে ওভাররাইড করতে কাজ করেছে:

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

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

}

এটি আমার জন্যও কাজ করা একমাত্র সমাধান। আমার কেসটি খণ্ডটি আপডেট করছে না, তবে পরিবর্তনগুলি টুকরো টুকরো করে পরিবর্তন করছে ically ফ্রেগমেন্টস্টেটপেজারএডাপ্টার প্রসারিত না করে, ভিউপ্যাজারটি টুকরো টুকরো টুকরো করে ফেরত দেয় যা একটি ভুল অবস্থান। ধন্যবাদ!
সিরা লাম

সমর্থন লাইব্রেরি 28.0.0 এ ভাল কাজ করে
কে।

ওভাররাইড কী করতে হবে? কিভাবে অ্যাডাপ্টারের সাথে যুক্ত একটি রাষ্ট্রীয় অবজেক্ট তৈরি করবেন?
ফানি ithত্বভিজ

ধন্যবাদ, বন্ধু. এই সমাধানটি কেবল কাজ করে
পার্থী

20

হতাশা ঘণ্টা এই সমস্যা কাটিয়ে ওঠার জন্য সর্বোপরি সমাধান চেষ্টা এবং মত অন্যান্য অনুরূপ প্রশ্ন অনেক সমাধান চেষ্টা করার সময় পর এই , এই এবং এই যা সব আমার সাথে FAILED এই সমস্যা সমাধানের জন্য এবং করতে 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তা পরীক্ষা করে এবং পৃষ্ঠাটি পুনরায় তৈরি করা হয়। তবে ওভারডিডেন সংস্করণ একই অবস্থানে ফিরে আসেitemId এমনভাবে যদিও পৃষ্ঠাটি ভিন্ন ভিন্ন, এবং ভিউপেজার সেই পৃষ্ঠাটিকে একটি পরিবর্তিত করে এবং পুনরায় তৈরি করা দরকার বলে সংজ্ঞা দেয় না।

এটি ব্যবহার করতে, long id জন্য, প্রতিটি পৃষ্ঠার জন্য প্রয়োজন। সাধারণত এটি অনন্য হওয়ার প্রত্যাশা করা হয় তবে আমি প্রস্তাব দিচ্ছি যে এই ক্ষেত্রে এটি একই পৃষ্ঠার পূর্ববর্তী মান থেকে আলাদা হওয়া উচিত। সুতরাং, অ্যাডাপ্টার বা এলোমেলো পূর্ণসংখ্যার (বিস্তৃত বিতরণ সহ) এ অবিচ্ছিন্ন কাউন্টার ব্যবহার করা সম্ভব।

আমি মনে করি যে এটি এই বিষয়টির সমাধান হিসাবে উল্লিখিত ট্যাগের ভিউ ব্যবহারের চেয়ে আরও সুসংগত উপায়। তবে সম্ভবত সব ক্ষেত্রে নয়।


1
এটাই. আমি এটি পরীক্ষা করে দেখেছি: কেবল POSITION_NONE যথেষ্ট নয়। আপনার দুর্দান্ত উত্তরের জন্য আপনাকে ধন্যবাদ! :)
স্লাভা

এই ফাংশনটি এমনকি উপস্থিত নেই PagerAdapter। এটা কোন ক্লাস?
সায়েত

@ সাকেত, আপনি ঠিক বলেছেন, ক্লাসটি হচ্ছেFragmentPagerAdapter
অ্যাটলস্কোডার

6

আমি এই সমস্যার খুব আকর্ষণীয় সিদ্ধান্ত পেয়েছি। ফ্রেগমেন্টপেজারএডাপ্টার ব্যবহার করার পরিবর্তে , যা সমস্ত টুকরো স্মৃতিতে রাখে, আমরা ফ্রেগমেন্টস্টেটপেজারএডাপ্টার ( android.support.v4.app.FragmentStatePagerAdapter ) ব্যবহার করতে পারি, আমরা যখন প্রতিটি সিলেক্ট করি তখন তা পুনরায় লোড করুন।

উভয় অ্যাডাপ্টারের উপলব্ধি অভিন্ন। সুতরাং, আমরা শুধু পরিবর্তন "দরকার প্রসারিত FragmentPagerAdapter " চালু " FragmentStatePagerAdapter প্রসারিত "


ভাল কথা, এটি খণ্ডের সাথে সম্পর্কিত ভিউয়ারের মেমরির সমস্যাগুলি সমাধান করতে অন্যকে সহায়তা করবে
আশু কুমার ২

দুর্দান্ত উত্তর, এটি আমাকে অনেক সাহায্য করেছে।
সেরজিও মারানী

5

এই সমস্যার জন্য অনেক অনুসন্ধান করার পরে, আমি একটি সত্যই ভাল সমাধান পেয়েছি যা আমি মনে করি এটি সম্পর্কে সঠিক উপায়। মূলত, ইনস্ট্যান্টিয়েট আইটেমটি কেবল তখনই দেখা হয় যখন ভিউটি তাত্ক্ষণিকভাবে প্রদর্শিত হয় এবং আর কখনও কখনও ভিউটি ধ্বংস না করা হয় (আপনি যখন পজিশন_নোনোন ফেরত পেতে getItemPosition ফাংশনটি ওভাররাইড করবেন তখন এটি ঘটে)। পরিবর্তে, আপনি যা করতে চান তা হ'ল তৈরি করা ভিউগুলি সংরক্ষণ করুন এবং সেগুলি অ্যাডাপ্টারে আপডেট করুন, একটি গিটিং ফাংশন তৈরি করুন যাতে অন্য কেউ এটি আপডেট করতে পারে, বা একটি সেট ফাংশন যা অ্যাডাপ্টার আপডেট করে (আমার প্রিয়)।

সুতরাং, আপনার মাইভিউপেজার অ্যাডাপ্টারে একটি ভেরিয়েবল যুক্ত করুন:

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
ফানি ithত্বভিজ

5

ওপি তাঁর প্রশ্ন উত্থাপনের আড়াই বছর পরেও এই সমস্যাটি এখনও ঠিক আছে, এখনও একটি সমস্যা। এটি সম্পর্কে স্পষ্টত গুগলের অগ্রাধিকার বিশেষভাবে বেশি নয়, সুতরাং কোনও সমাধান খুঁজে না পাওয়ার পরিবর্তে আমি একটি কাজের সন্ধান পেয়েছি। আমার জন্য বড় যুগান্তকারী সমস্যাটির আসল কারণ কী তা সন্ধান করছিল ( এই পোস্টে স্বীকৃত উত্তরটি দেখুন )। একবার যখন বিষয়টি স্পষ্ট হয়েছিল যে কোনও সক্রিয় পৃষ্ঠাগুলি সঠিকভাবে রিফ্রেশ হয় না, তখন আমার কাজটি সুস্পষ্ট ছিল:

আমার খণ্ডে (পৃষ্ঠাগুলি):

  • আমি সমস্ত কোড নিয়েছি যা ফর্মটি onCreateView এর বাইরে পপুলেট করেছে এবং এটিকে পপুলেটফর্ম নামে একটি ফাংশনে রেখেছি যা ফ্রেমওয়ার্কের পরিবর্তে কোথাও থেকে ডাকা যেতে পারে। এই ফাংশনটি getView ব্যবহার করে বর্তমান ভিউটি পাওয়ার চেষ্টা করে এবং যদি তা শূন্য হয় তবে এটি কেবল ফিরে আসে। এটি গুরুত্বপূর্ণ যে পপুলেটফর্মটিতে কেবলমাত্র কোডটি প্রদর্শিত হয় - অন্য সমস্ত কোড যা ফোকাসচেঞ্জ শ্রোতাদের তৈরি করে এবং সেই মতটি এখনও অনক্রিয়েটে রয়েছে
  • এমন একটি বুলিয়ান তৈরি করুন যা ফর্মটি নির্দেশ করে একটি পতাকা হিসাবে ব্যবহার করা যেতে পারে যা পুনরায় লোড করতে হবে। খনিটি এমবিরোলোডফর্ম
  • এমবিআরেলোডফর্ম সেট করা থাকলে পপুলেটফর্ম () কে কল করতে অনারেসিউম () ওভাররাইড করুন।

আমার ক্রিয়াকলাপে, যেখানে আমি পৃষ্ঠাগুলি লোড করি:

  • কিছু পরিবর্তন করার আগে পৃষ্ঠা 0 এ যান। আমি ফ্রেগমেন্টস্টেটপেজারএডাপ্টার ব্যবহার করছি, তাই আমি জানি যে দুটি বা তিনটি পৃষ্ঠা সর্বাধিক প্রভাবিত। পৃষ্ঠা 0 তে পরিবর্তন করা নিশ্চিত করে যে 0, 1 এবং 2 পৃষ্ঠাগুলিতে আমার কেবল কখনও সমস্যা আছে।
  • পুরানো তালিকা সাফ করার আগে এটি আকার () নিন। এইভাবে আপনি কীভাবে পজাগুলি বাগ দ্বারা প্রভাবিত তা জানেন। যদি> 3, এটিকে হ্রাস করুন 3 - আপনি যদি আলাদা পেজারআডাপ্টার ব্যবহার করেন তবে আপনাকে দেখতে হবে যে আপনাকে কত পৃষ্ঠা ব্যবহার করতে হবে (সম্ভবত সব?)
  • ডেটা পুনরায় লোড করুন এবং পেজ কল করুনএডাপ্টার.নোটেফাই ডেটাসেট চেঞ্জড ()
  • এখন, প্রতিটি প্রভাবিত পৃষ্ঠাগুলির জন্য, পৃষ্ঠাr.getChildAt (i) ব্যবহার করে পৃষ্ঠাটি সক্রিয় রয়েছে কিনা তা দেখুন - এটি আপনাকে জানায় যদি আপনার দৃষ্টিভঙ্গি থাকে। যদি তা হয়, পেজ.পপুলেটভিউ () কে কল করুন। যদি তা না হয়, তবে পুনরায় লোডফর্ম পতাকাটি সেট করুন।

এর পরে, যখন আপনি পৃষ্ঠাগুলির দ্বিতীয় সেটটি পুনরায় লোড করবেন, তবুও বাগটি কারও কারও পুরানো ডেটা প্রদর্শন করার কারণ ঘটবে। তবে এগুলি এখন সতেজ করা হবে এবং আপনি নতুন ডেটা দেখতে পাবেন - আপনার ব্যবহারকারীরা পৃষ্ঠাটি কখনই ভুল ছিল তা জানেন না কারণ তারা পৃষ্ঠাটি দেখার আগে এই রিফ্রেশটি ঘটবে।

আশা করি এটি কাউকে সাহায্য করবে!


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। আরো দেখুন stackoverflow.com/a/25994654/2914140 একটি হল hacky উপায় জন্য।
কুলমাইন্ড

5

একটি খুব সহজ উপায়: একটি ব্যবহার করুন FragmentPagerAdapterএবং আপনার পৃষ্ঠাগুলি দর্শন টুকরো টুকরো টুকরো টুকরো টুকরো টুকরো টুকরো টুকরো টুকরো টুকরো টুকরো টুকরো টুকরো টুকরো টুকরো টুকরো টুকরো টুকরো টুকরো টুকরো করার জন্য। তারা আপডেট হয়


5

রুই.আরাউজো এবং আলভারো লুইস বুস্তামন্তকে ধন্যবাদ। প্রথমে আমি রুই.আরউজোর উপায় ব্যবহার করার চেষ্টা করি, কারণ এটি সহজ। এটি কাজ করে কিন্তু যখন ডেটা পরিবর্তন হবে, পৃষ্ঠাটি স্পষ্টতই আবার চিত্রিত হবে। এটি খারাপ তাই আমি আলভারো লুইস বুস্তামন্তের উপায়টি ব্যবহার করার চেষ্টা করি। এইটা ঠিক আছে. কোডটি এখানে:

@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

কেবলমাত্র কেউ যদি ফ্র্যাগমেন্টস্টেটপেজারএডাপ্টার ব্যবহার করছে ভিত্তিক অ্যাডাপ্টার (যা ভিউপেজারটি আমার প্রয়োজনে সর্বাধিক 2 টি প্রদর্শনের উদ্দেশ্যে প্রয়োজনীয় ন্যূনতম পৃষ্ঠাগুলি তৈরি করতে দেয়), @ রুই.আরউজোর উত্তর ওভাররাইটিংয়ের আইটেমপজিশনের উত্তর উল্লেখযোগ্য বর্জ্য সৃষ্টি করবে না, তবে এটি এখনও উন্নত করা যেতে পারে।

সিউডো কোডে:

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()ডেটাসেট পরিবর্তিত হলে নতুন অবস্থানটি ফিরে আসে এবং ভিউপাগার জানতে পারবে যে তারা পরিবর্তন হয়েছে কি না। দুঃখের বিষয়, ভিউপেজার এটি করেনি।
ভিন্স স্টাইলিং

3

আমার একই ধরণের সমস্যা ছিল যার মধ্যে আমার চারটি পৃষ্ঠা এবং অন্য একটিতে পৃষ্ঠাগুলির আপডেট ভিউ রয়েছে। আমি বর্তমান পৃষ্ঠার সংলগ্ন পৃষ্ঠায় উইজেটগুলি (সিকবারস, টেক্সটভিউস, ইত্যাদি) আপডেট করতে সক্ষম হয়েছি। কল করার সময় শেষ দুটি পৃষ্ঠায় অবিচ্ছিন্ন উইজেট থাকবে mTabsAdapter.getItem(position)

আমার সমস্যা সমাধানের জন্য, আমি setSelectedPage(index)কল করার আগে ব্যবহার করেছি getItem(position)। এটি পৃষ্ঠাটি ইনস্ট্যান্ট করবে, আমাকে প্রতিটি পৃষ্ঠায় মান এবং উইজেটগুলি পরিবর্তন করতে সক্ষম করে।

সমস্ত আপডেট করার পরে আমি setSelectedPage(position)অনুসরণ করব notifyDataSetChanged()

আপনি প্রধান আপডেটিং পৃষ্ঠায় তালিকাভিউতে একটি সামান্য ঝাঁকুনি দেখতে পাচ্ছেন, তবে কিছুই লক্ষ্যণীয় নয়। আমি এটির মাধ্যমে পরীক্ষা করে দেখিনি, তবে এটি আমার তাত্ক্ষণিক সমস্যার সমাধান করে।


হাই, আমি আপনার কোডে আগ্রহী, আমি একই ধরণের সমস্যার মুখোমুখি হয়েছি, আমি সংলগ্ন খণ্ডগুলি আপডেট করতে সক্ষম হয়েছি তবে বর্তমান খণ্ডটি যা দৃশ্যমান তা আপডেট হয় না। আমি এখানে সমস্ত উত্তর সঙ্গে খুব বিভ্রান্ত। ভিউপেজার অ্যাডাপ্টারের দ্বারা দেখানো বর্তমান খণ্ডে আমি কীভাবে ভিউগুলি আপডেট করতে পারি
পঙ্কজ নিমগাদ

3

অন্য কারও পক্ষে এটি দরকারী মনে হলে আমি এই উত্তরটি পোস্ট করছি। ঠিক একই জিনিসটি করার জন্য, আমি কেবল সামঞ্জস্যের লাইব্রেরি থেকে ভিউপ্যাজার এবং পেজারআডাপ্টারের উত্স কোডটি নিয়েছি এবং এটি আমার কোডের মধ্যে সংকলিত করেছি (আপনাকে সমস্ত ত্রুটিগুলি বাছাই করে নিজেকে আমদানি করতে হবে, তবে এটি অবশ্যই করা যেতে পারে)।

তারপরে, কাস্টমভিউপাগারে, আপডেটভিউএট (ইনট পজিশন) নামে একটি পদ্ধতি তৈরি করুন। ভিউপেজার ক্লাসে সংজ্ঞায়িত অ্যারেলিস্ট মিটেমগুলি থেকে ভিউটি নিজেই অর্জন করতে পারে (ইনস্ট্যান্ট আইটেমের জন্য আপনাকে ভিডির জন্য একটি আইডি সেট করতে হবে এবং আপডেটভিউএটি () পদ্ধতিতে অবস্থানের সাথে এই আইডি তুলনা করতে হবে)। তারপরে আপনি প্রয়োজনীয় হিসাবে ভিউ আপডেট করতে পারেন।


2

আমার ধারণা, আমি ভিউপাগারের লজিক্স পেয়েছি।

আমার যদি পৃষ্ঠাগুলির একটি সেট রিফ্রেশ করার প্রয়োজন হয় এবং সেগুলি নতুন ডেটাসেটের উপর ভিত্তি করে প্রদর্শন করা হয় তবে আমি notifyDataSetChanged () কল করি । তারপরে, ভিউপ্যাজারটি আইটেম পজিশনে () বেশ কয়েকটি কল করে , সেখানে অবজেক্ট হিসাবে খণ্ডিত হয়ে যায় । এই খণ্ডটি হয় পুরানো ডেটাसेट থেকে (যেটি আমি বাতিল করতে চাই) বা কোনও নতুন থেকে (যা আমি প্রদর্শন করতে চাই) হতে পারি। সুতরাং, আমি আইটেম পজিশন () কে ওভাররাইড করব এবং সেখানে আমার ফ্রেমটি পুরানো ডেটাसेट থেকে বা নতুনটির থেকে কোনওভাবে নির্ধারণ করতে হবে।

আমার ক্ষেত্রে আমার কাছে বাম ফলকের শীর্ষ আইটেমের একটি তালিকা এবং ডানদিকে একটি সোয়াইপ ভিউ (ভিউপেজার) সহ একটি 2-ফলক বিন্যাস রয়েছে। সুতরাং, আমি আমার পেজারআডাপ্টারের ভিতরে এবং প্রতিটি তাত্ক্ষণিকৃত পৃষ্ঠাগুলির ভিতরে আমার বর্তমান শীর্ষ আইটেমের একটি লিঙ্ক সঞ্চয় করি তালিকার নির্বাচিত শীর্ষ আইটেমটি পরিবর্তন হয়ে গেলে আমি পেজারআডাপ্টারে নতুন শীর্ষ আইটেমটি সংরক্ষণ করি এবং কল করি পেজারআডাপ্টারে নোটিফাইডাটাসেট চেঞ্জড () করি । এবং ওভাররাইড হওয়া আইটেম পজিশনে () আমি আমার অ্যাডাপ্টার থেকে শীর্ষ আইটেমটি আমার খণ্ড থেকে শীর্ষ আইটেমের সাথে তুলনা করি। এবং যদি তারা সমান না হয় তবেই আমি POSITION_NONE প্রত্যাবর্তন করব। তারপরে, পেজারআডাপ্টার 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

নীচের কোডটি আমার পক্ষে কাজ করেছিল।

নীচে যেমন ফ্রেগমেন্টপেজারএডাপ্টার শ্রেণি প্রসারিত করে এমন একটি শ্রেণী তৈরি করুন।

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

তারপরে আপনি তৈরি প্রতিটি ফ্রেমের ভিতরে একটি আপডেটফ্র্যাগমেন্ট পদ্ধতি তৈরি করুন। এই পদ্ধতিতে আপনি খণ্ডগুলিতে যে জিনিসগুলি পরিবর্তন করতে হবে তা পরিবর্তন করুন। উদাহরণস্বরূপ, আমার ক্ষেত্রে, ফ্র্যাগমেন্ট0-তে একটি জিএলসুরফেসভিউ রয়েছে যা একটি প্লাই ফাইলের পাথের উপর ভিত্তি করে একটি 3 ডি অবজেক্ট প্রদর্শন করে, তাই আমার আপডেটফ্র্যাগমেন্ট পদ্ধতির ভিতরে আমি এই প্লাই ফাইলটির পথ পরিবর্তন করি।

তারপরে একটি ভিউপাগার উদাহরণ তৈরি করুন,

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

এবং একটি অ্যাডপ্যাটার উদাহরণ,

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

তাহলে এটি কর,

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

তারপরে শ্রেণীর অভ্যন্তরে কি আপনি উপরের অ্যাডাপ্টারের ক্লাসটি শুরু করেছিলেন এবং একটি ভিউপেজার তৈরি করেছিলেন, প্রতিবার আপনি আপনার খণ্ডগুলির একটি আপডেট করতে চান (আমাদের ক্ষেত্রে ফ্রেগমেন্ট0) নিম্নলিখিতটি ব্যবহার করুন:

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 পদ্ধতিটি সেট করতে হবে ২. আপনার ভিউ পেজারের সঠিক অবস্থানটি পড়তে হবে 3. তারপরে আপনার নতুন একের ডেটা অবস্থান হিসাবে সেই অবস্থানটি প্রেরণ করুন set.সেটনপেজ চেঞ্জের অভ্যন্তরে লিখিত আপডেট বোতামটিতে ক্লিক করুন শ্রোতা শ্রোতা

প্রোগ্রামের কোডটি কেবলমাত্র নির্দিষ্ট অবস্থানের উপাদানটি সেট করতে আমি কিছুটা সংশোধন করেছি

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সহজ তবে কিছুটা অদক্ষ উপায় কারণ এটি ইতিমধ্যে তাত্ক্ষণিকভাবে থাকা সমস্ত পৃষ্ঠার তাত্পর্যকে ডেকে আনে।

পেজারআডাপ্টারগুলিতে গতিশীল পরিবর্তন করতে আমি একটি লাইব্রেরি অ্যারেপেইজারএডাপ্টার তৈরি করেছি ।

অভ্যন্তরীণভাবে, এই লাইব্রেরি এর অ্যাডাপ্টার আসতে 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;
    }
}

থিলস লাইব্রেরি এছাড়াও টুকরো দ্বারা তৈরি পৃষ্ঠাগুলি সমর্থন করে।


1

এটি আমার মতো সকলের জন্য, যাদের কোনও পরিষেবাদি (বা অন্যান্য পটভূমি থ্রেড) থেকে ভিউপিজার আপডেট করা দরকার এবং কোনও প্রস্তাবই কাজ করেনি: লগ-চেক করার পরে আমি বুঝতে পেরেছি, বিজ্ঞপ্তিডেটসেট চেঞ্জড () পদ্ধতিটি কখনই ফিরে আসে না। গেটআইটেম পজিশন (অবজেক্ট অবজেক্ট) কে আরও প্রক্রিয়াজাতকরণ ছাড়াই সেখানে একটি সমস্ত প্রান্ত বলা হয়। তারপরে আমি পিতামাতার পেজারএডাপ্টার ক্লাসের ডকগুলিতে (সাবক্লাসের ডক্সগুলিতে নেই) খুঁজে পেয়েছি, "ডেটা সেট পরিবর্তনগুলি অবশ্যই মূল থ্রেডে উপস্থিত থাকতে হবে এবং অবশ্যই ডেটাসেট চেঞ্জড () অবধি কল করতে হবে" with সুতরাং, এই ক্ষেত্রে কার্যনির্বাহী সমাধানটি ছিল (ফ্রেগমেন্টস্টেটপেজারএডাপ্টার এবং গেট আইটেম পজিশন (অবজেক্ট অবজেক্ট) POSITION_NONE ফেরতের জন্য সেট করা):

এবং তারপরে ডেটাসেট চেঞ্জড ()- কে কল করতে হবে:

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

1

আপনি এর মতো ভিউপ্যাজে পেজার ট্রান্সফর্ম যুক্ত করতে পারেন

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

ভিউপ্যাজারটি ডায়নামিক ভিউ পরিবর্তনকে সমর্থন করার জন্য তৈরি করা হয়নি।

Https://issuetracker.google.com/issues/36956111 এবং বিশেষত এই সম্পর্কিত অন্য কোনও বাগ সন্ধান করার সময় আমার এর নিশ্চয়তা ছিল https://issuetracker.google.com/issues/36956111#comment56

এই প্রশ্নটি কিছুটা পুরানো, তবে গুগল সম্প্রতি ভিউপ্যাজার 2 দিয়ে এই সমস্যাটি সমাধান করেছে । এটি হস্তনির্মিত (অবিস্মৃত এবং সম্ভাব্য বগী) সমাধানগুলি কোনও মানক দ্বারা প্রতিস্থাপন করার অনুমতি দেবে। এটি কিছু উত্তর হিসাবে অযথা দৃষ্টিভঙ্গি পুনরায় পুনরুদ্ধারকেও প্রতিরোধ করে।

ভিউপেজার ২ উদাহরণগুলির জন্য, আপনি পরীক্ষা করতে পারেন https://github.com/googlesferences/android-viewpager2

আপনি যদি ভিউপেজার 2 ব্যবহার করতে চান তবে আপনার বিল্ড.gradle ফাইলটিতে আপনাকে নিম্নলিখিত নির্ভরতা যুক্ত করতে হবে:

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

তারপরে আপনি আপনার এক্সএমএল ফাইলটিতে আপনার ভিউপাগারটি প্রতিস্থাপন করতে পারেন:

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

এর পরে, আপনার ক্রিয়াকলাপে আপনাকে ভিউপ্যাজার 2 দ্বারা ভিউপেজার প্রতিস্থাপন করতে হবে

ভিউপাগের 2 এর একটি হয় একটি রিসাইক্লারভিউ প্রয়োজন dএডাপ্টার, বা ফ্রেগমেন্টস্টেট অ্যাডাপ্টার, আপনার ক্ষেত্রে এটি একটি পুনর্ব্যবহারযোগ্য ভিউএডাপ্টার হতে পারে

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

আপনি যদি ট্যাবলআউট ব্যবহার করছিলেন তবে আপনি একটি ট্যাবলেটআউটমিডিয়েটর ব্যবহার করতে পারেন:

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

তারপরে আপনি আপনার অ্যাডাপ্টারের ডেটা পরিবর্তন করে এবং notifyDataSetChanged পদ্ধতিতে কল করে আপনার মতামতগুলি রিফ্রেশ করতে সক্ষম হবেন



0

আমি মনে করি আমি ডেটা সেট পরিবর্তনগুলি অবহিত করার একটি সহজ উপায় করেছি:

প্রথমে ইনস্ট্যান্টিয়েট আইটেম ফাংশনটি যেভাবে কাজ করে তাতে কিছুটা পরিবর্তন করুন:

    @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এবং এটি কাজ করে .. অন্যান্য সমাধানের মধ্যে কেউই আমার জন্য কাজ করেন।


আসল প্রশ্নটি প্রায় ২ বছর পুরানো, আমি নিশ্চিত এখনই অ্যান্ড্রয়েড এপিআইতে অনেক পার্থক্য রয়েছে যে এখানে উত্তরগুলি অ্যান্ড্রয়েড এপিআইয়ের সমস্ত সংস্করণের জন্য সঠিক নাও হতে পারে।
C0deAttack
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.