您的位置:首页 > 编程语言 > PHP开发

在viewpager中使用FragmentPagerAdapter实现分页

2014-08-21 22:25 453 查看
首先需要在layout文件中配置ViewPager View

[html]view
plaincopy

<android.support.v4.view.ViewPager
android:id="@+id/pager"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="50dp" />

其实ViewPager本质上是一个View,继承体系如下,可以发现它的上面就是ViewGroup
,它是有能力add View的

java.lang.Object
android.view.View
android.view.ViewGroup
android.support.v4.view.ViewPager
上面提到过使用 PagerAdapter
来生成一个页面视图,也就是一页, PagerAdapter
决定了ViewPager一共有多少页,负责每页的初始化,每页的销毁等工作

[java]view
plaincopy

class MyPagerAdapter extends PagerAdapter{

@Override
public int getCount() {
return mViewList .size();
}

@Override
public Object instantiateItem(View container, int position) {
Log. i("INFO", "instantiate item:"+position);
((ViewPager) container).addView( mViewList.get(position),0);
return mViewList .get(position);
}

@Override
public void destroyItem(View container, int position, Object object) {
((ViewPager) container).removeView( mViewList.get(position));
}

@Override
public boolean isViewFromObject(View arg0, Object arg1) {
return arg0 == arg1;
}

可以看到ViewPager其实是一个组件容器,可以为它的每页添加一个要显示的View,用于展现数据

[java]view
plaincopy

mLayoutInflater = getLayoutInflater();

//可以按照需求进行动态创建Layout,这里暂用静态的xml layout
mViewList.add(mLayoutInflater.inflate(R.layout.per_pager1, null));
mViewList.add(mLayoutInflater.inflate(R.layout.per_pager2, null));
mViewList.add(mLayoutInflater.inflate(R.layout.per_pager3, null));

ViewPager viewPager = (ViewPager) findViewById(R.id.pager);
mPagerAdapter = new MyPagerAdapter();
viewPager.setAdapter(mPagerAdapter);

上面的每一个经过inflate的Layout就代表的是每一页的布局,就像我们平常使用的布局文件一样...

我们经常看到一般在ViewPager下会有一些圆点来指示当前我们浏览到第几页了,要实现这种效果,我们要根据页面的数量来动态生成圆点的数量,并添加到一个LinearLayout中,便于管理

[java]view
plaincopy

Bitmap bitmap = BitmapFactory. decodeResource(getResources(), R.drawable.icon_dot_normal );
for (int i = 0; i < mViewList.size(); i++) {
Button bt = new Button(this );
bt.setLayoutParams( new ViewGroup.LayoutParams(bitmap.getWidth(),bitmap.getHeight()));
bt.setBackgroundResource(R.drawable. icon_dot_normal );
mNumLayout .addView(bt);
}

那我们怎么才能知道当前滑动到第几页了呢 ? 其实我们可以为ViewPager设置一个OnPageChangeListener
页面改变监听器来监听页面的改变,从而得到当前滑动到了第几页

[java]view
plaincopy

viewPager. setOnPageChangeListener( new OnPageChangeListener() {

@Override
public void onPageSelected( int position) {

if (mPreSelectedBt != null){
mPreSelectedBt .setBackgroundResource(R.drawable. icon_dot_normal);
}

Button currentBt = (Button)mNumLayout .getChildAt(position);
currentBt.setBackgroundResource(R.drawable. home_page_dot_select );
mPreSelectedBt = currentBt;

//Log.i("INFO", "current item:"+position);
}

@Override
public void onPageScrolled( int arg0, float arg1, int arg2) {
// TODO Auto-generated method stub

}

@Override
public void onPageScrollStateChanged( int arg0) {
// TODO Auto-generated method stub

}
});

mPreSelectedBt 只是为了记录当前显示的圆点,为下一次圆点焦点切换做准备,下面看一个完整的实现

[java]view
plaincopy

public class MainActivity extends Activity {

ArrayList<View> mViewList = new ArrayList<View>();
LayoutInflater mLayoutInflater;
LinearLayout mNumLayout;

Button mPreSelectedBt;

MyPagerAdapter mPagerAdapter;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

mLayoutInflater = getLayoutInflater();

//可以按照需求进行动态创建Layout,这里暂用静态的xml layout
mViewList.add(mLayoutInflater.inflate(R.layout.per_pager1, null));
mViewList.add(mLayoutInflater.inflate(R.layout.per_pager2, null));
mViewList.add(mLayoutInflater.inflate(R.layout.per_pager3, null));

ViewPager viewPager = (ViewPager) findViewById(R.id.pager);
mPagerAdapter = new MyPagerAdapter();
viewPager.setAdapter(mPagerAdapter);

mNumLayout = (LinearLayout) findViewById(R.id.ll_pager_num);

Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.icon_dot_normal);
for (int i = 0; i < mViewList.size(); i++) {
Button bt = new Button(this);
bt.setLayoutParams(new ViewGroup.LayoutParams(bitmap.getWidth(),bitmap.getHeight()));
bt.setBackgroundResource(R.drawable.icon_dot_normal);
mNumLayout.addView(bt);
}

viewPager.setOnPageChangeListener(new OnPageChangeListener() {

@Override
public void onPageSelected(int position) {

if(mPreSelectedBt != null){
mPreSelectedBt.setBackgroundResource(R.drawable.icon_dot_normal);
}

Button currentBt = (Button)mNumLayout.getChildAt(position);
currentBt.setBackgroundResource(R.drawable.home_page_dot_select);
mPreSelectedBt = currentBt;

//Log.i("INFO", "current item:"+position);
}

@Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
// TODO Auto-generated method stub

}

@Override
public void onPageScrollStateChanged(int arg0) {
// TODO Auto-generated method stub

}
});

}

