[Android] تحديث ViewPager بشكل حيوي؟


Answers

بدلاً من إرجاع POSITION_NONE من getItemPosition() والتسبب في استخدام العرض الكامل ، قم بما يلي:

//call this method to update fragments in ViewPager dynamically
public void update(UpdateData xyzData) {
    this.updateData = xyzData;
    notifyDataSetChanged();
}

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

يجب أن تقوم الأجزاء الخاصة بك بتطبيق واجهة UpdateableFragment :

public class SomeFragment extends Fragment implements
    UpdateableFragment{

    @Override
    public void update(UpdateData xyzData) {
         // this method will be called for every fragment in viewpager
         // so check if update is for this fragment
         if(forMe(xyzData)) {
           // do whatever you want to update your UI
         }
    }
}

والواجهة:

public interface UpdateableFragment {
   public void update(UpdateData xyzData);
}

فئة البيانات الخاصة بك:

public class UpdateData {
    //whatever you want here
}
Question

لا يمكنني تحديث المحتوى في ViewPager.

سؤال: ما هي العلاقة والاستخدام الصحيح للوسائل instantiateItem () و getItem () في فئة FragmentPagerAdapter؟

كنت أستخدم فقط getItem () لتكوين وإرجاع الأجزاء الخاصة بي:

@Override
public Fragment getItem(int position) {
    return new MyFragment(context, paramters);
}

هذا عمل جيد (ولكن كما قلت لا أستطيع تغيير المحتوى).

لذلك وجدت هذا: ViewPager PagerAdapter لا تحديث العرض

واحدة خاصة تحدثت فيها عن طريقة instantiateItem ():

"يعد الأسلوب الخاص بي هو استخدام أسلوب setTag () لأي عرض تم إنشاؤه في طريقة instantiateItem ()"

حتى الآن أريد تطبيق instantiateItem () من أجل القيام بذلك. ولكن لا أعرف ما يجب أن أعود إليه (الإرجاع هو كائن) وما هي العلاقة مع getItem (int int)؟

حاليًا ، أستخدم getItem لإنشاء الجزء ، هل هذا خطأ؟ ولكن بعد ذلك يجب علي وضع الأجزاء في متغير المثال ، أو عدم تطبيق getItem () على الإطلاق ...؟ أنا لا أفهم ذلك.

حاولت قراءة reference :

  • مجردة عمومية جزء من الدالة getItem (موقع int)

    إرجاع الجزء المرتبط بموضع معين.

  • كائن عام instantiateItem (حاوية ViewGroup ، موضع int)

    قم بإنشاء الصفحة الخاصة بالموضع المحدد. يعتبر المهايئ مسؤولاً عن إضافة العرض إلى الحاوية الممنوحة هنا ، على الرغم من أنه يجب التأكد من أن ذلك يتم فقط من خلال الوقت الذي يعود إليه من إنهاء التحديث (ViewGroup). المعلمات

    الحاوية المحتوية على عرض والتي سيتم عرض الصفحة بها. position موضع الصفحة المراد إنشاء مثيل لها.

    عائدات

    إرجاع كائن يمثل الصفحة الجديدة. لا يحتاج هذا إلى عرض ، ولكن يمكن أن يكون هناك حاوية أخرى للصفحة.

... ولكن ما زلت لا أفهم كيف ترتبط وماذا يجب أن أفعل.

وهنا الكود. أنا أستخدم حزمة الدعم v4.

ViewPagerTest

public class ViewPagerTest extends FragmentActivity {
    private ViewPager pager;
    private MyFragmentAdapter adapter; 

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

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

        String[] data = {"page1", "page2", "page3", "page4", "page5", "page6"};

        adapter = new MyFragmentAdapter(getSupportFragmentManager(), 6, this, data);
        pager.setAdapter(adapter);

        ((Button)findViewById(R.id.button)).setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                reload();
            }
        });
    }

    private void reload() {
        String[] data = {"changed1", "changed2", "changed3", "changed4", "changed5", "changed6"};
        //adapter = new MyFragmentAdapter(getSupportFragmentManager(), 6, this, data);
        adapter.setData(data);
        adapter.notifyDataSetChanged();
        pager.invalidate();

        //pager.setCurrentItem(0);
    }
}

