Geçerli Parça örneğini viewpager'da alma


210

Aşağıda, 3 Fragment classesher biri 3 sekmenin her birine gömülü olan kodum ViewPager. Bir menü seçeneğim var. Gösterildiği gibi, onOptionsItemSelected()bir seçenek belirleyerek, şu anda görünür olan parçayı güncellemem gerekiyor. Bunu güncellemek için parça sınıfında bir yöntemi çağırmak zorunda. Birisi bu yöntemi nasıl arayacağınızı önerebilir mi?

public class MainActivity  extends ActionBarActivity {

     ViewPager ViewPager;
     TabsAdapter TabsAdapter;

     @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);

            ViewPager = new ViewPager(this);
            ViewPager.setId(R.id.pager);
            setContentView(ViewPager);

            final ActionBar bar = getSupportActionBar();

            bar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);

            //Attaching the Tabs to the fragment classes and setting the tab title.
            TabsAdapter = new TabsAdapter(this, ViewPager);
            TabsAdapter.addTab(bar.newTab().setText("FragmentClass1"),
                    FragmentClass1.class, null);
            TabsAdapter.addTab(bar.newTab().setText("FragmentClass2"),
              FragmentClass2.class, null);
            TabsAdapter.addTab(bar.newTab().setText("FragmentClass3"),
              FragmentClass3.class, null);


            if (savedInstanceState != null) {
                bar.setSelectedNavigationItem(savedInstanceState.getInt("tab", 0));
            }

        }

        @Override
        public boolean onOptionsItemSelected(MenuItem item) {

            switch (item.getItemId()) {

            case R.id.addText:

           **// Here I need to call the method which exists in the currently visible Fragment class**

                    return true;

            }

            return super.onOptionsItemSelected(item);
        }


     @Override
     protected void onSaveInstanceState(Bundle outState) {
      super.onSaveInstanceState(outState);
            outState.putInt("tab", getSupportActionBar().getSelectedNavigationIndex());

     }

     public static class TabsAdapter extends FragmentPagerAdapter
      implements ActionBar.TabListener, ViewPager.OnPageChangeListener {

      private final Context mContext;
            private final ActionBar mActionBar;
            private final ViewPager mViewPager;
            private final ArrayList<TabInfo> mTabs = new ArrayList<TabInfo>();

            static final class TabInfo {
                private final Class<?> clss;
                private final Bundle args;

                TabInfo(Class<?> _class, Bundle _args) {
                    clss = _class;
                    args = _args;
                }
            }

      public TabsAdapter(ActionBarActivity activity, ViewPager pager) {
       super(activity.getSupportFragmentManager());
                mContext = activity;
                mActionBar = activity.getSupportActionBar();
                mViewPager = pager;
                mViewPager.setAdapter(this);
                mViewPager.setOnPageChangeListener(this);
            }

      public void addTab(ActionBar.Tab tab, Class<?> clss, Bundle args) {
                TabInfo info = new TabInfo(clss, args);
                tab.setTag(info);
                tab.setTabListener(this);
                mTabs.add(info);
                mActionBar.addTab(tab);
                notifyDataSetChanged();

            }

      @Override
      public void onPageScrollStateChanged(int state) {
       // TODO Auto-generated method stub

      }

      @Override
      public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
       // TODO Auto-generated method stub

      }

      @Override
      public void onPageSelected(int position) {
       // TODO Auto-generated method stub
       mActionBar.setSelectedNavigationItem(position);
      }

      @Override
      public void onTabReselected(Tab tab, FragmentTransaction ft) {
       // TODO Auto-generated method stub

      }

      @Override
      public void onTabSelected(Tab tab, FragmentTransaction ft) {
       Object tag = tab.getTag();
                for (int i=0; i<mTabs.size(); i++) {
                    if (mTabs.get(i) == tag) {
                        mViewPager.setCurrentItem(i);

                    }
                }

                tabPosition = tab.getPosition();
      }

      @Override
      public void onTabUnselected(Tab tab, FragmentTransaction ft) {
       // TODO Auto-generated method stub

      }

      @Override
      public Fragment getItem(int position) {
       TabInfo info = mTabs.get(position);
                return Fragment.instantiate(mContext, info.clss.getName(), info.args);
      }

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

     }

    }

