我有一个带有aViewPager
和3 Fragment
s的应用程序。我正在尝试弄清楚如何Fragment
查看当前内容,以便了解其参数。
我正在OnPageChangeListener
抓取当前页面索引,但是
ViewPager.getChildAt(int position);
返回View
。这View
和当前之间有什么关系Fragment
?
Answers:
我已经反过来解决了这个问题。我没有从活动中搜索片段,而是在其所有者活动的onAttach()方法期间注册了该片段,并在onStop()方法中将其取消了注册。基本思路:
分段:
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try{
mActivity = (IMyActivity)activity;
}catch(ClassCastException e){
throw new ClassCastException(activity.toString() +" must be a IMyActivity");
}
mActivity.addFragment(this);
}
@Override
public void onStop() {
mActivity.removeFragment(this);
super.onStop();
}
IMyActivity:
public interface IFriendActivity {
public void addFragment(Fragment f);
public void removeFragment(Fragment f);
}
我的活动:
public class MyActivity implements IMyActivity{
[...]
@Override
public void addFragment(Fragment f) {
mFragments.add(f);
}
@Override
public void removeFragment(Fragment f) {
mFragments.remove(f);
}
}
OnAttach
未调用是在您OnStop
仍处于调用状态时折叠活动。
编辑-不要这样做。如果您很想这样做,请阅读注释,了解为什么这是一个坏主意。
在奇怪的机会上,您仍在尝试解决此问题:
扩展FragmentPagerAdapter
。在构造函数中,构建所需的片段,并将其存储在片段列表(数组/ ArrayList)中。
private final int numItems = 3;
Fragment[] frags;
public SwipeAdapter (FragmentManager fm) {
super(fm);
//Instantiate the Fragments
frags = new Fragment[numItems];
Bundle args = new Bundle();
args.putString("arg1", "foo");
frags[0] = new MyFragment();
frags[1] = new YourFragment();
frags[2] = new OurFragment();
frags[2].setArguments(args);
}
然后getItem(int position)
,您可以执行类似
public Fragment getItem(int position) {
return frags[position];
}
我不确定这是否是普遍接受的方式,但对我有用。
编辑
这确实不是一个好方法。如果您打算处理方向更改或您的应用程序进入后台,那么这很可能会破坏您的代码。请阅读此答案下方的评论以获取更多信息。宁可使用@James的答案
getActivity()
不会返回当前活动,但是某些先前的实例已被销毁
是的,如果您正在使用,这是可能的FragmentStatePagerAdapter
。
ViewPager vp;
//...
YourFragment fragment = (YourFragment) adapter.instantiateItem(vp, vp.getCurrentItem());
请不要使用这个
使您的适配器扩展以下FragmentStatePagerWithCurrentAdapter
类,而不是实现getItem
将相同的代码实现为getItemAtIndex
将设置ViewPager
OnPageChangeListener
为适配器的实例。
当您需要访问当前的Fragment时,只需调用adapter.getCurrentItem()
。
package your.package;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentStatePagerAdapter;
import android.support.v4.view.ViewPager.OnPageChangeListener;
import android.util.SparseArray;
import android.view.ViewGroup;
public abstract class FragmentStatePagerWithCurrentAdapter
extends FragmentStatePagerAdapter
implements OnPageChangeListener {
int currentPage = 0;
private SparseArray<Fragment> mPageReferenceMap = new SparseArray<Fragment>();
public FragmentStatePagerWithCurrentAdapter(FragmentManager fm) {
super(fm);
}
@Override
public final Fragment getItem(int index) {
Fragment myFragment = getItemAtIndex(index);
mPageReferenceMap.put(index, myFragment);
return myFragment;
}
public abstract Fragment getItemAtIndex(int index);
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
super.destroyItem(container, position, object);
mPageReferenceMap.remove(Integer.valueOf(position));
}
public Fragment getCurrentItem() {
return mPageReferenceMap.get(currentPage);
}
@Override
public void onPageScrollStateChanged(int arg0) {
}
@Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
}
@Override
public void onPageSelected(int newPageIndex) {
currentPage = newPageIndex;
}
}
我将以下博客文章用作参考:http : //tamsler.blogspot.com/2011/11/android-viewpager-and-fragments-part-ii.html
在这里进行了解释:http : //developer.android.com/guide/topics/fundamentals/fragments.html
在OnCreateView中,您必须返回一个视图以为片段绘制UI,我认为这就是关系。
这个问题也可能是类似的:从ViewPager获取焦点视图
getFragmentManager().findFragmentById(R.id.fragment_container);
那怎么办 我认为您将在该容器中获得当前片段。
您可以这样做:-在视图分页器适配器的类范围内(例如PagerAdapter,FragmentStatePagerAdapter ...),重写方法InstantiateItem:
@Override
public Object instantiateItem(ViewGroup container, int position) {
final Fragment frag = (Fragment) super.instantiateItem(container, position);
if(frag instanceof ListNoteOfTypeFragment){
final ListNoteOfTypeFragment listNoteOfTypeFragment = (ListNoteOfTypeFragment) frag;
//do whatever you want with your fragment here
listNoteOfTypeFragment.setNoteChangeListener(mListener);
}
return frag;
}
可以无缝运行的确定性答案(但小技巧):
页面片段布局中的某处:
<FrameLayout android:layout_width="0dp" android:layout_height="0dp" android:visibility="gone" android:id="@+id/fragment_reference">
<View android:layout_width="0dp" android:layout_height="0dp" android:visibility="gone"/>
</FrameLayout>
在片段的onCreateView()中:
...
View root = inflater.inflate(R.layout.fragment_page, container, false);
ViewGroup ref = (ViewGroup)root.findViewById(R.id.fragment_reference);
ref.setTag(this);
ref.getChildAt(0).setTag("fragment:" + pageIndex);
return root;
和从ViewPager返回Fragment的方法(如果存在):
public Fragment getFragment(int pageIndex) {
View w = mViewPager.findViewWithTag("fragment:" + pageIndex);
if (w == null) return null;
View r = (View) w.getParent();
return (Fragment) r.getTag();
}
豪尔赫·加西亚(Jorge Garcia)的FragmentStatePagerWithCurrentAdapter是一个很好的解决方案,但还需要一点改进。如果活动因响应配置更改而销毁并重新创建,或者类似的事件,则不会为片段管理器保存和检索的片段调用getItem。所以我通常在子类中重写getItem,然后将以下内容放入FragmentStatePagerWithCurrentAdapter中
@Override
public Object instantiateItem(ViewGroup container, int position) {
Object item = super.instantiateItem(container, position);
if ( item instanceof Fragment ) {
pageReferenceMap.put(position, (Fragment)item);
}
return item;
}
每次访问该位置的片段时,都会调用InstantiateItem。
或者只是将所有片段保存在地图中:
public class MyFragment extends Fragment implements OnPageChangeListener {
private ViewPager viewPager;
private FragmentStatePagerAdapter viewAdapter;
private View rootView;
private Map<Integer, Fragment> fragments = new HashMap<Integer, Fragment>();
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.introdution, container, false);
viewPager = (ViewPager) rootView.findViewById(R.id.pager);
viewAdapter = new ViewAdapter(getFragmentManager());
viewPager.setAdapter(viewAdapter);
viewPager.addOnPageChangeListener(this);
return rootView;
}
private class ViewAdapter extends FragmentStatePagerAdapter {
public ViewAdapter(FragmentManager fragmentManager) {
super(fragmentManager);
}
@Override
public Fragment getItem(int position) {
Fragment result = null;
switch (position) {
case 0: result = Fragment1.newInstance(); break;
case 1: result = Fragment2.newInstance(); break;
}
if (result != null)
fragments.put(position, result);
return result;
}
@Override
public int getCount() {
return 2;
}
}
@Override
public void onPageScrollStateChanged(int arg0) {
}
@Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
}
@Override
public void onPageSelected(int position) {
Fragment currentFragment = fragments.get(position);
}
}