如何在 MainActivity 中获取 ViewPager 创建的 Fragment 的元素?
我有几个用 ViewPager
组织的片段.我将 addOnPageChangeListener
添加到 MainActivity 的 onCreate
方法中的 ViewPager
中,该方法给出了所选片段的位置.
即使我通过声明 setOffscreenPageLimit
来防止 Fragment 自行破坏,但我仍然没有弄清楚如何从 MainActivity 访问 Fragment,因为只需使用 findViewById
返回空对象异常.
我想做的事:
我想访问片段的元素,例如布局和滚动视图,在 ViewPager
的 OnPageListener
中:
mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {@覆盖公共无效 onPageSelected(int i) {如果(我 == 0){//对第一个片段做一些事情.}否则如果(我== 1){//对第二个片段做一些事情.}}}
ViewPager
使用 FragmentPagerAdapter
:
公共类 SectionsPagerAdapter 扩展 FragmentPagerAdapter {公共 SectionsPagerAdapter(FragmentManager fm) {超级(调频);}@覆盖公共片段getItem(int位置){开关(位置){案例0:返回 Fragment1.newInstance(位置);情况1:返回 Fragment2.newInstance(位置);案例2:返回 Fragment3.newInstance(位置);案例3:返回 Fragment4.newInstance(位置);默认:抛出新的 IllegalArgumentException();}}@覆盖公共 int getCount() {返回 4;}}
是这样添加的:
mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());mViewPager.setAdapter(mSectionsPagerAdapter);
~
或者我应该改变我的方法吗?
如果使用这种设计无法访问片段,那么有效的替代途径是什么?
我曾尝试在自定义ViewPager
中实现ViewPager.onPageChangeListener
,但这似乎不是一个好的选择.
我可以处理它们各自片段中的元素,但这是一个乏味的过程并且难以维护,这就是我寻找一种同时处理它们的方法的原因.
我知道以前有人问过类似的问题,但我没有找到解决方案.
解决方案不幸的是,唯一的安全"方法是检查FragmentPagerAdapter
的源代码,并查看添加片段的 tag
是什么 - 因为 findFragmentByTag
是从 FragmentManager 获取片段的唯一安全方法.
当然,我们需要希望这个实现细节不会在不同的支持库版本之间发生变化,但实际上多年来并没有改变 :)
<小时>无论如何,FragmentPagerAdapter 说:
<块引用>//我们是否已经有了这个片段?字符串名称 = makeFragmentName(container.getId(), itemId);片段片段 = mFragmentManager.findFragmentByTag(name);
那么name
是什么?
private static String makeFragmentName(int viewId, long id) {返回 "android:switcher:" + viewId + ":" + id;}
什么是viewId
,什么是id
?
ViewId 是 container.getId()
,其中 container
是 ViewPager
本身.
id
为:final long itemId = getItemId(position);
默认为return position;
.
所以你可以找到片段如下:
片段片段 = fragmentManager.findFragmentByTag("android:switcher:" + viewPager.getId() + ":" + fragmentPosition);//如果fragment为null,它还没有被ViewPager创建
<小时>
注意:
值得注意的是,您不应该依赖 getItem(int position) {
来返回 与您传入的片段实例相同的片段实例,因为这会导致您这个问题.(这道题做对了,getItem()
方法必须总是返回一个新的 Fragment 实例.)
I have several fragments which are organized with a ViewPager
. I add an addOnPageChangeListener
to the ViewPager
in MainActivity's onCreate
method which gives the position of the selected fragment.
Even though I prevent the fragments from destroying themselves with stating a setOffscreenPageLimit
, I still haven't figured out how to access fragments from MainActivity, as simply using findViewById
returns null object exceptions.
What I want to do:
I would like to access elements of fragments, e.g. layouts and scrollviews, in the OnPageListener
of the ViewPager
:
mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageSelected(int i) {
if(i == 0) {
// Do something with the first fragment.
} else if(i == 1) {
// Do something with the second fragment.
}
}
}
The ViewPager
uses a FragmentPagerAdapter
:
public class SectionsPagerAdapter extends FragmentPagerAdapter {
public SectionsPagerAdapter(FragmentManager fm) {
super(fm);
}
@Override
public Fragment getItem(int position) {
switch (position) {
case 0:
return Fragment1.newInstance(position);
case 1:
return Fragment2.newInstance(position);
case 2:
return Fragment3.newInstance(position);
case 3:
return Fragment4.newInstance(position);
default:
throw new IllegalArgumentException();
}
}
@Override
public int getCount() {
return 4;
}
}
Which is added like this:
mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
mViewPager.setAdapter(mSectionsPagerAdapter);
~
Or should I change my approach?
If accessing fragments cannot be achieved with this design, what could be an effective alternative route?
I've tried to implement ViewPager.onPageChangeListener
in the custom ViewPager
, but it didn't seem to be a good option.
I could deal with the elements in their respective fragments, but this is a tedious process and hard to maintain, which I the reason I look for a way to handle them simultaneously.
I know similar questions have been asked before, but I didn't find a solution in them.
解决方案Unfortunately the only "safe" way to do it is to check the source code of FragmentPagerAdapter
, and see what tag
is the fragment is added with - because findFragmentByTag
is the only safe way to get a Fragment from a FragmentManager.
Of course, we need to hope that this implementation detail doesn't change between support library versions, but it actually hasn't changed in years :)
Anyways, so FragmentPagerAdapter says:
// Do we already have this fragment? String name = makeFragmentName(container.getId(), itemId); Fragment fragment = mFragmentManager.findFragmentByTag(name);
So what is name
?
private static String makeFragmentName(int viewId, long id) { return "android:switcher:" + viewId + ":" + id; }
What is viewId
and what is id
?
ViewId is container.getId()
, where container
is the ViewPager
itself.
id
is: final long itemId = getItemId(position);
which by default is return position;
.
So you can find the Fragment as follows:
Fragment fragment = fragmentManager.findFragmentByTag("android:switcher:" + viewPager.getId() + ":" + fragmentPosition);
// if fragment is null, it was not created yet by ViewPager
NOTE:
It is worth noting that you should NOT rely on getItem(int position) {
to return the same fragment instance as you passed in, because that will lead you to this problem. (This question does it correctly, the getItem()
method must always return a new Fragment instance.)
相关文章