class MyPagerAdapter extends PagerAdapter{

@Override
public int getCount() {
return mViewList.size();
}

@Override
public Object instantiateItem(View container, int position) {
Log.i("INFO", "instantiate item:"+position);
((ViewPager) container).addView(mViewList.get(position),0);
return mViewList.get(position);
}

@Override
public void destroyItem(View container, int position, Object object) {
Log.i("INFO", "destroy item:"+position);
((ViewPager) container).removeView(mViewList.get(position));
}

@Override
public boolean isViewFromObject(View arg0, Object arg1) {
return arg0 == arg1;
}
}
}

如果你仔细观察打印日志会发现,PagerAdapter的实现方式有点特殊,永远都会存在两个经过初始化的'页'(page>2时),显示当前页时会初始化下一页,会destroy上上页,一轮滑动完成的打印信息如下

[html]view
plaincopy

04-02 22:39:59.880: I/INFO(27187): instantiate item:0
04-02 22:39:59.880: I/INFO(27187): instantiate item:1
04-02 22:40:03.890: I/INFO(27187): instantiate item:2
04-02 22:40:39.020: I/INFO(27187): destroy item:0

当要显示的页数发生改变时,我们可以通过调用PagerAdapter的notifyDataSetChanged()
来通知数据的改变(必须在UI主线程中通知更新),同时圆点也需要进行更新

[java]view
plaincopy

mViewList.add(mLayoutInflater.inflate(R.layout.per_pager1, null));
Button bt = new Button(this);
bt.setLayoutParams(new ViewGroup.LayoutParams(bitmap.getWidth(),bitmap.getHeight()));
bt.setBackgroundResource(R.drawable.icon_dot_normal);
mNumLayout.addView(bt);
mPagerAdapter.notifyDataSetChanged();

以上基本上就是ViewPager基本的使用方式,还是比较简单的,但ViewPager最常使用的方式是结合Fragment
来一起使用,这种方式可以很方便的来管理每个页面的生命周期,Android也为我们提供了好些种固定的实现好了的Adapters来给ViewPager使用,它们包括FragmentPagerAdapter,FragmentStatePagerAdapter,FragmentPagerAdapter,
FragmentStatePagerAdapter
,它们中的每一种都可以编写少量简单的代码就为我们建立一个完整的用户界面,下一节将进行介绍

使用Fragment
来表示一页,显得更加简单和直观,Fragment
本身提供的一些特性可以让我们方便的对每一页进行管理,使用FragmentManager可以根据ID或TAG来查找Fragment
, 动态添加、删除、替换,Fragment
可以管理自己的生命周期,像Activity一样提供了一些生命周期回调方法。

