现在大部分的软件在安装完之后,第一次打开都会出现引导页,这些引导页就是通过ViewPager来实现的,本篇内容就是关于ViewPager中引导页的实现过程
首先我们要在主布局中添加一个用于承载ViewPager的控件以及导航点控件
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v4.view.ViewPager
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent">
</android.support.v4.view.ViewPager>
<!-- 这是导航点控件的布局 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_marginBottom="10dp"
android:gravity="center">
<ImageView
android:id="@+id/dot1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:background="@drawable/dot_selected"/>
<ImageView
android:id="@+id/dot2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:background="@drawable/dot_normal"/>
<ImageView
android:id="@+id/dot3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:background="@drawable/dot_normal"/>
<ImageView
android:id="@+id/dot4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:background="@drawable/dot_normal"/>
</LinearLayout>
</RelativeLayout>
然后我们在WelcomeActivity中添加引导页
//实现OnPageChangeListener,用于监听图片的滑动,然后改变导航点的状态
public class WelcomeActivity extends Activity implements ViewPager.OnPageChangeListener{
private ViewPager pager;
private List<View> views; //存放引导页View的集合
private ImageView[] dots;
private int[] ids = new int[]{ R.id.dot1,R.id.dot2,R.id.dot3,R.id.dot4};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_welcome);
pager = (ViewPager) findViewById(R.id.viewpager); //获取ViewPager控件
initViews(); //初始化各个引导页
initDots(); //初始化导航点
//ViewPager需要使用适配器,将views通过适配器添加到布局中
ViewPagerAdapter adapter = new ViewPagerAdapter(views); //自定义的适配器
pager.setAdapter(adapter);
pager.setOnPageChangeListener(this); //添加回调接口,用于监听引导页滑动,从而改变导航点
}
//初始化引导页
private void initViews() {
views = new ArrayList<>(); //List是一个接口,不能实例化,需要实例化一个ArrayList或者LinkedList
LayoutInflater inflater = LayoutInflater.from(this);
views.add(inflater.inflate(R.layout.one, null)); //给views添加引导页,使用的是布局one.xml
views.add(inflater.inflate(R.layout.two, null));
views.add(inflater.inflate(R.layout.three, null));
views.add(inflater.inflate(R.layout.four, null));
}
//初始化导航点
private void initDots() {
dots = new ImageView[ids.length];
for (int i=0;i<ids.length;i++){
dots[i] = (ImageView) findViewById(ids[i]);
}
}
//实现OnPageChangeListener接口需要重写此方法,作用:页面被滑动的时候调用
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
//实现OnPageChangeListener接口需要重写此方法,作用:新的页面被选中的时候调用
@Override
public void onPageSelected(int position) {
for (int i = 0; i<dots.length;i++){
if (i == position){ //设置当前被选中的引导页对应的导航点为dot_selected.png
dots[i].setImageResource(R.drawable.dot_selected);
}else { //设置当前被选中的引导页对应的导航点为dot_normal.png
dots[i].setImageResource(R.drawable.dot_normal);
}
}
}
//实现OnPageChangeListener接口需要重写此方法,作用:滑动状态改变的时候被调用
@Override
public void onPageScrollStateChanged(int state) {
}
}
适配器ViewPagerAdapter
public class ViewPagerAdapter extends PagerAdapter { //继承PagerAdapter
private List<View> views;
public ViewPagerAdapter(List<View> views){
this.views = views;
}
@Override
public int getCount() { //获取引导页数量,这里我们返回集合views的大小
return views.size();
}
/**
*PagerAdapter最多只能缓存三张要显示的图片,如果滑动的图片超出了缓存的范围,就会调用这个方法,将图片
*销毁,(( 如果引导页有三张及以上,此方法必须重写!!否则程序会崩溃,所以建议无论引导页数量多少,都重写此
*方法,避免日后增加引导页引发错误))
*/
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView(views.get(position));
System.out.println("引导页"+position+"被销毁");
}
/**
*当要显示的图片可以进行缓存的时候,会调用这个方法进行显示图片的缓存初始化,我们将要显示的ImageView
*加入到ViewGroup中,然后作为返回值返回即可
*/
@Override
public Object instantiateItem(ViewGroup container, int position) {
container.addView(views.get(position));
System.out.println("引导页"+position+"被缓存");
return views.get(position);
}
/**
*判断instantiateItem(ViewGroup, int)函数所返回来的View与一个页面视图View是否是代表的同一个视图
*(即它俩是否表示同一个View)
*/
@Override
public boolean isViewFromObject(View view, Object object) {
return (view == object);
}
}
注:如果引导页只有两张或一张,在定义适配器的时候,可以不用重写destroyItem方法,但是三张以上时必须重写destroyItem方法,所以为了避免日后增加引导页出错,建议一定要重写此方法。
关于缓存的顺序问题:
假如现在有A、B、C、D四张图片,程序运行后首先会缓存A和B,ViewPagerAdapter中只缓存了两张图片,当我们从A滑动到B的时候,C便会在此时进行缓存处理,ViewPagerAdapter中则缓存了三张图片。当我们从B滑动到C的时候,此时ViewPagerAdapter已经缓存三张图片,无法再缓存D,所以此时就会先调用destroyItem将A销毁掉,然后再缓存D进来。我将这个缓存制作成了Gif图: