举例讲解Android中ViewPager中的PagerTitleStrip子控件
先看个简单的,先上个效果图,吸引大家一下眼球。
三个页面间的滑动,此时是带着上面的标题一块滑动的。
看一下android 对于PagerTitleStrip的官方解释:
PagerTitleStrip是ViewPager的一个关于当前页面、上一个页面和下一个页面的一个非交互的指示器。它经常作为ViewPager控件的一个子控件被被添加在XML布局文件中。在你的布局文件中,将它作为子控件添加在ViewPager中。而且要将它的 android:layout_gravity 属性设置为TOP或BOTTOM来将它显示在ViewPager的顶部或底部。每个页面的标题是通过适配器的getPageTitle(int)函数提供给ViewPager的。
着重讲两点:
1、首先,文中提到:在你的布局文件中,将它作为子控件添加在ViewPager中。
2、第二,标题的获取,是重写适配器的getPageTitle(int)函数来获取的。
根据这两点,我们就可以看代码了:
1、XML布局文件:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.example.testviewpage_2.MainActivity" > <android.support.v4.view.ViewPager android:id="@+id/viewpager" android:layout_width="wrap_content" android:layout_height="200dip" android:layout_gravity="center"> <android.support.v4.view.PagerTitleStrip android:id="@+id/pagertitle" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="top" /> </android.support.v4.view.ViewPager> </RelativeLayout>
清楚的看到我们将.PagerTitleStrip将其作为ViewPager的子控件直接嵌入其中;这是第一步;当然android:layout_gravity=""的值要设置为top或bottom。将标题栏显示在顶部或底部。
2、重写适配器的getPageTitle()函数
便于大家有个整体认识,先贴全局代码,然后再逐个讲:
package com.example.testviewpage_2; import java.util.ArrayList; import java.util.List; import android.app.Activity; import android.os.Bundle; import android.support.v4.view.PagerAdapter; import android.support.v4.view.PagerTitleStrip; import android.support.v4.view.ViewPager; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; public class MainActivity extends Activity { private View view1, view2, view3; private List<View> viewList;// view数组 private ViewPager viewPager; // 对应的viewPager private List<String> titleList; //标题列表数组 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); viewPager = (ViewPager) findViewById(R.id.viewpager); LayoutInflater inflater = getLayoutInflater(); view1 = inflater.inflate(R.layout.layout1, null); view2 = inflater.inflate(R.layout.layout2, null); view3 = inflater.inflate(R.layout.layout3, null); viewList = new ArrayList<View>();// 将要分页显示的View装入数组中 viewList.add(view1); viewList.add(view2); viewList.add(view3); titleList = new ArrayList<String>();// 每个页面的Title数据 titleList.add("王鹏"); titleList.add("姜语"); titleList.add("结婚"); PagerAdapter pagerAdapter = new PagerAdapter() { @Override public boolean isViewFromObject(View arg0, Object arg1) { // TODO Auto-generated method stub //根据传来的key,找到view,判断与传来的参数View arg0是不是同一个视图 return arg0 == viewList.get((int)Integer.parseInt(arg1.toString())); } @Override public int getCount() { // TODO Auto-generated method stub return viewList.size(); } @Override public void destroyItem(ViewGroup container, int position, Object object) { // TODO Auto-generated method stub container.removeView(viewList.get(position)); } @Override public Object instantiateItem(ViewGroup container, int position) { // TODO Auto-generated method stub container.addView(viewList.get(position)); //把当前新增视图的位置(position)作为Key传过去 return position; } @Override public CharSequence getPageTitle(int position) { // TODO Auto-generated method stub return titleList.get(position); } }; viewPager.setAdapter(pagerAdapter); } }
3、变量
private List<String> titleList; //标题列表数组
申请了一个String数组,用来存储三个页面所对应的标题的
4、初始化
titleList = new ArrayList<String>();// 每个页面的Title数据 titleList.add("王鹏"); titleList.add("姜语"); titleList.add("结婚");
在初始化阶段增加了这么一段初始化数组的代码。
5、重写CharSequence getPageTitle(int )函数
@Override public CharSequence getPageTitle(int position) { // TODO Auto-generated method stub return titleList.get(position); }
根据位置返回当前所对应的标题。
大家可以看到,其实这里仅仅只重写了getPageTitle()函数,将其根据不同的位置返回不同的字符串就可以实现上面的标题栏功能。第一和第二步有关数组和初始化,其实都是这了这一步,其实我们完全可以用下面这个代码来取代它们:
@Override public CharSequence getPageTitle(int position) { // TODO Auto-generated method stub switch (position) { case 0: return "王鹏"; case 1: return "姜语"; case 2: return "结婚"; default: return ""; } }
这样效果是一样一样的,只是代码不好维护而已。
设置标题
将Page的Title分离出来的一个自定义View,这样可以灵活的设置title的样式、文本。
效果:
xml使用:
<android.support.v4.view.ViewPager xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/pager" android:layout_width="match_parent" android:layout_height="match_parent"> <android.support.v4.view.PagerTitleStrip android:id="@+id/pager_title_strip" android:layout_width="match_parent" android:layout_height="30dp" android:layout_gravity="bottom" android:paddingTop="4dp" android:paddingBottom="4dp" /> </android.support.v4.view.ViewPager>
android:layout_gravity 控制标题的位置 一般取值为 bottom或top
看到开源项目ImageLoader中使用了这个,找了半天没看到哪里findbyid的,
原来在它的源码里就把它想成是ViewPager的子控件了。
部份源码:
@Override protected void onAttachedToWindow() { super.onAttachedToWindow(); final ViewParent parent = getParent(); if (!(parent instanceof ViewPager)) { throw new IllegalStateException( "PagerTitleStrip must be a direct child of a ViewPager."); } final ViewPager pager = (ViewPager) parent; final PagerAdapter adapter = pager.getAdapter(); pager.setInternalPageChangeListener(mPageListener); pager.setOnAdapterChangeListener(mPageListener); mPager = pager; updateAdapter(mWatchingAdapter != null ? mWatchingAdapter.get() : null, adapter); }
分析:在onAttachedToWindow()时,直接找出parent-view,如果是ViewPager才能使用,否则直接抛出异常。
设置title值:
PagerAdapter 里有一个getPageTitle(),需要重写它,然后可以根据不同的page返回不同的title。
@Override public CharSequence getPageTitle(int position) { switch (position) { case 0: return getString(R.string.title_list); case 1: return getString(R.string.title_grid); default: return null; } }
而在PageTitleStrip的updateText()源码里,调用了viewPager的adapter.getPageTitle,拿到title并设置。