Fragment
成为ViewPager的一页时,FragmentManager会一直保存管理创建好了的Fragment,即使当前不是显示的这一页,Fragment对象也不会被销毁,在后台默默等待重新显示。但如果Fragment不再可见时,它的视图层次会被销毁掉,下次显示时视图会重新创建。

出于使用FragmentPagerAdapter
时,Fragment对象会一直存留在内存中,所以当有大量的显示页时,就不适合用FragmentPagerAdapter
了,FragmentPagerAdapter 适用于只有少数的page情况,像选项卡。这个时候你可以考虑使用FragmentStatePagerAdapter
,当使用FragmentStatePagerAdapter
时,如果Fragment不显示,那么Fragment对象会被销毁,但在回调onDestroy()方法之前会回调onSaveInstanceState(Bundle outState)方法来保存Fragment的状态,下次Fragment显示时通过onCreate(Bundle savedInstanceState)把存储的状态值取出来,FragmentStatePagerAdapter
比较适合页面比较多的情况,像一个页面的ListView

最后一点要注意,当使用FragmentPagerAdapter
时一定要为它的宿主ViewPager设置一个有效的ID !

下面是一个使用FragmentPagerAdapter
的示例,需要注意的是destroyItem()方法并不是去Destroy Fragment对象 而是Destroy的是Fragment的视图
, 这一点需要理解注意了

[java]view
plaincopy

class MyFragmentPagerAdapter extends FragmentPagerAdapter{

public MyFragmentPagerAdapter(FragmentManager fm) {
super(fm);
}

@Override
public Fragment getItem(int position) {
return MyPageFragment.create(position);
}

@Override
public int getCount() {
return mPagerNum; // 代表页数
}

@Override
public void destroyItem(ViewGroup container, int position, Object object) {
// 这里Destroy的是Fragment的视图层次,并不是Destroy Fragment对象
super.destroyItem(container, position, object);
Log.i("INFO", "Destroy Item...");
}
}

下面是一个Fragment的示例程序,记得前面说过,使用FragmentPagerAdapter
适配器时,创建好了的Fragment会一直在内存中,不会被销毁,但它的视图层次是会被销毁的,所以onCreate()方法只会被调用一次,而
onCreateView() 方法,每次Fragment从不可见到可见时会被调用,可以看到Fragment有一些生命周期回调方法 onPause()、onDestroy()等等

[java]view
plaincopy

public class MyPageFragment extends Fragment {

public static final String ARG_PAGE = "page_num";

// 当前页
private int currentPageNum;

public MyPageFragment() {
}

public static MyPageFragment create(int pagerNum) {

MyPageFragment myPageFrament = new MyPageFragment();
Bundle arg = new Bundle();
arg.putInt(ARG_PAGE, pagerNum);
myPageFrament.setArguments(arg);

return myPageFrament;

}

/* (non-Javadoc)
*
@See android.support.v4.app.Fragment#onCreate(android.os.Bundle)
*
* Fragment创建的时候调用
*
*/
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.i("INFO", "onCreate..");
currentPageNum = getArguments().getInt(ARG_PAGE);
}

/* (non-Javadoc)
* @see android.support.v4.app.Fragment#onCreateView(android.view.LayoutInflater, android.view.ViewGroup, android.os.Bundle)
*
* Fragment从不可见到可见时调用
*
*/
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {

Log.i("INFO", "onCreateView..");

ViewGroup rootView = (ViewGroup) inflater.inflate(R.layout.per_pager1,
container, false);

switch (currentPageNum) {
case 0:
rootView.setBackgroundResource(R.drawable.page1_bg);
break;
case 1:
rootView.setBackgroundResource(R.drawable.page2_bg);
break;
case 2:
rootView.setBackgroundResource(R.drawable.page3_bg);
break;
default:
break;
}

return rootView;

}

@Override
public void onPause() {
super.onPause();
}

@Override
public void onDestroy() {
super.onDestroy();
Log.i("INFO", "MyFragment Destroy...");
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: