36

我有以下问题:我有一个活动,其中我有两个选项卡,它们都使用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) {
    }
}

预先感谢您的回答。

4

5 回答 5

51

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

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

参考:在片段页面适配器中重用片段

于 2012-08-15T20:20:48.197 回答
22

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

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

v4 支持 api 的示例代码。

于 2013-06-18T06:06:59.760 回答
6

我发现了一种稍微不那么粗暴的方法来处理FragmentFragmentPagerAdapter. 与其模仿标签的创建方式,不如重写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 < 16 中,我认为instantiateItem()需要 aView()而不是ViewGroup(),如下所示:

public Object instantiateItem(View container, int position);

然后允许一种方法来获取Fragment,保持 hack 被包含在内。

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

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

private final Activity mContext;
于 2012-09-24T20:43:47.227 回答
1

一个更简单的方法是直接从 Fragment Manager 获取标签;像这样:

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

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

于 2017-07-10T05:59:39.817 回答
-1

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

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

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

按照这个链接和 FindFragmentById 我只是在 mainactivity 上使用了viewpager.getId()

于 2016-06-25T09:58:20.153 回答