viewpager的循环滑动和图片轮播
今天下午结束了,重新加载网络页面的优化。并完成了viewpager的循环滑动和图片轮播。感触颇深啊,刚开始提手的时候发现我连viewpager怎么都忘记了。
图片的轮播和循环滑动两个功能结合在一起的话,我认为,还是用viewpager最为简单。有查资料,现在主流的方式主要是两种, 一种是在list<View>的头和尾个添加一个元素如:list<View>-->1,2,3那么添加完了以后的结果是:list<view>-->3,1,2,3,1。但是显示的是原来的三个元素。通过onPagerChangeListener中的onPageSelected方法设定:(以三个元素为例)在viewpager的位置小于1的时候,3,在大于3的时候则直接跳到1(这里的位置都是包括0的)。由此来实现循环滑动。
但是这种方法有一个缺陷,就是在一组数据滑完,进入另一组数据进行切换的时候,会有明显的不自然的感觉。
因此,基于良好的用户体验,我选择了第二种。而第二种方法是通过将循环的数目增到最大:
@Override
public int getCount() {
return Integer.MAX_VALUE;
}
通过 return views.get(position % views.size());来确定viewpager的位置,但是这样也是有缺陷的。首先它不是真正意义上的无限循环,只不过是有很大的边界而已。其次,当页面的总数是2和3的时候,就不能销毁复用的页面,否者会出现错误,程序报错说是,在添加新的页面之前没有将之前的页面销毁掉。研究一下发现viewpager一般会缓存两个数据,而2和3刚好在这两个缓存的数据之间。要修改这个bug的话就要重写viewpager类,显然,这样做很麻烦,也费时费力所以我设置了一个判断来解决这个问题。接下来上整个pagerAdapter的代码和setadapter的代码。
ViewpagerAdapter 代码:
public class ViewpagerAdapter extends PagerAdapter {
private Context mContext;
private List<View> views;
public ViewpagerAdapter(Context mContext, List<View> views) {
this.mContext = mContext;
this.views = views;
}
@Override
public int getCount() {
return Integer.MAX_VALUE;
}
@Override
public boolean isViewFromObject(View arg0, Object arg1) {
return arg0 == arg1;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
if(views.size()>3){
((ViewPager)container).removeView(views.get(position % views.size()));
}
}
/**
* 载入图片进去,用当前的position 除以 图片数组长度取余数是关键
*/
@Override
public Object instantiateItem(ViewGroup container, int position) {
try {
((ViewPager)container).addView(views.get(position % views.size()), 0);
}catch(Exception e){
//handler something
}
return views.get(position % views.size());
}
}
setadapter代码
int[] imageIds = {R.mipmap.btn1,R.mipmap.btn12,R.mipmap.btn3};
final List<View> views = new ArrayList<>();
for (int i = 0; i <imageIds.length ; i++) {
ImageView imageView = new ImageView(getActivity());
imageView.setBackgroundResource(imageIds[i]);
views.add(imageView);
}
viewpagerAdapter = new ViewpagerAdapter(getActivity(),views);
viewPager.setAdapter(viewpagerAdapter);
viewPager.setCurrentItem((views.size()) * 1000);
接下来是响应每个图片的点击事件是通过获取每个图片所在的imageView的实例,然后用for来判断点击的:
/**
* 设置viewpager的点击事件
*/
for (int i = 0; i <views.size() ; i++) {
views.get(i).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(getActivity(),"选的的数字"+viewPager.getCurrentItem(),Toast.LENGTH_SHORT).show();
}
});
}
最后就是图片的轮播了,如果单单只有轮播就很简单了,循环一个延时的线程就可以了,但是我们滑动viewpager的时候,肯定是不想让它自动跳转了,所以我们判断当前的viewpager页面的状态:onPagerChageListener的onPageScrollStateChanged(int state)的参数:0---》表示没有动作,1---》表示正在滑动,2---》表示滑动结束,通过监听状态,设置标签,当标签为true时,就开始循环,当为false的时候,线程就不执行循环操作,
下面是代码:
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
}
@Override
public void onPageScrollStateChanged(int state) {
if(state==0){
pagerFlag = true;
}else {
pagerFlag = false;
}
}
});
循环线程代码:
final Handler handler = new Handler();
handler.post(new Runnable() {
@Override
public void run() {
if(pagerFlag){
viewPager.setCurrentItem(viewPager.getCurrentItem()+1);
}
Log.d(TAG, "run: "+"图片标记"+pagerFlag);
handler.postDelayed(this,5000);
}
});
好了,今天就这些了,明天是动态添加上传大量图片。敬请期待
---2016-07-14