2012-08-15 12 views
33

Mam następujący problem: mam jedno działanie, w którym mam dwie wypustki, które są skierowane zarówno jako fragmenty używając FragmentPagerAdapter W pewnym momencie chciałbym zmienić widok jednego z nich fragmenty, ale nie jestem w stanie findFragmentById() lub findFragmentByTag() jestem w stanie ustawić identyfikator, bo ja nie deklarując Fragment XML, ze względu na FragmentPagerAdapter A gdy próbuję ustawić znacznik Otrzymuję następujący problem:Android coraz fragment, który jest w FragmentPagerAdapter

08-15 21:46:23.805: E/AndroidRuntime(9297): java.lang.IllegalStateException: Can't change tag of fragment Companies{416d7b78 id=0x7f04002e companies}: was companies now android:switcher:2130968622:1 

Mój kod pager FragmentPagerAdapter:

public class TabsAdapter extends FragmentPagerAdapter implements ActionBar.TabListener, ViewPager.OnPageChangeListener { 
    private final FragmentActivity mContext; 
    private final ActionBar mActionBar; 
    private final ViewPager mViewPager; 
    private final ArrayList<TabInfo> mTabs = new ArrayList<TabInfo>(); 


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

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

    public TabsAdapter(SherlockFragmentActivity 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 int getCount() { 
     return mTabs.size(); 
    } 

    @Override 
    public Fragment getItem(int position) { 
     TabInfo info = mTabs.get(position); 
     FragmentTransaction ft=mContext.getSupportFragmentManager().beginTransaction(); 
     Fragment fragment=Fragment.instantiate(mContext, info.clss.getName(), info.args); 

     if(position==1){ 
      ft.add(mViewPager.getId(), fragment, "companies"); 
     }else{ 
      ft.add(mViewPager.getId(), fragment); 
     } 
     Log.v("FRAGMENT ID", "fragment tag: "+fragment.getTag()); 
     ft.commit(); 
     Log.v("FRAGMENT ID", "fragment tag: "+fragment.getTag()); 
     return fragment; 
    } 

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

    @Override 
    public void onPageSelected(int position) { 
     mActionBar.setSelectedNavigationItem(position); 
     new Thread(new Runnable() { 

      @Override 
      public void run() { 
       MainActivity.this.hideKeyboard(); 

      } 
     }).start(); 

    } 

    @Override 
    public void onPageScrollStateChanged(int state) { 
    } 

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


    } 

    @Override 
    public void onTabUnselected(Tab tab, FragmentTransaction ft) { 


    } 

    @Override 
    public void onTabReselected(Tab tab, FragmentTransaction ft) { 
    } 
} 

Z góry dziękuję za odpowiedzi.

Odpowiedz

50

Fragmenty dostarczone przez FragmentPagerAdapter są automatycznie oznaczane tagami po ich utworzeniu. Można pobrać tag z tą metodą:

private static String makeFragmentName(int viewPagerId, int index) { 
    return "android:switcher:" + viewPagerId + ":" + index; 
} 

Reference: reusing fragments in a fragmentpageradapter

+0

Dziękuję, to działało dla mnie. – ziky90

+15

Uwaga dla osób takich jak ja: viewId to id z ViewPager – htafoya

+0

niech cię Bóg błogosławi !! – user1767754

6

znalazłem nieco mniej brutto sposób, aby uzyskać uchwyt na Fragment stworzonej przez FragmentPagerAdapter. Zamiast naśladować sposób tworzenia znaczników, przesuń instantiateItem(), zwróć wartość Fragment zwróconą przez nadklasę i zapisz znacznik w TabInfo. Działa to dla mnie na API> = 15, może pracować z niższym. To nadal sprawia, że ​​niektóre założenia dotyczące kodu prywatnego.

static final class TabInfo { 
    private final Class<?> clss; 
    private final Bundle args; 
    private String tag; // ** add this 

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


@Override 
public Object instantiateItem(ViewGroup container, int position) { 
    final Fragment fragment = (Fragment) super.instantiateItem(container, position); 
    final TabInfo info = mTabs.get(position); 
    info.tag = fragment.getTag(); // set it here 
    return fragment; 
} 

Albo API < 16, myślę instantiateItem() trwa View() zamiast ViewGroup(), tak:

public Object instantiateItem(View container, int position); 

Następnie pozostawić sposób, aby uzyskać Fragment, utrzymując hack zawarte.

public Fragment getFragment(int index) { 
    return mContext.getFragmentManager().findFragmentByTag(mTabs.get(index).tag); 
} 

Do tego do pracy, zgłoszenie o mContext musi się zmienić, aby Activity, jest przekazywana w postaci Activity każdym razie:

private final Activity mContext; 
+1

próbuje zastosować to rozwiązanie, ale ** super.instantiateItem (kontener, pozycja) ** wyrzuca ** NPE ** dla mnie zarówno FragmentPagerAdapter jak i FragmentStatePagerAdapter – Sash0k

21

Dzięki tej funkcji można znaleźć fragment według pozycji adaptera pager.

public Fragment findFragmentByPosition(int position) { 
    FragmentPagerAdapter fragmentPagerAdapter = getFragmentPagerAdapter(); 
    return getSupportFragmentManager().findFragmentByTag(
      "android:switcher:" + getViewPager().getId() + ":" 
        + fragmentPagerAdapter.getItemId(position)); 
} 

Przykładowy kod dla api wsparcia v4.

+0

http://stackoverflow.com/ pytania/6976027/ponowne wykorzystanie-fragmenty-w-a-fragmentpageradapter/29287415 # 29287415 –

-1

Jest bardzo późno, aby odpowiedzieć na to pytanie, ale wiele przeszukałem nikt nie mówi mi dokładnej odpowiedzi, może ktoś znalazł to przydatne.

Kładę moje fragmenty poprzez FragmentPagerAdapter i zrobiłem komunikację między fragmentami

https://developer.android.com/training/basics/fragments/communicating.html#Deliver

następującą ten link i za FindFragmentById po prostu stosować viewpager.getId() na główną działalność.

1

Prostszym podejściem jest uzyskanie znaczników bezpośrednio z Menedżera fragmentów; w następujący sposób:

fm.getFragments().get(0).getTag() 

Możesz zastąpić pozycję, w zależności od fragmentu, do którego potrzebujesz znacznika. Mam nadzieję, że to pomoże innym !.

Powiązane problemy