Aşağıda, updateList()aramak istediğim yöntemle fragman sınıfı olduğunu varsayalım :

 public class FragmentClass1{

    ArrayList<String> originalData;


    @Override
         public View onCreateView(LayoutInflater inflater, ViewGroup container,
           Bundle savedInstanceState) {

          View fragmentView = inflater.inflate(R.layout.frag1, container, false);

          originalData = getOriginalDataFromDB();

          return fragmentView;

         }


    public void updateList(String text)
    {
       originalData.add(text);
       //Here I could do other UI part that need to added
    }
}

hangi parça yöntemini aramak istiyorsunuz?
Biraj Zalavadia

@BirajZalavadia İçinde bir parametre bulunan ve bir görünüm oluştururken zaten başlatılmış olan parça sınıfının örnek değişkenlerini kullanan kendi tanımlanmış yöntemim.
rick

1
viewpager'daki parçalarınızın Sınıf adını verebilir misiniz?
Biraj Zalavadia


Görünen parçalara erişmenin en basit yolu stackoverflow.com/questions/7379165/… , en iyi iki cevaba bakın.
Luksprog

Yanıtlar:


205

bir seçenek belirleyerek, şu anda görünür olan parçayı güncellemem gerekiyor.

Bunu yapmanın basit bir yolu, FragmentPagerAdapteruygulama ile ilgili bir hile kullanmaktır :

case R.id.addText:
     Fragment page = getSupportFragmentManager().findFragmentByTag("android:switcher:" + R.id.pager + ":" + ViewPager.getCurrentItem());
     // based on the current position you can then cast the page to the correct 
     // class and call the method:
     if (ViewPager.getCurrentItem() == 0 && page != null) {
          ((FragmentClass1)page).updateList("new item");     
     } 
return true;

Lütfen değişken adı olarak sınıfın adının çok kafa karıştırıcı olduğu değişken adlandırma kuralınızı yeniden düşünün (bu nedenle hayır ViewPager ViewPager, ViewPager mPagerörneğin kullanın ).


23
API değişirse bu parça etiketi geleceğe yönelik mi?
Maarten

7
@Maarten Hayır, sadece adaptör ortaya çıktığından beri kullanılan yaygın bir hack (ve kaynak kodu mevcut), henüz değişmedi. Daha güvenilir bir şey istiyorsanız, diğer seçenekleri kullanmanız gerekir, en dikkate değer instantiateItem()yöntemi geçersiz kılma ve uygun parçalara kendiniz referans alma.
Luksprog

5
Saatler süren hayal kırıklığından ve sayfaları doğrudan sormaktan sonra mAdapter.getItem(position), harika ... En azından şimdi diğer 8512 denemelerinin işe yaramadığını biliyorum. Teşekkürler
Diolor

29
FragmentPagerAdapter yerine FragmentStatePagerAdapter kullanıyorsanız, bunun çalışmadığını unutmayın.
Shawn Lauzon

3
@ShawnLauzon FragmentStatePagerAdapter farklı bir uygulamaya sahiptir, bu durumda görünür parçaları almak için instantiateItem () yöntemini çağırırsınız.
Luksprog

155
    public class MyPagerAdapter extends FragmentPagerAdapter {
        private Fragment mCurrentFragment;

        public Fragment getCurrentFragment() {
            return mCurrentFragment;
        }
//...    
        @Override
        public void setPrimaryItem(ViewGroup container, int position, Object object) {
            if (getCurrentFragment() != object) {
                mCurrentFragment = ((Fragment) object);
            }
            super.setPrimaryItem(container, position, object);
        }
    }

28
Google, mCurrentPrimaryItem döndüren FragmentPageAdapter.getCurrentPrimaryItem () sağlamalıdır.
eugene

1
Ben de bu tekniği kullanmak.Ayrıca yöntemleri ile PagerFragment tanımlamak onPageSelected/ onPageDeselectedve tüm çağrı parçaları benim uzatmak var. Ardından setPrimaryitem, kullanıcı yeni bir sayfaya geçtiğinde bu yöntemleri uygun şekilde çağırabilir. Bu, gösterilmeyen sayfalara veri yüklemek için daha tembel bir strateji uygulayabileceğiniz anlamına gelir. Bununla birlikte, sayfa geçişi sırasında bir sonraki sayfanın zaten veri ile doldurulmasının daha iyi göründüğünü unutmayın, bu nedenle tüm verilerin tembel olarak yüklenmesi onPageSelectedideal olmayabilir.
JHH

3
Neden ifaçıklama? Parça sadece equalssığ karşılaştırma olan nesne yöntemini çağırır . Öyleyse neden her zaman aramıyorsun mCurrentFragment = ((Fragment) object);?
Overclover

