ViewPager'da FragmentPagerAdapter kullanan parça ikinci kez görüntülendiğinde boştur


98

Ana görünümde farklı parçaları açan alt kısımda sekmeler bulunan bir parça arayüzüne sahibim.

Öğe listesi olan belirli bir parçam var. Kullanıcı bu listedeki öğelerden birini seçerse, önceki parçadaki listedeki tüm öğeler arasında yatay olarak kayan bir görüntüleyici içeren başka bir parça açılır. Bu harika çalışıyor.

Viewpager, öğeleri görüntülemek için FragmentPagerAdapter kullanır.

Sorun, kullanıcı listedeki bir öğeyi seçip görüntülediğinde, listeye geri dönmek için sekme çubuğundaki düğmeye bastığında ve ardından başka bir öğe seçtiğinde ortaya çıkar. Bir öğe ikinci kez seçildiğinde, görüntüleyici yerine boş bir ekran belirir. Bu olduğunda LogCat'imde hiçbir hata almıyorum.

Görüntüleyici neden yalnızca ilk kez görünüyor?

FragmentPagerAdapter:

public class ViewPagerAdapter extends FragmentPagerAdapter {
    Cursor mCursor;

    public ViewPagerAdapter(FragmentManager fm, Cursor c) {
        super(fm);
        mCursor = c;
    }

    public void changeCursor(Cursor c) {
        mCursor = c;
        this.notifyDataSetChanged();
    }

    @Override
    public int getCount() {
        if (mCursor == null) return 0;
        else return mCursor.getCount();
    }

    @Override
    public Fragment getItem(int position) {
        mCursor.moveToPosition(position);
        return TeamCardFragment.newInstance(mCursor, position);
    }
}

PagerFragment:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    Bundle bundle = getArguments();
    mCursorPosition = bundle.getInt(TeamCardCommon.BUNDLE_KEY_CURSOR_POSITION);

    View mView = inflater.inflate(R.layout.team_card_master, container, false);
    mViewPager = (ViewPager)mView.findViewById(R.id.team_card_master_view_pager);

    mAdapter = new ViewPagerAdapter(getFragmentManager(), cursor);
    new setAdapterTask().execute();

    return mView;
}

private class setAdapterTask extends AsyncTask<Void, Void, Void> {
    protected Void doInBackground(Void... params) {
        return null;
    }

    @Override
    protected void onPostExecute(Void result) {
        mViewPager.setAdapter(mAdapter);
        mViewPager.setCurrentItem(mCursorPosition);
    }
}

Yanıtlar:


221

Ben de aynı sorunu yaşadım. Ekran sorunumu "ikinci seferde" çözmek android.support.v4.app.FragmentPagerAdapteriçin PageAdapter öğemin üst sınıfını değiştirmek !android.support.v4.app.FragmentStatePagerAdapterViewPager


2
Şaka yapmıyorum? Artık bu koda sahip değilim, aksi takdirde test ederdim. Belki bu cevap başkasına yardımcı olur.
howettl

10
Ne adam ama! Günlerdir bu çözümü arıyordum! Çok teşekkürler adamım, bir cazibe gibi çalışıyor. Ama içimdeki geliştirici, bu değişikliğin nasıl bir etki yaratacağını soruyor. Demek istediğim, neden daha önce çalışmadı ve neden StatePagerAdapter
Anand

1
ayrıca @Override public int getItemPosition (Object object) {return POSITION_NONE; }
Helin Wang

1
Benim için de çalıştı. İşte bir bağlantı. Tüm farkı yaratan parça durumunu koruyor gibi görünüyor. developer.android.com/reference/android/support/v4/app/…
Tjaart

1
Bunun işe yaraması bir tesadüf, doğru cevap @Daniel F'nin cevabı. Her neyse, buradaki yorumcuların rahatlığı için, arasındaki fark FragmentPagerAdapterve FragmentStatePagerAdapterönceki sayfadaki fark birkaç sayfa için daha uygundur, tüm parçaları bellekte tutar, böylece sayfa geçişinde en iyi performansa sahip olurken, ikincisi birçok sayfa için daha uygundur. sayfaları yok eder, yalnızca durumlarını korur, belleği daha verimli kullanır ancak sayfa geçişinde biraz daha yavaştır.
Cristina De Rito

87

