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
,里面有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 的示例代码。
【讨论】:
***.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中的片段的主要内容,如果未能解决你的问题,请参考以下文章