标签:
英文版api地址:FragmentPagerAdapter(自备梯子)
类概述(Class Overview):
是PagerAdapter的实现类,展示的每一页是Fragment,并且可以长时间持续保存在fragment manager中,以供用户返回到以前的页面。
这种PagerAdapter(即FragmentPagerAdapter)的最佳用法就是用在:少数的、静态的Fragment上,比如一系列的标签。每一页被用户浏览过的的Fragment都会被保存在内存中,尽管此时视图层次(view hieratchy)因为不可见而已经被销毁了。这便导致会有一些内存被占用,因为这些内存中要被用来保存保存fragment的实例状态之类的呀。所以说,你想要使用ViewPager来展示比较多的页面时,请你考虑使用FragmentStatePagerAdapter。
当使用FragmentPagerAdapter时,要注意:和FragmentPagerAdapter搭配使用的ViewPager时,Adapter中必须使用有效的ID集合(我的理解是往Adapter里面传的List<Fragment>中添加的不能是同一个Fragment的引用,尽管每个页面有可能相同,但也请多new几个Fragment然后添加进List中去)
子类实现时,只需要实现getItem(int) 和 getCount() 就可以啦!
这里有一个例子来示范怎样使用FragmentPagerAdapter:
1 public class FragmentPagerSupport extends FragmentActivity { 2 static final int NUM_ITEMS = 10; 3 4 MyAdapter mAdapter; 5 6 ViewPager mPager; 7 8 @Override 9 protected void onCreate(Bundle savedInstanceState) { 10 super.onCreate(savedInstanceState); 11 setContentView(R.layout.fragment_pager); 12 13 mAdapter = new MyAdapter(getSupportFragmentManager()); 14 15 mPager = (ViewPager)findViewById(R.id.pager); 16 mPager.setAdapter(mAdapter); 17 18 // Watch for button clicks. 19 Button button = (Button)findViewById(R.id.goto_first); 20 button.setOnClickListener(new OnClickListener() { 21 public void onClick(View v) { 22 mPager.setCurrentItem(0); 23 } 24 }); 25 button = (Button)findViewById(R.id.goto_last); 26 button.setOnClickListener(new OnClickListener() { 27 public void onClick(View v) { 28 mPager.setCurrentItem(NUM_ITEMS-1); 29 } 30 }); 31 } 32 33 public static class MyAdapter extends FragmentPagerAdapter { 34 public MyAdapter(FragmentManager fm) { 35 super(fm); 36 } 37 38 @Override 39 public int getCount() { 40 return NUM_ITEMS; 41 } 42 43 @Override 44 public Fragment getItem(int position) { 45 return ArrayListFragment.newInstance(position); 46 } 47 } 48 49 public static class ArrayListFragment extends ListFragment { 50 int mNum; 51 52 /** 53 * Create a new instance of CountingFragment, providing "num" 54 * as an argument. 55 */ 56 static ArrayListFragment newInstance(int num) { 57 ArrayListFragment f = new ArrayListFragment(); 58 59 // Supply num input as an argument. 60 Bundle args = new Bundle(); 61 args.putInt("num", num); 62 f.setArguments(args); 63 64 return f; 65 } 66 67 /** 68 * When creating, retrieve this instance‘s number from its arguments. 69 */ 70 @Override 71 public void onCreate(Bundle savedInstanceState) { 72 super.onCreate(savedInstanceState); 73 mNum = getArguments() != null ? getArguments().getInt("num") : 1; 74 } 75 76 /** 77 * The Fragment‘s UI is just a simple text view showing its 78 * instance number. 79 */ 80 @Override 81 public View onCreateView(LayoutInflater inflater, ViewGroup container, 82 Bundle savedInstanceState) { 83 View v = inflater.inflate(R.layout.fragment_pager_list, container, false); 84 View tv = v.findViewById(R.id.text); 85 ((TextView)tv).setText("Fragment #" + mNum); 86 return v; 87 } 88 89 @Override 90 public void onActivityCreated(Bundle savedInstanceState) { 91 super.onActivityCreated(savedInstanceState); 92 setListAdapter(new ArrayAdapter<String>(getActivity(), 93 android.R.layout.simple_list_item_1, Cheeses.sCheeseStrings)); 94 } 95 96 @Override 97 public void onListItemClick(ListView l, View v, int position, long id) { 98 Log.i("FragmentList", "Item clicked: " + id); 99 } 100 } 101 }
R.layout.fragment_pager的代码:
1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 2 android:orientation="vertical" android:padding="4dip" 3 android:gravity="center_horizontal" 4 android:layout_width="match_parent" android:layout_height="match_parent"> 5 6 <android.support.v4.view.ViewPager 7 android:id="@+id/pager" 8 android:layout_width="match_parent" 9 android:layout_height="0px" 10 android:layout_weight="1"> 11 </android.support.v4.view.ViewPager> 12 13 <LinearLayout android:orientation="horizontal" 14 android:gravity="center" android:measureWithLargestChild="true" 15 android:layout_width="match_parent" android:layout_height="wrap_content" 16 android:layout_weight="0"> 17 <Button android:id="@+id/goto_first" 18 android:layout_width="wrap_content" android:layout_height="wrap_content" 19 android:text="@string/first"> 20 </Button> 21 <Button android:id="@+id/goto_last" 22 android:layout_width="wrap_content" android:layout_height="wrap_content" 23 android:text="@string/last"> 24 </Button> 25 </LinearLayout> 26 </LinearLayout>
R.layout.fragment_pager_list的源代码:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@android:drawable/gallery_thumb"> <TextView android:id="@+id/text" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center_vertical|center_horizontal" android:textAppearance="?android:attr/textAppearanceMedium" android:text="@string/hello_world"/> <!-- The frame layout is here since we will be showing either the empty view or the list view. --> <FrameLayout android:layout_width="match_parent" android:layout_height="0dip" android:layout_weight="1" > <!-- Here is the list. Since we are using a ListActivity, we have to call it "@android:id/list" so ListActivity will find it --> <ListView android:id="@android:id/list" android:layout_width="match_parent" android:layout_height="match_parent" android:drawSelectorOnTop="false"/> <!-- Here is the view to show if the list is emtpy --> <TextView android:id="@android:id/empty" android:layout_width="match_parent" android:layout_height="match_parent" android:textAppearance="?android:attr/textAppearanceMedium" android:text="No items."/> </FrameLayout> </LinearLayout>
公有构造方法(Public Constructors):
公有方法(Public Methods):
public void destroyItem(ViewGroup container,int position,Object object)
移除对应指定位置(position)的页面。适配器负责从container中移除这些视图,尽管它唯一保证在finishUpdate(ViewGroup)之前执行完!
public void finishUpdate(ViewGroup container)
当展示页面变化成功时调用该方法。此时应该确保所有的页面在适当的时候已经完成了添加、移除工作。
public abstract Fragment getItem(int position)
返回已经和特定位置有联系的Fragment
public long getItemId(int position)
返回指定位置的页面的标示,该标示是唯一的
默认的实现是返回指定位置的序号(即position),如果你的需求实现中,子页面的位置可以变化,你可以尝试通过重写该方法来实现
public Object instantiateItem(ViewGroup container,int position)
创建指定页。适配器负责添加视图到父布局中去。该方法只确保它会在finishUpdate(ViewGroup)调用之前完成
Returns:
Object:返回的这个对象代表了新的一个页面(Page)。它不一定是一个视图View,有可能是一些其他的父布局(Container)。
public boolean isViewFromObject(View view,Object object)
判断一个页面(Page)是否对应产生了一个唯一的键对象,而产生唯一键对象的过程是通过instantiateItem(ViewGroup,int)方法的调用和完成实现的。本方法保证了 PagerAdapter能够运行正常。
public void restoreState(Parcelable state,ClassLoader loader)
恢复和当前适配器相关的任何实例状态,前提是你要在之前就通过saveState()方法保存了实例状态
public Parcelable saveState()
保存任何和当前适配器有关的数据,以供在之后UI状态发生重建时的实例状态恢复
public void setPrimaryItem(ViewGroup container,int position,Object object)
调用该方法是为了告知适配器哪个子页面目前被视为主要的子页面。它对应的是给用户展示的当前页。
public void startUpdate(ViewGroup container)
当展示页有变化并且将要开始更新时会调用该方法。
PS:
关于上面的:Adapter中必须使用有效的ID集合。我的理解如下:
当我在给FragmentAdapter(我自己定义的实现了FragmentPagerAdapter的Adapter类)传入List<Fragment>参数时,
当我给List里面同时添加同一个FragmentContent(自己定义的一个继承Fragment的类)多次时,如下图“
跑起来会报错,如下图:
具体报错内容为:java.lang.IllegalStateException: Can‘t change tag of fragment FragmentContent{421fbc80 id=0x7f0c006a android:switcher:2131492970:0}: was android:switcher:2131492970:0 now android:switcher:2131492970:1
不难看出,就是因为在引用了同一个Fragment传入才导致Adapter内部出错。具体原因不知。这便验证了上面的观点。
标签:
原文地址:http://www.cnblogs.com/codekk/p/5466382.html