【问题标题】:Android getting fragment that is in FragmentPagerAdapterAndroid获取FragmentPagerAdapter中的片段
【发布时间】:2012-08-12 04:00:33
【问题描述】:

我有以下问题: 我有一个活动,其中我有两个选项卡,它们都使用 FragmentPagerAdapter 作为片段 在某些时候,我想更改其中一个片段的视图,但我无法 findFragmentById() 或 findFragmentByTag() 我无法设置 id,因为我没有在 XML 中声明 Fragment,因为 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

我的寻呼机代码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) {
    }
}

提前感谢您的回答。

【问题讨论】:

    标签: android android-fragments fragmentpageradapter


    【解决方案1】:

    由 FragmentPagerAdapter 提供的片段在实例化时会自动标记。您可以使用此方法检索标签:

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

    Reference: reusing fragments in a fragmentpageradapter

    【讨论】:

    • 像我这样的人注意:viewId 是 ViewPager 的 id
    • 我以为方法是放在扩展FragmentPagerAdapter的类中,但方法应该只是放在Fragment类中。
    • @Robert:片段并不总是在视图分页器中使用,但FragmentPagerAdapter 总是在视图分页器中使用。将它放在Fragment 中是没有意义的。
    • @DeeV 对不起,我的错不是片段,而是活动。在我的例子中,有一个Activity,里面有ViewPager。 ViewPager 包含 2 个片段的 FragmentPagerAdapter。因此,为了重用片段,我将方法放在 Activity 到 findFragmentByTag() 中的 ViewPager 布局中。
    • 为什么要这样做?我的意思是,如果您从它的位置生成片段名称,只需按位置直接获取它。 .getSupportFragmentManager().getFragments().get(position) 或 .getChildFragmentManager().getFragments().get(position)
    【解决方案2】:

    使用此功能,您可以通过寻呼机适配器位置找到片段。

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

    v4 支持 api 的示例代码。

    【解决方案3】:

    我发现了一种稍微不那么粗暴的方法来处理由FragmentPagerAdapter 创建的Fragment。 不要模仿标签的创建方式,而是覆盖instantiateItem(),获取超类返回的Fragment,并将标签保存在TabInfo中。这适用于我的 API >= 15,可能适用于更低的版本。这仍然对私有代码做出了一些假设。

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

    或者在 API instantiateItem() 采用 View() 而不是 ViewGroup(),如下所示:

    public Object instantiateItem(View container, int position);
    

    然后提供一种获取Fragment 的方法,从而控制黑客攻击。

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

    为此,mContext 的声明需要更改为 Activity,无论如何它作为 Activity 传入:

    private final Activity mContext;
    

    【讨论】:

    • 试图应用此解决方案,但 super.instantiateItem(container, position) 为我抛出了 NPE FragmentPagerAdapter 和 FragmentStatePagerAdapter
    【解决方案4】:

    一个更简单的方法是直接从片段管理器中获取标签;像这样:

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

    您可以替换位置,具体取决于您需要标记的片段。希望这对其他人有帮助!。

    【讨论】:

      【解决方案5】:

      回答这个问题已经很晚了,但是我搜索了很多没有人告诉我确切的答案,可能有人觉得它有用。

      我已经通过FragmentPagerAdapter 设置了我的片段,并且我在片段之间进行了通信

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

      点击此链接,对于 FindFragmentById,我只是在 mainactivity 上使用了 viewpager.getId()。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-07-13
        • 1970-01-01
        • 2012-09-15
        • 1970-01-01
        • 2012-12-11
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多