ViewPager学习

        项目需求,想要实现一个轮播的广告页,于是使用VIewPager来实现,首先来看下PagerAdapter。

1.PagerAdapter

        PagerAdapter为一个抽象类,导包如下:

import android.support.v4.view.PagerAdapter;

        在使用PagerAdapter时,需要自定义类继承自PagerAdapter,同时,需要实现以下四个方法:

@Override
//此方法返回可获得的View数量
public int getCount() {
    return 0;
}

@Override
//用来判断instantiateItem方法返回的Object是否要和当前页面关联
public boolean isViewFromObject(View view, Object object) {
    return false;
}

@Override
//移除position处的view,将view从container中移除
public void destroyItem(ViewGroup container, int position, Object object) {
    super.destroyItem(container, position, object);
}

@Override
//创建position位置处的view,同时需要手动添加到container中
public Object instantiateItem(ViewGroup container, int position) {
    return super.instantiateItem(container, position);
}

        示例使用如下:

public class ViewPagerAdapter extends PagerAdapter {

    private List<ImageView> views;

    public ViewPagerAdapter(List<ImageView> views) {
        this.views = views;
    }

    @Override
    public int getCount() {
        return views == null ? 0 : views.size();
    }

    @Override
    public boolean isViewFromObject(View view, Object object) {
        return view == object;
    }

    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        if (views != null) {
            View view = views.get(position);
            container.removeView(view);
        }
    }

    @Override
    public Object instantiateItem(ViewGroup container, int position) {
        if (views != null) {
            View view = views.get(position);
            if (view != null) {
                container.addView(view);
                return view;
            }
        }   
        return null;
    }
}

2.实现轮播

        采用Handler+ViewPager来实现定时播放,同时使用LinearLayout来实现圆点指示器

a.布局如下:

<?xml version="1.0" encoding="utf-8"?>
<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" />

    <LinearLayout
        android:id="@+id/indicator"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_marginBottom="10dp"
        android:gravity="center_horizontal"
        android:orientation="horizontal"
        android:padding="5dp" />
</RelativeLayout>

b.圆点指示器

        如上面的布局文件所示,采用LinearLayout来定制圆点指示器,当只有一张图片时,不显示圆点指示器,圆点采用Shape绘制而成,主要有正常状态的圆点和被选中的圆点:

(1).正常圆点
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="oval"
    android:useLevel="false">
    <solid android:color="#fff" />
    <size
        android:width="10dp"
        android:height="10dp" />
</shape>
(2).选中状态的圆点
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="oval"
    android:useLevel="false">
    <!-- 圆的大小,要保证长和宽一样大 -->
    <size
        android:width="10dp"
        android:height="10dp" />
    <!-- 中间填充的颜色 -->
    <solid android:color="#000" />
    <!-- 边框大小及颜色 --> 
    <stroke
    android:width="1dp"
    android:color="#fff" />
</shape>

        使用时,根据List中ImageView的数量添加圆点,当List的大小为1时,隐藏圆点指示器,添加圆点指示器的代码如下:

private void initIndicator() {
    //mIndicator布局中的LinearLayout
    mIndicator.removeAllViews();
    if (mImages != null && mImages.size() > 1) {
        mIndicator.setVisibility(View.VISIBLE);
    } else {
        mIndicator.setVisibility(View.GONE);
    }
    for (int i = 0; i < mImages.size(); i++) {
        ImageView imageView = new ImageView(SplashActivity.this);
        if (i == 0) {
            imageView.setBackgroundResource(R.drawable.point_selected);
        } else {
            imageView.setBackgroundResource(R.drawable.point_normal);
        }
        mIndicator.addView(imageView);
    }
}

        同时,ViewPager中的页面改变时,需要改变圆点状态,方法如下:

private void changePoint(int position) {
    //mPrePosition标识页面变换之前的位置
    if (mPrePosition != position) {
        ImageView prePoint = (ImageView) mIndicator.getChildAt(mPrePosition);
        ImageView mCurPoint = (ImageView) mIndicator.getChildAt(position);
        if (prePoint != null && mCurPoint != null) {
            prePoint.setBackgroundResource(R.drawable.point_normal);
            mCurPoint.setBackgroundResource(R.drawable.point_selected);
            mPrePosition = position;
        }
    }
}

c.示例代码如下:

//示例数据,初始化要显示的图片*****************************************
mImages = new ArrayList<ImageView>();
ImageView imageView1 = new ImageView(SplashActivity.this);
imageView1.setBackgroundResource(R.drawable.default_imageload_pic);
mImages.add(imageView1);
ImageView imageView2 = new ImageView(SplashActivity.this);
imageView2.setBackgroundResource(R.drawable.default_imageload_pic);
mImages.add(imageView2);
ImageView imageView3 = new ImageView(SplashActivity.this);
imageView3.setBackgroundResource(R.drawable.default_imageload_pic);
mImages.add(imageView3);
//*********************************************************************

    mAdapter = new ViewPagerAdapter(mImages);
    mViewPager.setAdapter(mAdapter);

        设置监听页面变化,需要在页面被选中时,改变圆点指示器的状态:

mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
    @Override
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {

    }

    @Override
    public void onPageSelected(int position) {
        //改变圆点指示器的位置
        changePoint(position);
    }

    @Override
    public void onPageScrollStateChanged(int state) {

    }
});

        当用户手动滑动图片时,停止自动滑动,设置一个标志位即可。

mViewPager.setOnTouchListener(new View.OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        autoChange = false;
        return false;
    }
});

        使用Handler自动翻页,示例代码如下:

private Handler mHanlder = new Handler() {
    @Override
    public void handleMessage(Message msg) {
        switch (msg.what) {
            case MSG_CHANGE:
                if (autoChange) {
                    changeImage(mPrePosition + 1);
                    mHanlder.sendEmptyMessageDelayed(MSG_CHANGE, INTERVAL);
                }
                break;
        }
    }
};
mHanlder.sendEmptyMessageDelayed(MSG_CHANGE, INTERVAL);

//翻页
private void changeImage(int position) {
    if (mPrePosition != position) {
        if (mImages != null) {
            if (position >= mImages.size()) {
                position = 0;
            }
            mViewPager.setCurrentItem(position);
        }
    }
}

注意:

        为了避免Handler造成的内存泄漏,需要在onDestory方法里面remove掉所有消息,并且销毁Handler,方法如下:

@Override
protected void onDestroy() {
    super.onDestroy();
    mHanlder.removeCallbacksAndMessages(null);
    mHanlder = null;
}