Bunu ana parçadaki getFragmentManager()ile değiştirerek çözmeyi başardım getChildFragmentManager(). Bu üst parça, yapıcıda bir parça yöneticisi gerektiren sayfalanabilir (kaydırılabilir) parçaları içermek için bir android.support.v4.app.FragmentPagerAdapter örnekliyordu. Bu kurucuya dönüş değerini geçtim getChildFragmentManager().

Hackbod'un bağlantısı, Fragments içindeki Fragments içinde bulunan anahtardı ( https://developer.android.com/about/versions/android-4.2.html#NestedFragments )

Bir parçayı yerleştirmek için, getChildFragmentManager()bir parça eklemek istediğiniz Parçayı çağırmanız yeterlidir . Bu, parça işlemleri oluşturmak için normalde üst düzey etkinlikten yaptığınız gibi kullanabileceğiniz bir FragmentManager döndürür.


Teşekkür ederim ... bir fragmentpageradapter içeren onresume () 'den sonra kayan bir sekme görünümünü yeniden başlatmaya çalışırken benzer bir sorun yaşıyordum ... kullandığım eğitici 2016 yılına aitti ve yine de onu almak için fragmentstatepageradapter olarak değiştirmem gerekiyordu iş. Keşke NEDEN bilseydim.
Nerdy Bunz

bu cevap zamanımın çoğunu kurtardı. Çünkü sadece kullanmak FragmentStatePagerAdapterburada sorulan soruyu çözmez. ile birlikte FragmentStatePagerAdapterana parça YourAdapter adapter = new YourAdapter (getChildFragmentManager()); eklenmelidir
MMK

17

benim için bunu görüntüleyicimde aramak zorunda kaldım:

myViewPager.setSaveFromParentEnabled(false);

Görüntüleyicinin yenilenmemesi sorununu yaşadım ve tek gördüğüm parçaların olması gereken yerde boş beyaz bir ekrandı. GetChildFragmentManager'a geçiyordum ama yardımcı olmadı.


1
Bu neden işe yaradı? Bu sorunumu çözdü ama neden olduğuna dair hiçbir fikrim yok.
ClayHerendeen

Şimdi kodumdan kaldırdım. Soruna parça yöneticisi neden oluyordu. Getchildfragmentmanager ve getfragmentmanager arasında geçiş yapmayı deneyin
j2emanue

Bunu zaten denedim. Kaydırmayı devre dışı bırakan ViewPager'ların her birine sekmeler yerleştirdim. Bunun kötü bir tasarım olduğunu biliyorum ama müşteriler benim olmamasını istiyor. Üst düzey sekme çubuğu için bir childFragmentManager kullanıyorum. Alt düzey sekme çubuğu / görüntüleyici için geçiş yapmak sorunu çözmedi. Sanırım çalıştığı için şimdilik setSaveFromParentEnabled (false) 'a bağlı kalacağım.
ClayHerendeen

En son destek kitaplığını kullanıyor musunuz
j2emanue

2
Son 2 gündür aynı sorunla karşı karşıyaydım .. Çözümünüz benim için çalıştı. Teşekkürler !
brijexecon

11

CoordinatorLayout'u bir AppBarLayout ve ViewPager ile kullandığım çok özel durumumda, benim için çözen şey android'i AppBarLayout xml özelliklerimden fitsSystemWindows = "true" olarak kaldırmaktı .

Bana neden diye sorma. Kulağa biraz saçma geldiğini ve hiçbir ilişkisi olmaması gerektiğini biliyorum, ancak adaptörümde zaten getChildFragmentManager () kullandığım için soruna neden olan tek şey bu tek satırdı. Sırf bunu bulmak için bütün gün kodumda hata ayıklayarak geçirdim, bu yüzden umarım başka birine biraz zaman kazandırır.


3
Ah adamım ... Bu konuda neredeyse teslim olacaktım. Korkunç günümü yaşadın! Geez Google, WTF AppBarLayout'ta yanlış mı? Neredeyse yüz sayfaya baktım ve bu sorunu şanssız bir şekilde çözmeye çalışırken hata ayıklamak için bir ton saat harcadım. Sonunda yorumunuzla sorunu çözmeyi başardığım için gerçekten minnettarım. Çok teşekkürler! Not: O kadar çaresizdim ki AOSP'de bir sorun bile yarattım: code.google.com/p/android/issues/… XD
Guillem Roca

