ViewPager PagerAdapter Görünümü güncellemiyor


597

ViewPager'i uyumluluk kitaplığından kullanıyorum. Ben başarılı bir şekilde hangi sayfa aracılığıyla görüntüleyebilirsiniz birkaç görüntüleme görüntüleme var.

Ancak, ViewPager'ı yeni bir Görünümler kümesiyle nasıl güncelleyeceğinizi anlamakta zorlanıyorum.

Yeni bir Veri Listesi kullanmak istediğim her seferinde arama yapmak mAdapter.notifyDataSetChanged(), mViewPager.invalidate()hatta yeni bir adaptör oluşturmak gibi her türlü şeyi denedim .

Hiçbir şey yardımcı olmadı, metin görünümleri orijinal verilerden değişmeden kaldı.

Güncelleme: Küçük bir test projesi yaptım ve neredeyse görüşleri güncelleyebildim. Sınıfı aşağıya yapıştıracağım.

Bununla birlikte, güncellenen görünmeyen 2. görünümdür, 'B' kalır, güncelleme düğmesine bastıktan sonra 'Y' göstermelidir.

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 ile ilgili bir hata için lütfen stackoverflow.com/questions/12510404/… adresine bakın .
samis

2
Bunu araştırdığım için üzgünüm. Sorunuz bana gerçekten yardımcı oldu, teşekkürler! Ben alamadım bir şey PagerAdapter veri referans Faaliyet
Ewanw

Adaptörünüzü

1
Görünüşe göre adaptörü tekrar görünüm çağrı cihazınıza ayarlarsanız sıfırlanır.
16:27, EpicPandaForce

çağrı
chris

Yanıtlar:


856

Bunu başarmanın birkaç yolu vardır.

İlk seçenek daha kolay, ancak biraz daha verimsiz.

Geçersiz Kıl getItemPositionsizin de PagerAdapterböyle:

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

Bu şekilde, aradığınızda notifyDataSetChanged()görünüm çağrı cihazı tüm görünümleri kaldırır ve tümünü yeniden yükler. Böylece yeniden yükleme etkisi elde edilir.

İkinci seçenek, Alvaro Luis Bustamante (daha önce alvarolb) tarafından önerildiği , etmektir setTag()içinde yöntemin instantiateItem()yeni bir görünüm başlatmasını. Ardından kullanmak yerine, güncellemek istediğiniz görünümü bulmak için notifyDataSetChanged()kullanabilirsiniz findViewWithTag().

İkinci yaklaşım çok esnek ve yüksek performanslı. Orijinal araştırma için alvarolb şeref.


4
Etrafımdaki çalışmalardan daha iyi, herhangi bir yan etkisi yok gibi görünüyor, teşekkürler.
C0deAttack

3
Benzer bir sorunum var. ViewPager'im yeni arama sonuçlarını gösterecek, ancak varsayılan olarak imleçteki ilk girişe dönmeyecektir. Veri kümesini güncellerken pozisyonun nasıl sıfırlanacağını bilen var mı?
mAndroid

1
@mAndroid daha fazla ayrıntı içeren ayrı bir soru göndermelisiniz.
rui.araujo

1
POSITION_NONE değerini döndürmek, Android'in sorgulanan konumla ilişkili görünümü silmesine neden olduğu için genel uygulamaya çok fazla verimsizlik ekliyor. Ardından, görüntülenmeden önce görünümün yeniden oluşturulması gerekir. Görünümlerin güncellenmemesi sorununu çözer, ancak muhtemelen karmaşık düzenler için en iyi çözüm değildir.
wufoo

11
Daha iyi yanıt (tüm öğeleri çıkarmadan) -> stackoverflow.com/a/10852046/898056
yhpark

484

İçinde herhangi bir hata olduğunu sanmıyorum PagerAdapter. Sorun şu ki, nasıl çalıştığını anlamak biraz karmaşık. Burada açıklanan çözümlere bakıldığında, yanlış görüş ve dolayısıyla anlık görüşlerin benim açımdan yetersiz kullanımı söz konusudur.