denedim ve iyi çalışıyor, sadece getCurrentFragment () 'i olması gereken Fragment'e
dökün

113

Her şeyden önce tüm "aktif" parça sayfalarını takip edin. Bu durumda, ViewPager tarafından kullanılan FragmentStatePagerAdapter içindeki parça sayfalarını takip edersiniz.

@Override
public Fragment getItem(int index) {
    Fragment myFragment = MyFragment.newInstance();
    mPageReferenceMap.put(index, myFragment);
    return myFragment;
}

"Etkin olmayan" fragman sayfalarına başvuruda bulunmaktan kaçınmak için FragmentStatePagerAdapter's destroyItem (...) yöntemini uygulamanız gerekir:

@Override
public void destroyItem (ViewGroup container, int position, Object object) {
    super.destroyItem(container, position, object);
    mPageReferenceMap.remove(position);
}

ve şu anda görünür olan sayfaya erişmeniz gerektiğinde şunu ararsınız:

int index = mViewPager.getCurrentItem();
MyAdapter adapter = ((MyAdapter)mViewPager.getAdapter());
MyFragment fragment = adapter.getFragment(index);

MyAdapter'ın getFragment (int) yöntemi şöyle görünür:

public MyFragment getFragment(int key) {
    return mPageReferenceMap.get(key);
}

Umarım yardımcı olabilir!


Açık bir şekilde açıklar mısınız? Bu FragmentStatePagerAdapter sınıfını kodumda nerede tutmam gerekir? BTW Tek parça MyFragmentClass değil, 3 parça sınıfı var.
rick

7
Yönelim değişikliğinden sonra da çalıştığı için getItem yerine instantiateItem içinde mPageReferenceMap öğesini güncelleştirirseniz daha da iyi olur. '@Override public Object instantiateItem (ViewGroup kapsayıcısı, int konumu) {Fragment fragment = (Fragment) Super.instantiateItem (container, position); mPageReferenceMap.put (konum, parça); dönüş parçası; } '
pmellaaho

MPageReferenceMap türü nedir?
DoruAdryan

10
Bu cevap gerçekten kötü! Bir ViewPager'in önbelleğini tek başına tutacağı için elle tutmamalısınız. ViewPager, parçanın ne zaman ayrılması ya da ayrılmaması gerektiğine, neyi duraklatacağına ve ne zaman, her parçayla ilgili bir referansı tutmak işe yaramaz bir ek yük ekler ve bellek için optimize edilmez.
Livio

3
Bu yaklaşımı denedim ama maalesef etkinlik yeniden yaratıldığında işe yaramıyor. Android N ve sonraki sürümlerde, çoklu pencere özelliğini kullanırken bunu görebilirsiniz. Uygulamanız açıkken, 'son işaretler' düğmesini (kare olan) uzun süre basılı tutun. Etkinlik ve parça kaydedilenInstanceState öğesinden yeniden oluşturulur, bağdaştırıcı yeniden oluşturulur (böylece mPageReferenceMap artık boştur), ancak getItem yeniden çağrılmaz. Bağdaştırıcı.getFragment (dizin) çökecek şekilde harita boş kalır.
Martin Konicek

102

Bu belirli parça sınıflarının örnek değişkenleri için NullPointerException almıyorum tek yoludur. Bu, aynı şeye takılanlar için yararlı olabilir. OnOptionsItemSelected () 'de aşağıdaki şekilde kodladım:

if(viewPager.getCurrentItem() == 0) {
    FragmentClass1 frag1 = (FragmentClass1)viewPager
                            .getAdapter()
                            .instantiateItem(viewPager, viewPager.getCurrentItem());
    frag1.updateList(text); 
} else if(viewPager.getCurrentItem() == 1) {
    FragmentClass2 frag2 = (FragRecentApps)viewPager
                            .getAdapter()
                            .instantiateItem(viewPager, viewPager.getCurrentItem());
    frag2.updateList(text);
}

3
Bu en doğru cevap olduğunu düşünüyorum - FragmentStatePagerAdapterherhangi bir kodu geçersiz kılmadan tasarım ile hizalayın . Aslında, bir işlev sadece geri dönmek kadar basit olmalıdır viewPager.getAdapter().instantiateItem(viewPager, viewPager.getCurrentItem()).
John Pang

39

FragmentStatePagerAdapter, parçanızı belirtilen parametre değerlerine dayalı olarak döndüren instantiIIt adıyla genel bir yönteme sahiptir, bu yöntemin iki parametresi vardır ViewGroup (ViewPager) ve konum.

public Object instantiateItem(ViewGroup container, int position);

Belirtilen konumun parçasını almak için bu yöntemi kullandı,

Fragment fragment = (Fragment) adaper.instantiateItem(mViewPager, position);

5
Ama bu halihazırda halihazırda başlatılmış olan parçayı döndürmez, onun yerine yenisini değil, değil mi? Böylece adı "örnek" ...
Ixx

1
@Ixx Hayır, yeni bir parça oluşturmaz. Yöntem adının burada yanlış olduğunu düşünüyorum.
Bugs

15

Çok geç olduğunu biliyorum ama bunu yapmanın gerçekten basit yolları var,

// 0 bulundurmadaki parça için

((mFragment) viewPager.getAdapter().instantiateItem(viewPager, 0)).yourMethod();

10

Burada, bunu öngörülebilir şekilde yapmanın gerçekten YOK olduğu gerçeğine gerçekten değinmeyen ve gelecekte kendinizi bir noktada ayağınıza vurmanıza neden olmayacak bir çok cevap var.

FragmentStatePagerAdapterizlenen parçalara nasıl güvenilir bir şekilde erişileceğini bilen tek sınıftır FragmentManager- parçanın kimliğini veya etiketini denemeye ve tahmin etmeye yönelik herhangi bir girişim güvenilir değildir, uzun vadeli. Durum kaydedildiğinde / geri yüklendiğinde örnekleri manuel olarak izleme girişimleri büyük olasılıkla iyi çalışmayacaktır, çünkü durumu geri yüklediğinde FragmentStatePagerAdaptergeri çağrıları iyi çağıramayabilir.

İş yapabildiğim tek şey, kodun kopyalanması ve FragmentStatePagerAdapterbir pozisyon ( mFragments.get(pos)) verildiğinde parçayı döndüren bir yöntem eklemektir . Bu yöntemin parçanın gerçekten kullanılabilir olduğunu varsaydığını unutmayın (yani bir noktada görülebilir).

Özellikle maceracıysanız, özel mFragmentslistenin öğelerine erişmek için yansımayı kullanabilirsiniz , ancak daha sonra bir kareye geri dönüyoruz (listenin adının aynı kalacağı garanti edilmez).


1
"durum kaydedildiğinde / geri yüklendiğinde iyi çalışmıyor" ile başa çıkmak için saveState () yöntemini geçersiz kılar. Böylece, aktivite duraklatıldığında çağrı cihazı hiçbir parçayı kaydetmez. işe yarıyor.
AntoineP

2
Bu, altta yatan sorunu düzeltmeden patchwork'e ekler. İşe yaramadığını iddia etmiyorum - sadece iyi bir uygulama değil.
Melllvar

8
getSupportFragmentManager().getFragments().get(viewPager.getCurrentItem());

Yukarıdaki satırdan alınan örneği üzerinde çalışmak istediğiniz parçaya yayınlayın. Mükemmel çalışıyor.

viewPager

parçaları yöneten çağrı örneğidir.


Bu, yalnızca tüm sayfalar Parça olarak yüklenmişse çalışır. Örneğin, çok sayıda sekme / sayfa içeren bir tablo varsa, bunların tümü yüklenmez, böylece bu bir indexoutofbounce istisnasını yükseltebilir.
progNewbie

Yeni bir evet, ek bir geçici çözüm koduna ihtiyaç duyacaktır.
Gaurav Pangam

@progNewbie Evgeny'nin aşağıdaki cevabı bence bu durumu ele alacaktı
Gaurav Pangam

7

bir seçenek belirleyerek, şu anda görünür olan parçayı güncellemem gerekiyor.

Şu anda görünür olan parçaya referans almak için, ViewPagerolarak bir referansınız olduğunu varsayın mPager. Daha sonra aşağıdaki adımlar referans alacaktır currentFragment:

  1. PageAdapter adapter = mPager.getAdapter();
  2. int fragmentIndex = mPager.getCurrentItem();
  3. FragmentStatePagerAdapter fspa = (FragmentStatePagerAdapter)adapter;
  4. Fragment currentFragment = fspa.getItem(fragmentIndex);

Kullanılan tek döküm hattı 3 genellikle geçerlidir. FragmentStatePagerAdapterViewPager için kullanışlı bir adaptördür.


7

