最近项目中用到banner效果,我按照以前的思路去写遇到了几个问题。parent已经存在等。参照第三方### youth5201314/banner实现了一个轻量级banner效果。
问题原因分析
- The specified child already has a parent. You must call removeView
图片数量小于3时,由于VP的预加载机制默认会加载相邻的view,右滑时会先执行instantiateItem()方法再执行destroyItem()。由于当前View已经存在所以会报he specified child already has a parent. You must call removeView的错误(可以采用API14的VP来屏蔽预加载(不推荐)) - 采用Integer.MAX_VALUE
当getCount返回的页数非常大的时候,比如10亿,调用setCurrentItem会引起ANR。(实际开发中最多10张图片,返回值Integer.MAX_VALUE显得有点浪费)
public int getCount() {
return Integer.MAX_VALUE;
}
效果
思路
- 实现无限循环的轮播图的原理是:在需要显示的图片的集合的首尾各添加一张图片。因此最后的ViewPager集合展示的图片的数量会比实际的图片多两张,这两张是为了方便切换来实现无限循环的效果的。
- 在onPageScrollStateChanged(int state)方法中通过vp的setCurrentItem()实现无限轮播的效果。
代码
构造轮播图
//构造数据头放最末尾数据,尾端放起始数据
for (int i = 0; i <= imageIds.length + 1; i++) {
ImageView imageView = new ImageView(this);
if (i == 0)
imageView.setBackgroundResource(imageIds[imageIds.length - 1]);
else if (i == imageIds.length + 1)
imageView.setBackgroundResource(imageIds[0]);
else
imageView.setBackgroundResource(imageIds[i - 1]);
mImageViews.add(imageView);
}
实现轮播效果
@Override
public void onPageScrollStateChanged(int state) {
currentItem = mViewPager.getCurrentItem();
switch (state) {
case 0://No operation
if (currentItem == 0) {
mViewPager.setCurrentItem(imageIds.length, false);
} else if (currentItem == imageIds.length + 1) {
mViewPager.setCurrentItem(1, false);
}
break;
case 1://start Sliding
if (currentItem == imageIds.length + 1) {
mViewPager.setCurrentItem(1, false);
} else if (currentItem == 0) {
mViewPager.setCurrentItem(imageIds.length, false);
}
break;
case 2://end Sliding
break;
}
}
private Runnable task = new Runnable() {
@Override
public void run() {
if (imageIds.length > 1) {
Log.e("run", "currentItem : " + currentItem);
currentItem = currentItem % (imageIds.length + 1) + 1;
if (currentItem == 1) {
mViewPager.setCurrentItem(currentItem, false);
handler.post(task);
} else {
mViewPager.setCurrentItem(currentItem);
handler.postDelayed(task, delayTime);
}
}
}
};