Son birkaç gündür birlikte çalışıyorum PagerAdapterve şunları ViewPagerbuldum:

Üzerindeki notifyDataSetChanged()yöntem PagerAdapteryalnızca ViewPagertemel sayfaların değiştiğini bildirir. Örneğin, sayfaları dinamik olarak oluşturduysanız / sildiyseniz (listenize öğe ekleyerek veya listenizden öğe kaldırarak) ViewPagerbununla ilgilenmelidir. Bu durumda ViewPageryeni bir görünümün getItemPosition()ve getCount()yöntemleri kullanılarak silinip silinmeyeceğini belirler .

Bence ViewPager, bir notifyDataSetChanged()çağrı alındıktan sonra çocuk görüşlerini ve konumunu kontrol eder getItemPosition(). Bir alt görünüm için bu yöntem döndürülürse POSITION_NONE, ViewPagergörünümün silindiğini, çağrıldığını destroyItem()ve bu görünümün kaldırıldığını anlar .

Bu şekilde, yalnızca sayfaların içeriğini güncellemek istiyorsanız getItemPosition()her zaman geri dönmek POSITION_NONEiçin geçersiz kılma tamamen yanlıştır, çünkü önceden oluşturulan görünümler yok edilir ve her aradığınızda yenileri oluşturulur notifyDatasetChanged(). Sadece birkaç TextViewsaniye boyunca o kadar da yanlış görünmeyebilir , ancak bir veritabanından alınan ListView'ler gibi karmaşık görünümleriniz olduğunda, bu gerçek bir sorun ve kaynak israfı olabilir.

Bu nedenle, bir görünümün içeriğini, görünümü yeniden kaldırmaya ve yeniden başlatmaya gerek kalmadan verimli bir şekilde değiştirmek için birkaç yaklaşım vardır. Çözmek istediğiniz soruna bağlıdır. Benim yaklaşım setTag()yöntem yöntem herhangi bir anlık görünüm için kullanmaktır instantiateItem(). Bu nedenle, verileri değiştirmek istediğinizde veya ihtiyacınız olan görünümü geçersiz kılmak istediğinizde , önceden başlatılmış görünümü almak ve istediğiniz her seferinde yeni bir görünüm silmek / oluşturmak zorunda kalmadan istediğiniz gibi değiştirmek / kullanmak için findViewWithTag()yöntemi çağırabilirsiniz. ViewPagerbazı değerleri güncellemek için.

Eğer 100 ile 100 sayfaları var olduğunu, örneğin düşünün TextViews ve sadece periyodik bir değeri güncellemek istiyorum. Daha önce açıklanan yaklaşımlarla, bu TextView, her güncellemede 100 saniyeyi kaldırdığınız ve somutlaştırdığınız anlamına gelir . Mantıklı değil...


11
+1 - Çözümünüz sadece liste görünümleri, metin görünümleri ve resimler içeren bir sekme içeren sayfaları güncellemem gerektiğinde tam olarak burada açıkladığım sorunla karşılaştığım bir cazibe gibi çalışmıyor. (OutOfErrorExceptions ve benzeri ...) Teşekkürler!
schlingel

3
@alvarolb: Merhaba, setTagyöntemde ne demek istediğini gerçekten bilmiyorum onInstantiateItem, Bu cevabı bazı kodlarla güncellemek ister misin? Teşekkürler.
Huy Kulesi

35
Bir örnek yazsaydınız mükemmel olurdu.
Sami Eltamawy

13
Birinin dediği gibi: bir örnek takdir edilecektir!
Jey10

15
6 yıl sonra kimse örnek veremez.
Oussaki

80

Değişim FragmentPagerAdapterTo FragmentStatePagerAdapter.

getItemPosition()Yöntemi geçersiz kıl ve döndür POSITION_NONE.

Sonunda, notifyDataSetChanged()görünüm çağrı cihazını dinleyecektir .


Tüm getItemPosition'ı düzgün bir şekilde uygulamanız ve parça bulunmazsa POSITION_NONE döndürmeniz gerektiğini düşünüyorum.
tkhduracell

46

Alvarolb tarafından verilen cevap kesinlikle bunu yapmanın en iyi yoludur. Cevabını temel alarak, bunu uygulamanın kolay bir yolu, aktif görünümleri konuma göre depolamaktır:

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

Daha sonra notifyDataSetChangedyöntemi geçersiz kılarak görünümleri yenileyebilirsiniz ...

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

Görünümünüzde instantiateItemve notifyDataSetChangediçinde yenilemek için benzer kodu kullanabilirsiniz . Kodumda aynı yöntemi kullanıyorum.


8
tam bir adaptör örneği verebilir misiniz? Bu Parçalar kullanılarak mı yapılıyor yoksa yapılmıyor mu?

9
<görünümü yeni verilerle yenile> ?? bunun ne anlama geldiğini eklememiz gerek ya da hiçbir şey?
Akarsh M

Bu yöntem tüm görünümleri günceller. Yalnızca bir görünümü güncellemek istiyorsanız, kendi notifyDataItemChanged yönteminizi şu şekilde yazabilirsiniz: public void notifyDataItemChanged (int pos) {TextView tv = (TextView) views.get (pos) .findViewById (R.id.tv); tv.setText (list.get (pos)); ) (super.notifyDataSetChanged; }
Kai Wang

Yeni çağrı cihazı boyutu eski boyuttan küçükse bu kod çöküyor
Anton Duzenko

@AntonDuzenko doğru, görüşlerini silmek oldukça zordur.
MLProgrammer-CiM

28

Aynı sorun vardı. Benim için FragmentStatePagerAdapter genişletmek ve aşağıdaki yöntemleri geçersiz kılmak için çalıştı:

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

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

}

Bu benim için de işe yarayan tek çözüm. Benim durumum parçayı güncellemiyor, ancak parçaları dinamik olarak kaldırıyor ya da ekliyor. FragmentStatePagerAdapter genişletilmeden ViewPager, önbelleğe alınmış parçaları yanlış bir konuma döndürür. Teşekkürler!
Sira Lam

Destek kütüphanesinde iyi çalışıyor 28.0.0
Oleksii K.

Ne yapmak için geçersiz kıl? Bağdaştırıcı ile ilişkili bir durum nesnesi nasıl oluşturulur?
Phani Rithvij

Sağol kanka. Bu çözüm sadece işe yarıyor
Parthi

20

Hayal kırıklığı saat bu sorunun üstesinden gelmek için her şeyden çözümler çalışıyor ve aynı zamanda gibi diğer benzer sorular üzerine birçok çözümler çalışırken sonra bu , bu ve bu tüm bu sorunu çözmek için ve yapmak benimle BAŞARISIZ hangi ViewPagereski yok etmek Fragmentve dolgu pagerile yeni Fragments. Sorunu aşağıdaki gibi çözdüm:

1) Make ViewPageruzanır için sınıfını FragmentPagerAdapteraşağıdaki gibidir:

 public class myPagerAdapter extends FragmentPagerAdapter {

2) için bir madde oluşturma ViewPagersaklamak olduğunu titleve fragmentşu şekilde:

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) aşağıdaki gibi benim saklamak ViewPageriçin benim FragmentManagerörnek almak yapıcı olun class:

private FragmentManager mFragmentManager;
private ArrayList<PagerItem> mPagerItems;

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

4) Yeni listeden yeni ayarlamayı tekrar aşağıdaki gibi yapmak için , öncekini doğrudan kendisinden adaptersilerek yeni verilerle verileri yeniden ayarlamak için bir yöntem oluşturun :fragmentfragmentManageradapterfragment

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) Kaptan Activityveya Fragmentadaptörü yeni verilerle yeniden başlatmayın. Yeni verileri yöntemle setPagerItemsyeni verilerle aşağıdaki gibi ayarlayın:

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

Umut ediyorum bu yardım eder.


@Tomer karşılaştığınız sorun neydi?
Sami Eltamawy


9

Aynı sorunu vardı ve benim çözüm FragmentPagerAdaptergeçersiz kılma ile kullanıyor FragmentPagerAdapter#getItemId(int position):

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

Varsayılan olarak, bu yöntem öğenin konumunu döndürür. Sanırım değiştirilip değiştirilmediğini ViewPagerkontrol eder itemIdve yalnızca değiştirilmişse sayfayı yeniden oluşturur. Ancak geçersiz kılınmayan sürüm, itemIdsayfa gerçekten farklı olsa bile aynı konumu döndürür ve ViewPager, sayfanın bir tane olduğunu ve yeniden oluşturulması gerektiğini tanımlamaz.

Bunu kullanmak long idiçin her sayfa için gereklidir. Normalde benzersiz olması beklenir, ancak bu durumda, aynı sayfa için önceki değerden farklı olması gerektiğini öneririm. Bu nedenle, burada adaptörde veya rastgele tamsayılarda (geniş dağılımlı) sürekli sayıcı kullanmak mümkündür.

Ben bu konuda bir çözüm olarak belirtilen görüş Etiketler kullanmak yerine daha tutarlı bir yol olduğunu düşünüyorum. Ama muhtemelen tüm durumlar için değil.


1
Bu. Ben kontrol ettim: sadece POSITION_NONE yeterli değil. Harika cevabınız için teşekkürler! :)
Slava

Bu işlev, içinde bulunmuyor bile PagerAdapter. Bu hangi sınıf?
Saket

@Saket, haklısın, sınıfFragmentPagerAdapter
atlascoder

6

Bu sorunun çok ilginç bir kararını buldum. Tüm parçaları bellekte tutan FragmentPagerAdapter kullanmak yerine, her seferinde seçtiğimizde parçayı yeniden yükleyen FragmentStatePagerAdapter ( android.support.v4.app.FragmentStatePagerAdapter ) kullanabiliriz .

Her iki bağdaştırıcının gerçekleştirmeleri aynıdır. Yani, sadece " genişletmek için FragmentPagerAdapter " değiştirmek gerekir " FragmentStatePagerAdapter genişletmek "


iyi bir noktaya, fragman ilgili viewPager bellek sorunları çözmek için diğer yardımcı olacaktır
Ashu Kumar

Harika cevap, bu bana çok yardımcı oldu.
Sergio Marani

5

Bu sorunu araştırdıktan sonra, bunun için doğru yol olduğunu düşündüğüm gerçekten iyi bir çözüm buldum. Esasen, instantiateItem yalnızca görünüm başlatıldığında çağrılır ve görünüm yok edilmedikçe bir daha asla çağrılmaz (POSITION_NONE değerini döndürmek için getItemPosition işlevini geçersiz kıldığınızda olan budur). Bunun yerine, yapmak istediğiniz görünümü oluşturulan görünümleri kaydetmek ve bunları adaptöre güncellemek, başka birinin güncelleyebilmesi için bir get işlevi oluşturmak veya adaptörü (favorim) güncelleyen bir set işlevi oluşturmaktır.

Yani, MyViewPagerAdapter içine bir değişken ekleyin:

private View updatableView;

örneğinizde bir:

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

bu şekilde, görünümünüzü güncelleyecek bir işlev oluşturabilirsiniz:

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

Bu yardımcı olur umarım!


Verilerimi ayarlamadığımı fark ettim, instantiateItembu yüzden görüşlerim güncellenmiyordu. Cevabınızdan anladım. +1
Phani Rithvij

5

OP sorusunu sorduktan iki buçuk yıl sonra, bu konu hala, hala bir konudur. Google'ın bu konudaki önceliği özellikle yüksek değil, bu yüzden bir düzeltme bulmak yerine bir geçici çözüm buldum. Benim için büyük atılım, sorunun gerçek nedeninin ne olduğunu bulmaktı ( bu yazıdaki kabul edilen cevaba bakınız ). Sorunun, etkin sayfaların düzgün bir şekilde yenilenmediği açık olduğunda, geçici çözümüm açıktı:

Parçamda (sayfalar):

  • OnCreateView formu doldurur tüm kodu aldı ve çerçeve yerine, her yerden çağrılabilir PopulateForm adlı bir işlev koymak. Bu işlev getView kullanarak geçerli Görünümü elde etmeye çalışır ve bu null ise, sadece geri döner. PopulateForm öğesinin yalnızca görüntülenen kodu içermesi önemlidir - FocusChange dinleyicilerini oluşturan tüm diğer kodlar ve benzeri hala OnCreate'de
  • Formun yeniden yüklenmesi gerektiğini gösteren bir bayrak olarak kullanılabilen bir boolean oluşturun. Benimki mbReloadForm
  • MbReloadForm ayarlanmışsa, PopulateForm () öğesini çağırmak için OnResume () öğesini geçersiz kılın.

Sayfaları yüklemeyi yaptığım Etkinliğimde:

  • Herhangi bir şeyi değiştirmeden önce sayfa 0'a gidin. FragmentStatePagerAdapter kullanıyorum, bu yüzden iki veya üç sayfanın en fazla etkilendiğini biliyorum. 0 sayfasına geçmek, yalnızca 0, 1 ve 2. sayfalarda sorun yaşamamı sağlar.
  • Eski listeyi silmeden önce boyutunu () alın. Bu şekilde hatadan kaç sayfa etkilendiğini bilirsiniz. > 3 ise, 3'e düşürün - farklı bir PagerAdapter kullanıyorsanız, kaç sayfa ile uğraşmanız gerektiğini görmeniz gerekir (belki hepsi?)
  • Verileri yeniden yükleyin ve pageAdapter.notifyDataSetChanged () öğesini çağırın
  • Şimdi, etkilenen sayfaların her biri için sayfanın pager.getChildAt (i) kullanarak etkin olup olmadığına bakın - bu, bir görünümünüz olup olmadığını gösterir. Öyleyse, pager.PopulateView () öğesini çağırın. Değilse, ReloadForm bayrağını ayarlayın.

Bundan sonra, ikinci bir sayfa grubunu yeniden yüklediğinizde, hata yine de bazılarının eski verileri görüntülemesine neden olur. Bununla birlikte, şimdi yenilenecek ve yeni verileri göreceksiniz - kullanıcılarınız sayfanın hiç yanlış olduğunu bilmeyecek, çünkü bu yenileme sayfayı görmeden önce gerçekleşecek.

Umarım bu birine yardımcı olur!


5

Bütün bu çözümler bana yardımcı olmadı. bu yüzden çalışan bir çözüm buldum: setAdapterHer zaman yapabilirsiniz , ama yeterli değil. adaptörü değiştirmeden önce bunları yapmanız gerekir:

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

ve bundan sonra:

viewPager.setAdapter(adapter);

Teşekkürler! Benim durumumda ViewPagerparça içinde kullandım , slideShowPagerAdapter.getFragmentManager()onunla değiştirildi getChildFragmentManager(). Belki getFragmentManager()senin durumunda yardımcı olacaktır. Ben kullandım FragmentPagerAdapter, değil FragmentStatePagerAdapter. Ayrıca hacky bir yol için stackoverflow.com/a/25994654/2914140 adresine bakın .
CoolMind

5

Çok daha kolay bir yol: a kullanın FragmentPagerAdapterve sayfalandırılmış görünümlerinizi parçalara sarın. Güncelleniyorlar


5

Rui.araujo ve Alvaro Luis Bustamante'a teşekkür ederiz. İlk başta, rui.araujo'nun yolunu kullanmaya çalışıyorum, çünkü bu kolay. Çalışır, ancak veri değiştiğinde sayfa açıkça yeniden çizilir. Kötü, bu yüzden Alvaro Luis Bustamante'nin yolunu kullanmaya çalışıyorum. Mükemmel. İşte kod:

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

Ve veri değiştiğinde:

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

Herhangi birinin FragmentStatePagerAdapter tabanlı bağdaştırıcıyı kullanması durumunda (ViewPager'in görüntüleme amacım için gereken minimum sayfaları oluşturmasına izin verir, benim durumum için en fazla 2), @ rui.araujo'nun adaptörünüzdeki getItemPosition üzerine yazma cevabı önemli israfa neden olmaz, ancak yine de geliştirilebilir.

Sahte kodda:

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

ViewPager içinde, öğenin geçmiş konumunu bilmek oldukça kolaydı, en mükemmel uygulama sadece getItemPosition()veri kümesi değiştiğinde yeni konumu döndürmektir ve ViewPager bunların değiştirilip değiştirilmediğini bilecektir. ne yazık ki, ViewPager yapmadı.
VinceStyling

3

Benzer bir sorun yaşadım ve dört sayfam vardı ve sayfalardan biri diğer üç sayfanın görüntülerini güncelledi. Geçerli sayfaya bitişik sayfadaki widget'ları (SeekBars, TextViews, vb.) Güncelleyebildim. Son iki sayfada, arama yapılırken başlatılmamış widget'lar bulunur mTabsAdapter.getItem(position).

Sorunumu çözmek için setSelectedPage(index)aramadan önce kullandım getItem(position). Bu, sayfayı her bir sayfadaki değerleri ve widget'ları değiştirmeme olanak tanıyacak şekilde başlatır.

Güncellenmesi Sonuçta ben kullanayım setSelectedPage(position)izledi notifyDataSetChanged().

Ana güncelleme sayfasındaki ListView'de hafif bir titreşim görebilirsiniz, ancak farkedilemez. Bunu tam anlamıyla test etmedim, ancak acil sorunumu çözdü.


Merhaba, kodunuzla ilgileniyorum, benzer bir sorunla karşı karşıyayım, bitişik parçaları güncelleyebiliyorum ama görünür olan mevcut parça güncellenmiyor. Buradaki tüm cevaplarla kafam çok karıştı. VIewPager bağdaştırıcısı tarafından gösterilen geçerli parçadaki görünümleri nasıl güncelleyebilirim
Pankaj Nimgade

3

Başka birinin yararlı bulması durumunda bu yanıtı gönderiyorum. Aynı şeyi yapmak için, sadece uyumluluk kütüphanesinden ViewPager ve PagerAdapter kaynak kodunu aldım ve kodumda derledim (Tüm hataları sıralamanız ve kendinizi içe aktarmanız gerekir, ancak kesinlikle yapılabilir).

Ardından, CustomViewPager içinde updateViewAt (int position) adlı bir yöntem oluşturun. Görünümün kendisi, ViewPager sınıfında tanımlanan ArrayList mItems öğelerinden edinilebilir (örnek öğedeki görünümler için bir Id ayarlamanız ve bu kimliği updateViewAt () yöntemindeki konumla karşılaştırmanız gerekir). Ardından görünümü gerektiği gibi güncelleyebilirsiniz.


2

Sanýrým, ViewPager'in mantýklarý bende.

Bir dizi sayfayı yenilemem ve yeni veri kümesine dayalı olarak görüntülemem gerekirse , notifyDataSetChanged () öğesini çağırırım . Ardından, ViewPager, bir Nesne olarak Fragment'i ileterek getItemPosition () öğesine bir dizi çağrı yapar . Bu Parça ya eski bir veri kümesinden (atmak istediğim) ya da yeni bir kümeden (görüntülemek istediğim) olabilir. Yani, getItemPosition () geçersiz kılma ve orada bir şekilde benim parçam eski veri kümesinden veya yeni bir veri olup olmadığını belirlemek zorunda.

Benim durumumda, sol bölmedeki en iyi öğelerin bir listesi ve sağda bir kaydırma görünümü (ViewPager) içeren 2 bölmeli bir düzenim var. Bu nedenle, geçerli üst öğeme bir bağlantıyı PagerAdapter'imin içinde ve ayrıca her bir örneklenmiş sayfa Parçasının içinde saklıyorum. Listedeki seçili üst öğe değiştiğinde, yeni üst öğeyi PagerAdapter içinde depolarım ve notifyDataSetChanged () öğesini çağırırım . Geçersiz kılınan getItemPosition () 'da bağdaştırıcımdaki en üst öğeyi parçamdaki en üst öğeyle karşılaştırırım. Ve sadece eşit değilse, POSITION_NONE döndürürüm. Ardından, PagerAdapter POSITION_NONE döndüren tüm parçaları yeniden başlatır.

NOT. Bir referans yerine üst öğe kimliğini saklamak daha iyi bir fikir olabilir.

Aşağıdaki kod parçacığı biraz şematik ama ben aslında çalışma kodundan adapte.

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

Önceki tüm araştırmacılar için teşekkürler!


2

Aşağıdaki kod benim için çalıştı.

Aşağıdaki gibi FragmentPagerAdapter sınıfını genişleten bir sınıf oluşturun.

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

Ardından, oluşturduğunuz her Parça içinde bir updateFragment yöntemi oluşturun. Bu yöntemde, parçada değiştirmeniz gereken şeyleri değiştirirsiniz. Örneğin, benim durumumda, Fragment0 bir .ply dosyası yoluna dayalı bir 3d nesne görüntüleyen bir GLSurfaceView içeriyordu, bu yüzden benim updateFragment yöntemi içinde bu kat dosya yolunu değiştirmek.

ardından bir ViewPager örneği oluşturun,

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

ve bir Adpater örneği,

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

o zaman bunu yap,

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

Daha sonra sınıfın içinde yukarıdaki Bağdaştırıcı sınıfını başlattınız ve bir viewPager oluşturdunuz, parçalarınızdan birini (her defasında Fragment0) her güncellemek istediğinizde aşağıdakileri kullanın:

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.

Bu çözüm Alvaro Luis Bustamante tarafından önerilen tekniğe dayanmaktadır.


1

1.İlk olarak Pageradapter sınıfınızda getItemposition yöntemini ayarlamanız gerekir 2. View Pager'ınızın Tam konumunu okumalısınız 3. daha sonra bu konumu yeni bir konumunuzun veri konumu olarak gönderin 4. dinleyici

bu program kodu sadece belirli bir konum öğesini ayarlamak için biraz i değiştirildi

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

benim için işe yarayan gidiyordu viewPager.getAdapter().notifyDataSetChanged();

ve adaptörü görünümü içini güncellenmesi için kodunuzu koyarak getItemPositionşöyle

@Override
public int getItemPosition(Object object) {

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

    return super.getItemPosition(object);
}

bu konuda en doğru yol olmayabilir ama işe yaradı ( return POSITION_NONEhile benim için bir kazaya neden oldu, bu yüzden bir seçenek değildi)


1

Tüm parçaları dinamik olarak güncelleyebilirsiniz, üç adımda görebilirsiniz.

Adaptörünüzde:

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

Şimdi etkinliğinizde:

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) {

}}