MyFragmentAdapter

class MyFragmentAdapter extends FragmentPagerAdapter {
    private int slideCount;
    private Context context;
    private String[] data;

    public MyFragmentAdapter(FragmentManager fm, int slideCount, Context context, String[] data) {
        super(fm);
        this.slideCount = slideCount;
        this.context = context;
        this.data = data;
    }

    @Override
    public Fragment getItem(int position) {
        return new MyFragment(data[position], context);
    }

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

    public void setData(String[] data) {
        this.data = data;
    }

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

MyFragment

public final class MyFragment extends Fragment {
    private String text;

    public MyFragment(String text, Context context) {
        this.text = text;
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.slide, null);
        ((TextView)view.findViewById(R.id.text)).setText(text);

        return view;
    }
}

هنا أيضا شخص ما لديه مشكلة مماثلة ، لا توجد إجابات ...

http://www.mail-archive.com/android-developers@googlegroups.com/msg200477.html




الإجابة المقبولة لا تفهم ، هذا هو السبب في إضافة حل سهل. ايجاد حل العمل.

فقط أخبر المحول ، إنه يعمل بشكل رائع ،

رمز المرجع

 void setAdapter(int position) {
        PagerAdapter pagerAdapter = new PagerAdapter(getSupportFragmentManager());
        viewPager.setAdapter(pagerAdapter);
        // when notify then set manually current position.
        viewPager.setCurrentItem(position);
        pagerAdapter.notifyDataSetChanged();
    }

استدعاء هذا الرمز عند تعيين المحول وعندما تريد تحديث واجهة المستخدم.

في الجزء الخاص بك ، أضف هذا الرمز للتحديث استخدم exampleof لسياق الإرسال.

((YourActivityName) getContext()).setAdapter(selectedTabPosition);

يشترك هذا الرمز فقط في الغرض من العثور على حل عملي ، نأمل أن يكون مفيدًا!




عدلت قليلاً من الحل الذي قدمه Bill Phillips ليتناسب مع احتياجاتي

private class PagerAdapter extends FragmentStatePagerAdapter{
    Bundle oBundle;
    FragmentManager oFragmentManager;
    ArrayList<Fragment> oPooledFragments;

public PagerAdapter(FragmentManager fm) {
    super(fm);
    oFragmentManager=fm;

    }
@Override
public int getItemPosition(Object object) {

    Fragment oFragment=(Fragment)object;
    oPooledFragments=new ArrayList<>(oFragmentManager.getFragments());
    if(oPooledFragments.contains(oFragment))
        return POSITION_NONE;
    else
        return POSITION_UNCHANGED;
    } 
}

بحيث يقوم getItemPosition() بارجاع POSITION_NONE فقط لتلك الأجزاء الموجودة حاليا في FragmentManager عندما يتم استدعاء getItemPosition . (لاحظ أن هذا FragmentStatePager و ViewPager المرتبط به ViewPager في جزء لا في نشاط)







لأولئك الذين ما زالوا يواجهون نفس المشكلة التي واجهتها من قبل عندما يكون لدي ViewPager مع 7 أجزاء. الإعداد الافتراضي لهذه الأجزاء لتحميل المحتوى باللغة الإنجليزية من خدمة واجهة برمجة التطبيقات ولكن المشكلة هنا هي أنني أريد تغيير اللغة من نشاط الإعدادات وبعد الانتهاء من نشاط الإعدادات ، أريد عرض ViewPager في النشاط الرئيسي لتحديث الأجزاء لمطابقة اختيار اللغة من المستخدم وتحميل المحتوى العربي إذا اختار المستخدم اللغة العربية هنا ما فعلت للعمل من أول مرة

1- يجب عليك استخدام FragmentStatePagerAdapter كما هو مذكور أعلاه.

2-on mainActivity i override the onResume وقمنا بما يلي

 if (!(mPagerAdapter == null)) {
mPagerAdapter.notifyDataSetChanged();
}

3-i overrided the getItemPosition () in mPagerAdapter وإرجاعه POSITION_NONE.

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

