先看个简单的,先上个效果图,吸引大家一下眼球。
三个页面间的滑动,此时是带着上面的一块滑动的。
看一下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并设置。