Sonunda parçanızda, böyle bir şey:

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

}}

Kodun tamamını burada görebilirsiniz .

Teşekkürler Alvaro Luis Bustamante.


1

Her zaman geri dönmek POSITION_NONEbasit ama biraz verimsiz bir yöntemdir, çünkü bu zaten başlatılmış olan tüm sayfaların örneklenmesini uyandırır.

PagerAdapters dinamik olarak öğeleri değiştirmek için bir kütüphane ArrayPagerAdapter oluşturdum .

Dahili olarak, bu kütüphanenin adaptörler dönmek POSITION_NONEüzerine getItemPosiition()sadece gerektiğinde.

Bu kütüphaneyi kullanarak öğeleri aşağıdaki gibi dinamik olarak değiştirebilirsiniz.

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

Thils kitaplığı, Parçalar tarafından oluşturulan sayfaları da destekler.


1

Bu benim gibi herkes için, bir servis (veya başka bir arka plan iş parçacığı) Viewpager güncellemek ve tekliflerin hiçbiri işe yaramadı: Ben biraz logchecking sonra fark, notifyDataSetChanged () yöntemi asla döndürmez. getItemPosition (Object object), daha fazla işlem yapılmadan tüm uçlar olarak adlandırılır. Sonra üst PagerAdapter sınıfının belgelerinde buldum (alt sınıfların belgelerinde değil), "Veri kümesi değişiklikleri ana iş parçacığında meydana gelmeli ve bir dataifySetChanged () çağrısı ile bitmelidir". Bu nedenle, bu durumda çalışma çözümü (FragmentStatePagerAdapter ve getItemPosition (Object nesnesi kullanılarak POSITION_NONE döndürülecek şekilde ayarlandı) kullanıldı:

ve daha sonra notDataDataSetChanged () çağrısı:

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

1

Viewpager'a şu şekilde çağrı dönüşümü ekleyebilirsiniz:

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

Aşağıdaki kodda, çağrı cihazı kaydırma sırasında çalışma zamanında görünüm rengimi değiştirdim

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

geç kaldım biliyorum ama yine de birine yardım edebilir. Ben sadece accetping cevap genişletiyor m ve ben de üzerine yorum ekledik.

iyi,

cevabın kendisi bunun verimsiz olduğunu söylüyor

böylece gerektiğinde aonly yenilemek yapmak için bunu yapabilirsiniz

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, dinamik görünüm değişikliğini desteklemek için tasarlanmamıştır.

Bununla ilgili başka bir hata ararken bunun onayını aldım https://issuetracker.google.com/issues/36956111 ve özellikle https://issuetracker.google.com/issues/36956111#comment56

Bu soru biraz eski, ancak Google yakın zamanda ViewPager2 ile bu sorunu çözdü . El yapımı (bakımsız ve potansiyel olarak buggy) çözümlerin standart bir çözümle değiştirilmesine izin verecektir. Ayrıca, bazı cevaplar gibi görünümlerin gereksiz yere yeniden oluşturulmasını da önler.

ViewPager2 örnekleri için https://github.com/googlesamples/android-viewpager2 adresini kontrol edebilirsiniz.

ViewPager2'yi kullanmak istiyorsanız, build.gradle dosyanıza aşağıdaki bağımlılığı eklemeniz gerekir:

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

Daha sonra xml dosyanızdaki ViewPager'inizi aşağıdakilerle değiştirebilirsiniz:

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

Bundan sonra, aktivitenizde ViewPager'i ViewPager2 ile değiştirmeniz gerekecektir.

ViewPager2 için bir RecyclerView.Adapter veya bir FragmentStateAdapter gerekir, sizin durumunuzda bir RecyclerView.Adapter olabilir

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

Bir TabLayout kullanıyorsanız, TabLayoutMediator kullanabilirsiniz:

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

Ardından, bağdaştırıcınızın verilerini değiştirerek ve notifyDataSetChanged yöntemini çağırarak görünümlerinizi yenileyebilirsiniz.



0

Veri kümesi değişikliklerini bildirmek için basit bir yol yaptığımı düşünüyorum:

İlk olarak, instantiateItem işlevinin çalışma şeklini biraz değiştirin:

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

"updateView" için, görünümü doldurmak istediğiniz tüm verilerle doldurun (setText, setBitmapImage, ...).

destroyView'ın şu şekilde çalıştığını doğrulayın:

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

Şimdi, verileri değiştirmeniz, yapmanız ve PagerAdapter'taki sonraki işlevi çağırmanız gerektiğini varsayalım:

    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
}

Örneğin, viewPager tarafından gösterilen tüm görünümleri bir şeyin değiştiğini bildirmek isterseniz, şunları arayabilirsiniz:

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

Bu kadar.


0

Değeri için, KitKat + 'da adapter.notifyDataSetChanged(), yeterince setOffscreenPageLimityüksek olmanız koşuluyla, yeni görünümlerin ortaya çıkmasına neden olmak için yeterli görünüyor . Yaparak istenilen davranışı elde edebiliyorum viewPager.setOffscreenPageLimit(2).


0

Aslında kullanmak notifyDataSetChanged()üzerine ViewPagerve CirclePageIndicatorben diyoruz bundan sonra destroyDrawingCache()üzerinde ViewPagerve .. diğer çözümlerin hiçbiri benim için çalıştı çalışır.


Orijinal soru neredeyse 2 yaşında, eminim Android API'de şimdiye kadar birçok farklılık var, buradaki cevaplar Android API'nin tüm sürümleri için doğru olmayabilir.
C0deAttack
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.