Bunu yapmanın en iyi yolu CallingFragmentName fragment = (CallingFragmentName) viewPager .getAdapter () .instantiateItem (viewPager, viewPager.getCurrentItem ()); Boştaki işaretçi istisnası atmayacak ve bu parçanın herhangi bir yöntemini çağırmayacak şekilde çağırma Parçanızı yeniden başlatır.


6

Geçerli Parça:

Bu, parçalar sekmesi şablonuyla bir proje oluşturduysanız çalışır.

Fragment f = mSectionsPagerAdapter.getItem(mViewPager.getCurrentItem());

Bunun varsayılan sekmeli etkinlik şablonu uygulamasıyla çalıştığını unutmayın.


30
Bu, getItem () uygulamanıza bağlıdır - parçanın yeni bir örneğini döndürebilir, bu da muhtemelen istediğiniz şey değildir.
Tom

İşte böyle yapıyorsun. fragman projesi ile bir tabor oluşturduğunuzda hala varsayılan yapılandırmaya sahipseniz. hiçbirinin bu çözümü yoktu. bu yüzden yardımcı olacağını düşündüm.
hasan

3

Aşağıdakileri kullandım:

 int index = vpPager.getCurrentItem();
 MyPagerAdapter adapter = ((MyPagerAdapter)vpPager.getAdapter());
 MyFragment suraVersesFragment = (MyFragment)adapter.getRegisteredFragment(index);

1
Bu, burada bulunan yanıttan özel bir çağrı cihazı uygulamasına dayanır: stackoverflow.com/questions/8785221/…
Tom Redman

1
Bu tam olarak yapmaya çalıştığım şeydi, ancak hangi yöntemleri geçersiz kılmak bilmeden, saatlerce boşa harcanırdı - teşekkürler!
Bron Davies

2

FragmentStatePagerAdaptermCurrentPrimaryItemtüründe özel bir örnek değişkeni var Fragment. Sadece Android devs neden bir alıcı ile sağlamadı merak edebilirsiniz. Bu değişken setPrimaryItem()yöntemde somutlaştırılır . Bu nedenle, bu değişkene referans almanız için bu yöntemi geçersiz kılın. Ben sadece kendi beyan mCurrentPrimaryItemve içeriğini setPrimaryItem()geçersiz kılma benim kopya ile sona erdi .

Uygulamanızda FragmentStatePagerAdapter:

private Fragment mCurrentPrimaryItem = null;

@Override
public void setPrimaryItem(ViewGroup container, int position, Object object) {
    Fragment fragment = (Fragment)object;
    if (fragment != mCurrentPrimaryItem) {
        if (mCurrentPrimaryItem != null) {
            mCurrentPrimaryItem.setMenuVisibility(false);
            mCurrentPrimaryItem.setUserVisibleHint(false);
        }
        if (fragment != null) {
            fragment.setMenuVisibility(true);
            fragment.setUserVisibleHint(true);
        }
        mCurrentPrimaryItem = fragment;
    }
}

public TasksListFragment getCurrentFragment() {
    return (YourFragment) mCurrentPrimaryItem;
}

2

Sen tanımlayabilirsiniz PagerAdaptero zaman mümkün herhangi almak için bu gibi Fragmentin ViewPager.

private class PagerAdapter extends FragmentPagerAdapter {
    private final List<Fragment> mFragmentList = new ArrayList<>();

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

    @Override
    public Fragment getItem(int position) {
        return mFragmentList.get(position);
    }

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

    public void addFragment(Fragment fragment) {
        mFragmentList.add(fragment);
    }
}

Akımı almak için Fragment

Fragment currentFragment = mPagerAdapter.getItem(mViewPager.getCurrentItem());

2

ViewPager'i kullandığımızda, etkinlikteki parça örneğine erişmenin iyi bir yolu instantiateItem'dir (viewpager, index). // index- örneği istediğiniz parçanın dizini.

örneğin 1 dizin parçasının örneğine erişiyorum.

Fragment fragment = (Fragment) viewPageradapter.instantiateItem(viewPager, 1);

if (fragment != null && fragment instanceof MyFragment) {      
 ((MyFragment) fragment).callYourFunction();

}

2

Önceki uygulamamda, daha sonra erişebilmek için alt Parçaların bir listesini sakladım, ancak bu, büyük bellek sızıntılarına neden olan yanlış bir uygulama olduğu ortaya çıktı.

instantiateItem(...)Geçerli Fragment almak için yöntem kullanarak sonunda :

val currentFragment = adapter?.instantiateItem(viewPager, viewPager.currentItem)