يعمل مثل السحر




لقد عشت نفس المشكلة ولقد بحثت كثيرا من المرات. أي إجابة في أو عبر google لم تكن الحل لمشكلتي. كانت مشكلتي سهلة. لدي قائمة ، وأظهر هذه القائمة مع viewpager. عندما أقوم بإضافة عنصر جديد لرأس القائمة وقمت بتحديث تغيرات أنماط العرض. كان حلّي النهائي سهلًا جدًا يمكن لأي شخص استخدامه. عند إضافة عنصر جديد إلى القائمة وترغب في تحديث القائمة. أولا تعيين viewpager محول إلى الصفر ثم إعادة إنشاء محول وتعيين i إلى viewpager.

myVPager.setAdapter(null);
myFragmentAdapter = new MyFragmentAdapter(getSupportFragmentManager(),newList);
myVPager.setAdapter(myFragmentAdapter);

تأكد من أن المحول يجب أن يمد FragmentStatePagerAdapter




لن يعمل هذا الحل مع الجميع ، ولكن في حالتي ، كل جزء في ViewPager هو فئة مختلفة ، ولا يوجد سوى واحد منهم في وقت واحد.

مع هذا القيد ، هذا الحل آمن ويجب أن يكون آمنًا للاستخدام في الإنتاج.

private void updateFragment(Item item) {

    List<Fragment> fragments = getSupportFragmentManager().getFragments();
    for (Fragment fragment : fragments) {

        if (fragment instanceof MyItemFragment && fragment.isVisible()) {
            ((MyItemFragment) fragment).update(item);
        }

    }
}

إذا كان لديك إصدارات متعددة من نفس الجزء ، فيمكنك استخدام نفس الاستراتيجية لاستدعاء الطرق على تلك الأجزاء لتحديد ما إذا كانت هي الجزء الذي ترغب في تحديثه.




لقد كنت أحاول العديد من الطرق المختلفة ، ولم يكن أي من مشكلاتي حقيقيًا. وفيما يلي كيف أقوم بحلها بمزيج من الحلول التي تقدمها لك جميعًا. شكرا لكم جميعا.

class PagerAdapter extends FragmentPagerAdapter {

    public boolean flag_refresh=false;

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

    @Override
    public Fragment getItem(int page) {
        FragmentsMain f;
        f=new FragmentsMain();
        f.page=page;
        return f;
    }

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

    @Override
    public int getItemPosition(Object item) {
        int page= ((FragmentsMain)item).page;

        if (page == 0 && flag_refresh) {
            flag_refresh=false;
            return POSITION_NONE;
        } else {
            return super.getItemPosition(item);
        }
    }

    @Override
    public void destroyItem(View container, int position, Object object) {

        ((ViewPager) container).removeView((View) object);
    }
}

أريد فقط تحديث الصفحة 0 بعد onResume ().

 adapter=new PagerAdapter(getSupportFragmentManager());
 pager.setAdapter(adapter);

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

    if (adapter!=null) {
        adapter.flag_refresh=true;
        adapter.notifyDataSetChanged();
    }
}

في My FragmentsMain ، هناك "صفحة" صحيحة عامة ، والتي يمكن أن تخبرني ما إذا كانت هي الصفحة التي أريد تحديثها.

public class FragmentsMain extends Fragment {

private Cursor cursor;
private static Context context;
public int page=-1;



بعد ساعات من الإحباط أثناء محاولة جميع الحلول المذكورة أعلاه للتغلب على هذه المشكلة وأيضا محاولة العديد من الحلول على أسئلة أخرى مماثلة مثل this ، this كل ما فشل معي لحل هذه المشكلة وجعل ViewPager لتدمير Fragment القديم وملء pager مع Fragment جديد s. لقد حلت المشكلة على النحو التالي:

1) جعل فئة ViewPager تمتد إلى FragmentPagerAdapter النحو التالي:

 public class myPagerAdapter extends FragmentPagerAdapter {

2) إنشاء عنصر لـ ViewPager بتخزين title ViewPager كما يلي:

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 يأخذ 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();

اتمني ان يكون مفيدا.