Android获取FragmentPagerAdapter中的片段

Posted

技术标签:

【中文标题】Android获取FragmentPagerAdapter中的片段【英文标题】:Android getting fragment that is in 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 Companies416d7b78 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) 
    

提前感谢您的回答。

【问题讨论】:

【参考方案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,里面有ViewPagerViewPager 包含 2 个片段的 FragmentPagerAdapter。因此,为了重用片段,我将方法放在 ActivityfindFragmentByTag() 中的 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 的示例代码。

【讨论】:

***.com/questions/6976027/…【参考方案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()

【讨论】:

以上是关于Android获取FragmentPagerAdapter中的片段的主要内容,如果未能解决你的问题,请参考以下文章

xamarin怎样获取android外卡路径

Android View如何获取焦点

android怎么获取drawble图片高宽

android怎么获取fragment屏幕宽度

android获取本地文件名字?

Android快速获取联系人