Android FragmentStatePagerAdapter
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10656323/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Android FragmentStatePagerAdapter
提问by mraviator
I'm working with a FragmentStatePagerAdapter using this example.
我正在使用这个 example使用 FragmentStatePagerAdapter 。
The MyAdapter class is implemented as follows:
MyAdapter 类实现如下:
public static class MyAdapter extends FragmentStatePagerAdapter {
public MyAdapter(FragmentManager fm) {
super(fm);
}
@Override
public int getCount() {
return NUM_ITEMS;
}
@Override
public Fragment getItem(int position) {
return ArrayListFragment.newInstance(position);
}
}
The ListFragment class includes the following method to create a new instance:
ListFragment 类包括以下创建新实例的方法:
/**
* Create a new instance of CountingFragment, providing "num"
* as an argument.
*/
static ArrayListFragment newInstance(int num) {
ArrayListFragment f = new ArrayListFragment();
// Supply num input as an argument.
Bundle args = new Bundle();
args.putInt("num", num);
f.setArguments(args);
return f;
}
When I create a new fragment state pager adapter in my activity, getItem
is called, which in turn calls the newInstance
method in the ListFragment class. This is great when I want to create a new fragment.
当我在我的活动中创建一个新的片段状态寻呼适配器时,getItem
被调用,它依次调用newInstance
ListFragment 类中的方法。当我想创建一个新片段时,这很棒。
But it's not clear to me how to modify getItem
(if even needed) to get the fragment object when it already existsand the user pages from, for example, page 2 to page 1. I'd like my Activity to retrieve that existing, previously created fragment so that it can run an inner class AsyncMethod
, which resides in the fragment class.
但是我不清楚如何修改getItem
(如果甚至需要)以在片段对象已经存在以及用户页面从第 2 页到第 1 页时获取它。我希望我的 Activity 检索现有的,以前创建片段以便它可以运行AsyncMethod
驻留在片段类中的内部类。
采纳答案by toobsco42
I have implemented something similar to what you have. I extended the FragmentPagerAdapter
class like so:
我已经实现了类似于你所拥有的东西。我FragmentPagerAdapter
像这样扩展了课程:
public class ContactsFragmentPagerAdapter extends FragmentPagerAdapter {
ActionBar mActionBar;
private List<Fragment> mFragments;
public ContactsFragmentPagerAdapter(FragmentManager fm, List<Fragment> fragments) {
super(fm);
mFragments = fragments;
}
@Override
public int getCount() {
return mFragments.size();
}
@Override
public Fragment getItem(int position) {
return mFragments.get(position);
}
public void setActionBar(ActionBar bar) {
mActionBar = bar;
}
}
Notice I have added an argument to the constructor to pass in the List
of Fragment
objects. This way the getItem()
method of this class can return any class that extends Fragment
or any of its subclasses and not just one specific class ArrayListFragment
like you have done.
请注意,我向构造函数添加了一个参数以传入List
ofFragment
对象。这样,此类的getItem()
方法可以返回任何扩展类Fragment
或其任何子类,而不仅仅是ArrayListFragment
像您所做的那样只返回一个特定类。
In the Activity
where I instantiate my subclass of FragmentPagerAdapter
I have passed in the list of Fragment
objects:
在Activity
我实例化我的子类的地方,FragmentPagerAdapter
我已经传入了Fragment
对象列表:
Class the instantiates the FragmentPagerAdapter
类实例化 FragmentPagerAdapter
public final class ContactManager extends Activity {
private ContactsFragmentPagerAdapter mAdapter;
private ViewPager mPager;
public ActionBar mActionBar;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.contact_manager);
List<Fragment> fragments = new Vector<Fragment>();
fragments.add(Fragment.instantiate(this, ContactsListFragment.class.getName()));
fragments.add(Fragment.instantiate(this, GroupsListFragment.class.getName()));
mAdapter = new ContactsFragmentPagerAdapter(this.getFragmentManager(), fragments);
mPager = (ViewPager) findViewById(R.id.pager);
mPager.setAdapter(mAdapter);
mPager.setOnPageChangeListener(new OnPageChangeListener() {
@Override
public void onPageScrollStateChanged(int arg0) {}
@Override
public void onPageScrolled(int arg0, float arg1, int arg2) {}
@Override
public void onPageSelected(int arg0) {
mActionBar.getTabAt(arg0).select();
}
});
}
}
By accessing the variable "fragments", you can access a previously created Fragment
so that you can run methods of that Fragment
.
通过访问变量“fragments”,您可以访问先前创建Fragment
的Fragment
.
回答by imiric
I think the solution is much simpler than the answers provided.
我认为解决方案比提供的答案简单得多。
If you take a look at the source of FragmentStatePagerAdapter.instantiateItem()
, you'll notice that instantiateItem()
handles this logic for you, and thus your implementation of getItem()
should always return a new instance.
如果您查看 的源代码FragmentStatePagerAdapter.instantiateItem()
,您会注意到它instantiateItem()
为您处理此逻辑,因此您的 实现getItem()
应始终返回一个新实例。
So in order to return an existing Fragment, simply do (assuming you're calling from ViewPager
):
因此,为了返回现有的 Fragment,只需执行以下操作(假设您从 调用ViewPager
):
Fragment f = (Fragment) getAdapter().instantiateItem(this, getCurrentItem());
回答by qix
While @imiric's solution is very concise, it still bothers me that it requires knowledge of the implementation of the class. My solution involves adding the following to your adapter, which should behave nicely with a FragmentStatePagerAdapter possibly destroying fragments:
虽然@imiric 的解决方案非常简洁,但它需要了解类的实现,这仍然困扰着我。我的解决方案包括将以下内容添加到您的适配器中,它应该与 FragmentStatePagerAdapter 可能会破坏片段表现良好:
private SparseArray<WeakReference<Fragment>> mFragments = new SparseArray<>();
@Override
public Object instantiateItem(ViewGroup container, int position) {
Fragment f = (Fragment) super.instantiateItem(container, position);
mFragments.put(position, new WeakReference<>(f)); // Remember what fragment was in position
return f;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
super.destroyItem(container, position, object);
mFragments.remove(position);
}
public Fragment getFragment(int position) {
WeakReference<Fragment> ref = mFragments.get(position);
Fragment f = ref != null ? ref.get() : null;
if (f == null) {
Log.d(TAG, "fragment for " + position + " is null!");
}
return f;
}
回答by farid_z
public class MyPagerAdapter extends FragmentStatePagerAdapter {
final Context m_context;
final WeakReference<Fragment>[] m_fragments;
public DetailPagerAdapter(FragmentManager fm) {
super(fm);
m_context = ...
m_fragments = new WeakReference[enter size here];
}
@Override
public Fragment getItem(int position) {
final Fragment fragment = instantiate your fragment;
m_fragments[position] = new WeakReference<Fragment>(fragment);
return fragment;
}
@Override
public int getCount() {
return ...
}
public Fragment getFragment(final int position) {
return m_fragments[position] == null ? null :
m_fragments[position].get();
}
}
回答by Daniel De León
Do not need modify the FragmentPagerAdapter, because fragments are cached by the FragmentManager. So you must need find inside it. Use this function to find the fragment by pager adapter position.
不需要修改 FragmentPagerAdapter,因为 FragmentManager 缓存了 FragmentPagerAdapter。所以你必须在里面找到。使用此函数可通过寻呼机适配器位置查找片段。
public Fragment findFragmentByPosition(int position) {
FragmentPagerAdapter fragmentPagerAdapter = getFragmentPagerAdapter();
return getSupportFragmentManager().findFragmentByTag(
"android:switcher:" + getViewPager().getId() + ":"
+ fragmentPagerAdapter.getItemId(position));
}
Sample code for v4 support api.
v4 支持 api 的示例代码。