35 votes

Android obtenant un fragment qui est dans FragmentPagerAdapter

J'ai le problème suivant: J'ai une activité dans laquelle j'ai deux onglets qui sont faites à la fois comme des fragments à l'aide de FragmentPagerAdapter Dans certains moment, je voudrais changer l'Affichage de l'un de ces fragments, mais je ne suis pas en mesure de findFragmentById() ou findFragmentByTag() je suis incapable de définir id, parce que je ne suis pas déclarer Fragment de XML, en raison de la FragmentPagerAdapter Et quand je suis en train de mettre la balise, je suis problème suivant:

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

Mon code de la 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) {
    }
}

Je vous remercie d'avance pour vos réponses.

51voto

DeeV Points 16141

Les fragments fournis par FragmentPagerAdapter sont marqués automatiquement lorsqu'ils sont instanciés. Vous pouvez récupérer la balise avec cette méthode:

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

Référence: réutilisation de fragments dans un fragmentpageradapter

22voto

Daniel De León Points 2842

Avec cette fonction, vous pouvez trouver le fragment par position de l'adaptateur de pager.

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

Exemple de code pour l'API de support v4.

6voto

nash Points 51

J'ai trouvé un peu moins brut de façon à obtenir une poignée sur un Fragment créé par un FragmentPagerAdapter. Au lieu d'imiter la façon dont les balises sont créés, substituer instantiateItem(), obtenir l' Fragment retournée par la super-classe, et d'enregistrer l'étiquette en TabInfo. Cela fonctionne pour moi sur API >= 15, peut travailler avec les plus faibles. De ce fait encore des hypothèses sur un code privé.

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

Ou de l'API de moins de 16 ans, je pense que instantiateItem() prend un View() au lieu de ViewGroup(), comme ceci:

public Object instantiateItem(View container, int position);

Ensuite, permettre à un moyen d'obtenir de l' Fragment, en gardant le hack contenus.

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

Pour que cela fonctionne, la déclaration pour l' mContext des besoins de changer de Activity, il est passé en Activity quand même:

private final Activity mContext;

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X