Veya başka bir Parçayı pozisyona almak için:

val position = 0
val myFirstFragment: MyFragment? = (adapter?.instantiateItem(viewPager, position) as? MyFragment)

Gönderen belgeler :

Verilen konum için sayfa oluşturun. Bağdaştırıcı, görünümü burada verilen kapsayıcıya eklemekten sorumludur, ancak bunun yalnızca finishUpdate'den (ViewGroup) döndüğü zaman yapılmasını sağlamalıdır.


Kısa ve temiz, teşekkür ederim
JimmyFlash

1

Aynı sorunu vardı ve bu kodu kullanarak çözdü.

MyFragment fragment = (MyFragment) thisActivity.getFragmentManager().findFragmentById(R.id.container);

MyFragment adını parçanızın adıyla değiştirin ve parça kabınızın kimliğini ekleyin.


1

Bu, kabul edilen cevaptan daha fazla geleceğe yöneliktir:

public class MyFragmentPagerAdapter extends FragmentPagerAdapter {

    /* ------------------------------------------------------------------------------------------ */
    // region Private attributes :

    private Context _context;
    private FragmentManager _fragmentManager;
    private Map<Integer, String> _fragmentsTags = new HashMap<>();

    // endregion
    /* ------------------------------------------------------------------------------------------ */



    /* ------------------------------------------------------------------------------------------ */
    // region Constructor :

    public MyFragmentPagerAdapter(Context context, FragmentManager fragmentManager) {

        super(fragmentManager);

        _context = context;
        _fragmentManager = fragmentManager;
    }

    // endregion
    /* ------------------------------------------------------------------------------------------ */



    /* ------------------------------------------------------------------------------------------ */
    // region FragmentPagerAdapter methods :

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

    @Override
    public Fragment getItem(int position) {

        if(_fragmentsTags.containsKey(position)) {

            return _fragmentManager.findFragmentByTag(_fragmentsTags.get(position));
        }
        else {

            switch (position) {

                case 0 : { return Fragment.instantiate(_context, Tab1Fragment.class.getName()); }
                case 1 : { return Fragment.instantiate(_context, Tab2Fragment.class.getName()); }
            }
        }

        return null;
    }

    @Override
    public Object instantiateItem(ViewGroup container, int position) {

        // Instantiate the fragment and get its tag :
        Fragment result = (Fragment) super.instantiateItem(container, position);
        _fragmentsTags.put(position, result.getTag());

        return result;
    }

    // endregion
    /* ------------------------------------------------------------------------------------------ */
}

Bunun yerine WeakHashMap kullanmalısınız.
Prakash Nadar

1

Söz konusu senaryo, her bir Parça tarafından kendi menü öğelerini ekleyerek ve resmi belgelerde açıklandığı gibi doğrudan onOptionsItemSelected () yöntemiyle daha iyi sunulur . Belgesiz numaralardan kaçınmak daha iyidir.


Bu cevap, bunun nasıl yapılacağı hakkında daha fazla ayrıntı kullanabilir. Menü öğesi eklemek ViewPagersorunu nasıl çözer ?
16'da Suragch

@Suragch ViewPager sorunu, menü olayları parçaları barındıran Etkinlik içinde işlenirse ve olaylar parçanın içinde işleniyorsa mevcut değildir. Bağlantı, bir parçanın kendi menü öğelerini nasıl ekleyebileceğini gösterir.
Y2i

1

Tüm yorumları ve cevapları okuduktan sonra bu sorun için en uygun çözümü açıklayacağım. En iyi seçenek @ rik'in çözümü, bu yüzden gelişimim onun temelidir.

Her FragmentClass'a sormak yerine

if(FragmentClass1){
   ...
if(FragmentClass2){
   ...
}

Kendi arayüzünüzü oluşturun ve çocuğunuzun parçalarının onu uygulamasını sağlayın.

public interface MyChildFragment {
    void updateView(int position);
}

Ardından, iç parçalarınızı başlatmak ve güncellemek için böyle bir şey yapabilirsiniz.

Fragment childFragment = (Fragment) mViewPagerDetailsAdapter.instantiateItem(mViewPager,mViewPager.getCurrentItem());

if (childFragment != null) {
   ((MyChildFragment) childFragment).updateView();
}

Eğer bu kodu nereye koyduğunu PS sistem önce insatiateItem çağırırsanız aslında oluşturmak, dikkatli olun savedInstanceStatebunun boş Çocuğunuz fragmanının olacak

public void onCreate(@Nullable Bundle savedInstanceState){
      super(savedInstanceState)
}

Uygulamanızı kilitler.

İyi şanslar


1

Cevapladığı şeye dayanarak @chahat jain:

"ViewPager aracını kullandığımızda, etkinlikteki parça örneğine erişmenin iyi bir yolu instantiateItem (viewpager, index). // index- örneğini istediğiniz parçanın dizinidir."

Bunu kotlin'de yapmak istiyorsan

val fragment =  mv_viewpager.adapter!!.instantiateItem(mv_viewpager, 0) as Fragment
                if ( fragment is YourFragmentFragment)
                 {
                    //DO somthign 
                 }

0'ın parça örneğine 0

// ================================================ ========================= // // ##################### ######## Kullanım örnekleri ################################# // // == ================================================== ===================== //

İşte akıl almaz bir vizyon elde etmek için tam bir örnek

İşte .xml dosyasındaki veiewPager'im

   ...
    <android.support.v4.view.ViewPager
                android:id="@+id/mv_viewpager"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_margin="5dp"/>
    ...

Ve sekmeyi eklediğim ev etkinliği

...
import kotlinx.android.synthetic.main.movie_tab.*

class HomeActivity : AppCompatActivity() {

    lateinit var  adapter:HomeTabPagerAdapter

    override fun onCreate(savedInstanceState: Bundle?) {
       ...
    }



    override fun onCreateOptionsMenu(menu: Menu) :Boolean{
            ...

        mSearchView.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
          ...

            override fun onQueryTextChange(newText: String): Boolean {

                if (mv_viewpager.currentItem  ==0)
                {
                    val fragment =  mv_viewpager.adapter!!.instantiateItem(mv_viewpager, 0) as Fragment
                    if ( fragment is ListMoviesFragment)
                        fragment.onQueryTextChange(newText)
                }
                else
                {
                    val fragment =  mv_viewpager.adapter!!.instantiateItem(mv_viewpager, 1) as Fragment
                    if ( fragment is ListShowFragment)
                        fragment.onQueryTextChange(newText)
                }
                return true
            }
        })
        return super.onCreateOptionsMenu(menu)
    }
        ...

}

0

Faaliyetlerimde:

int currentPage = 0;//start at the first tab
private SparseArray<Fragment> fragments;//list off fragments
viewPager.setOnPageChangeListener(new OnPageChangeListener() {

@Override
public void onPageSelected(int pos) {
        currentPage = pos;//update current page
}

@Override
public void onPageScrolled(int arg0, float arg1, int arg2) {}
@Override
public void onPageScrollStateChanged(int arg0) {}
});



@Override
public void onAttachFragment(Fragment fragment) {
    super.onAttachFragment(fragment);
    if(fragment instanceof Fragment1)
        fragments.put(0, fragment);
    if(fragment instanceof Fragment2)
        fragments.put(2, fragment);
    if(fragment instanceof Fragment3)
        fragments.put(3, fragment);
    if(fragment instanceof Fragment4)
        fragments.put(4, fragment);
}

Then I have the following method for getting the current fragment

public Fragment getCurrentFragment() {
    return fragments.get(currentPage);
}

0
final ViewPager.OnPageChangeListener onPageChangeListener =
    new ViewPager.OnPageChangeListener() {
      @Override public void onPageSelected(int position) {
        switch (position) {
          case 0:
            FragmentClass1 frag1 =
                (FragmentClass1) viewPager.getAdapter()
                    .instantiateItem(viewPager, viewPager.getCurrentItem());
            frag1.updateList("Custom text");
            break;
          case 1:
            break;
          case 2:
            break;
        }
      }

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

      }

      @Override public void onPageScrollStateChanged(int state) {
      }
    };


 viewPager.addOnPageChangeListener(onPageChangeListener);

viewPager.setAdapter(adapter);


viewPager.post(new Runnable() {
  @Override public void run() {
    onPageChangeListener.onPageSelected(viewPager.getCurrentItem());
  }
});

Bazen parça null bir nesne gönderebilir, böylece ilk yükte sorunu çözmek için yeni bir Runnable çalıştırabilirsiniz.

Teşekkürler rick


Lütfen bu kodun neden OP'nin sorununu çözeceğini açıklayan bir metin ekleyin. Ayrıca, başka kaç cevap olduğu düşünüldüğünde, bu cevabın neden verilenden daha iyi olduğunu açıklayın. Diğerlerinin anlamasına yardımcı olun.
APC

0

FragmentPagerAdapter öğenizden setPrimaryItem'i geçersiz kılma: nesne görünür parçadır:

 @Override
        public void setPrimaryItem(ViewGroup container, int position, Object object) {
            if (mCurrentFragment != object) {
                mCurrentFragment = (LeggiCapitoloFragment) object;
            }
            super.setPrimaryItem(container, position, object);
        }

0

Geçerli öğeyi çağrı cihazından alın ve adaptörünüzden bu konumun parçasına sorun.

 int currentItem = viewPager.getCurrentItem();
    Fragment item = mPagerAdapter.getItem(currentItem);
    if (null != item && item.isVisible()) {
       //do whatever want to do with fragment after doing type checking
        return;
    }

3
Ya getItemyeni bir örnek oluşturursa
Prakash Nadar

0

Geçerli parçayı almak için - ViewPager PageSelected (son int konumu) genel boşluğa pozisyon alın ve ardından

public PlaceholderFragment getFragmentByPosition(Integer pos){
    for(Fragment f:getChildFragmentManager().getFragments()){
        if(f.getId()==R.viewpager && f.getArguments().getInt("SECTNUM") - 1 == pos) {
            return (PlaceholderFragment) f;
        }
    }
    return null;
}

SECTNUM - genel statik PlaceholderFragment newInstance (int sectionNumber) içinde atanan konum bağımsız değişkeni ; Parçanın

getChildFragmentManager () veya getFragmentManager () - nasıl oluşturulduğuna bağlıdır SectionsPagerAdapter


0

Fragment'a bir BroadcastReceiver uygulayabilir ve her yerden bir Amaç gönderebilirsiniz. Parçanın alıcısı belirli eylemi dinleyebilir ve örneğin yöntemini çağırabilir.

Bir uyarı, View bileşeninin zaten somutlaştırıldığından emin olmaktır ve (ve bir listeyi kaydırma gibi bazı işlemler için ListView zaten oluşturulmalıdır).


0

Bu en basit kesmek:

fun getCurrentFragment(): Fragment? {
    return if (count == 0) null
    else instantiateItem(view_pager, view_pager.currentItem) as? Fragment
}

(kotlin kodu)

Sadece arayın instantiateItem(viewPager, viewPager.getCurrentItem()ve şuraya yayınlayın Fragment. Öğeniz zaten somutlaştırılmış olacaktı. Emin olmak için bir kontrol ekleyebilirsiniz getCount.

Hem ile çalışır FragmentPagerAdapterve FragmentStatePagerAdapter!


0

Çağrı cihazınız bir Parçanın içindeyse bunu kullanın:

private fun getPagerCurrentFragment(): Fragment? {
    return childFragmentManager.findFragmentByTag("android:switcher:${R.id.myViewPagerId}:${myViewPager.currentItem}")
}

R.id.myViewPagerIdXml Layout içindeki ViewPager öğenizin kimliği nerede .


Bu yalnızca normal FragmentPageAdapter ile çalışır, FragmentStatePageAdapter ile çalışmaz.
progNewbie

0

Bir fragman dizisini kayıt fragmanları olarak bildirebilirsiniz

class DashboardPagerAdapter(fm: FragmentManager?) : FragmentStatePagerAdapter(fm!!) {
    // CURRENT FRAGMENT
    val registeredFragments = SparseArray<Fragment>()

    override fun instantiateItem(container: ViewGroup, position: Int): Any {
        val fragment = super.instantiateItem(container, position) as Fragment
        registeredFragments.put(position, fragment)
        return fragment
    }

    override fun getItem(position: Int): Fragment {
        return when (position) {
            0 -> HomeFragment.newInstance()
            1 -> ConverterDashboardFragment.newInstance()
            2 -> CartFragment.newInstance()
            3 -> CustomerSupportFragment.newInstance()
            4 -> ProfileFragment.newInstance()
            else -> ProfileFragment.newInstance()
        }
    }

    override fun getCount(): Int {
        return 5
    }

}

Sonra kullanabilirsiniz

adapter?.let {
    val cartFragment = it.registeredFragments[2] as CartFragment?
    cartFragment?.myCartApi(true)
}

Bu şekilde gitmeye karar verirseniz, destroyItem () yöntemini uygulamanız ve destroyed örneğini kayıtlıFragments'tan kaldırmanız gerekir, aksi takdirde bir bellek sızıntısı olur.
dephinera

Bu iyi bir öneri. Cevapta bir düzenleme yapabilirsiniz.
Hamza Khan

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.