İpucu için teşekkürler. En azından sorunu çözmemize yardımcı oldu. Şimdi tam ekran yapma seçeneğini bulmaya çalışıyoruz
Paresh Mayani

Sen bir hayat kurtarıcısın! Neden bu sorunu yaşadığım konusunda kesinlikle bilgisizdim ve neden işe yaradığına dair hala ipucu yok!
nandu

10

Ben adaptörü değişti kendisi için aynı sorunu vardı FragmentPagerAdapteriçin FragmentStatePagerAdapterve getFragmentManager()parent fragmanındagetChildFragmentManager()

Bunun arkasındaki neden, FragmentStatePagerAdapterçok sayıda sayfanın depolanmasında yararlıdır ve ziyaret edilen her sayfayla ilişkili bellek, sayfa görünmezken yalnızca parçanın kaydedilmiş durumunu koruduğundan daha azdır. Bu, parçalar arasında geçiş yaparken ek yükü azaltır.


4

Koymak için deneyin setOffscreenPageLimit (int limit)üzerinde ebeveyn ViewPager.

mViewPager.setOffscreenPageLimit(totalPages-1);

Bu benim için çekicilik gibi çalıştı.

Benim durumumda I fragmanı içini vardı TabLayoutileViewPager.

Ve ViewPagero parçanın içinde bir tane daha. İlk kez her şey iyi çalışıyor ama sekmeyi değiştirip geri döndüğümde, parçamın bir kısmı boş kaldı.


1
İyi cevap. Bana yardımcı oldu.
Thirumalvalavan


1

View pager öğelerini parçalar yerine standart görünümler olarak yeniden uygulayarak ve adaptörü buna göre değiştirerek bunu aştık.


isViewFromObject (Görünüm görünümü, Nesne nesnesi) işlevini kaldırmayı deneyebilirsiniz
Mina Samy

Daha iyi bir yol olmalı ....: / Android'e ne kadar çok girersem o kadar az olgun olduğunun farkındayım.
StackOverflow

1
İç içe geçmiş parçalar desteklenmez , bu nedenle standart görünümle yeniden uygulamak iyi bir yol gibi görünüyor.
Sylphe

Benzer bir sorunla mücadele ediyorum. FragmentAdapter yerine PagerAdapter kullanmayı denedim, yine de aynı sorunla karşılaşıyorum. Lütfen bana yardım edin !
Gaurav Arora

İç içe geçmiş parçaları kullanmak istiyorsanız, bu cevapta verdiğim adaptörü kullanabilirsiniz: stackoverflow.com/questions/7700226/…
Slickelito

1

Aynı sorunu Xamarin Android'de ikinci kez boş bir ekranla alıyordum .. Aşağıdakileri ayarlamak benim için sorunu çözdü .

viewPager.SaveFromParentEnabled = false;

0

Bağdaştırıcıyı, uygulamanız simge durumuna küçültüldüğünde ve daha sonra çağrıldığında bu hatayla karşılaştığınız durumlar için de başlatabilirsiniz.

@Override 
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    Bundle bundle = getArguments();
    mCursorPosition = bundle.getInt(TeamCardCommon.BUNDLE_KEY_CURSOR_POSITION);
    View mView = inflater.inflate(R.layout.team_card_master, container, false);
    mViewPager = (ViewPager)mView.findViewById(R.id.team_card_master_view_pager);
    initViewPagerAdapter();
    return mView;
}
private void initViewPagerAdapter(){
    mAdapter = new ViewPagerAdapter(getFragmentManager(), cursor);
    new setAdapterTask().execute();
}

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

0

Aynı şeye sahiptim, Çağrı Bağdaştırıcısını ikinci kez çağırdığımda, çocuk görünümü bir NullPointerException döndürüyor. Ve FragmentStatePagerAdapter içindeki bağdaştırıcıyı değiştirmek de sorunumu çözdü.


0

Değişim FragmentPagerAdapteriçine FragmentStatePagerAdapter Kullanım getChildFragmentManager()yerinegetFragmentManager()

getChildFragmentManager()- çünkü belgelere göre, Parçaları bu Parçanın içine yerleştirmek ve yönetmek için özel bir FragmentManager döndürecektir. Bu arada getFragmentManager()FragmentManager'ı bu etkinlikle ilişkili parçalarla etkileşime girmesi için döndürecektir.


0

sınıf ViewPagerAdapter FragmentStatePagerAdapter genişletiyor bu çalışmayı benim için deneyin

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.