Android中ViewPager的简略使用(底部圆点)
http://blog.****.net/tibib/article/details/8724281高效显示Bitmap系列的学习、翻译文章还没有写完,估计这个礼拜末能结束吧~
android.support.v4.ViewPager类在 API 4+ Support 支持包中开始为我们提供,它可以让我们有能力左右滑动以'页'的形式展示数据。我们可以通过继承
PagerAdapter
来生成页面形式的视图。介绍具体的使用方式之前先来看下效果
首先需要在layout文件中配置ViewPager View
<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一共有多少页,负责每页的初始化,每页的销毁等工作
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,用于展现数据
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中,便于管理
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 页面改变监听器来监听页面的改变,从而得到当前滑动到了第几页
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 只是为了记录当前显示的圆点,为下一次圆点焦点切换做准备,下面看一个完整的实现
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上上页,一轮滑动完成的打印信息如下
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主线程中通知更新),同时圆点也需要进行更新
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
,它们中的每一种都可以编写少量简单的代码就为我们建立一个完整的用户界面,下一节将进行介绍