最近笔者想通过ViewPager来实现一个广告Banner,并实现无限轮播的效果,但是在这个过程中踩了不少的坑,听我慢慢道来。如果大家有遇到和我一样的情况,可以参考我的解决方法,没有那就更好,如果针对我的解决方法,有啥更好的方案,欢迎和我分享

使用ViewPager实现无限轮播代码

MainActivity代码

public class MainActivity extends AppCompatActivity {

private ViewPager mViewPager;
private TextView mTvDesTitle;
private LinearLayout mPointContainer;
private List<ImageView> mImageViewList;
private String[] mDesTitles;
private int[] mImageIds;
private int previousSelectPos = 0;//用于记录上一次选中的小圆点位置
private boolean isRunning = false;//定义一个标记,用于判断是否轮播 @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initViews();
initData();
initAdapter();
//实现ViewPager的无限轮播
new Thread() {
@Override
public void run() {
isRunning = true;
while (isRunning) {
try {
Thread.sleep(2 * 1000);//每隔2s切换一次
} catch (InterruptedException e) {
e.printStackTrace();
}
//更新ViewPager的显示,更新UI要在主线程实现
runOnUiThread(new Runnable() {
@Override
public void run() {
mViewPager.setCurrentItem(mViewPager.getCurrentItem() + 1);
}
}); }
}
}.start();
} private void initViews() {
mViewPager = (ViewPager) findViewById(R.id.view_pager);
mTvDesTitle = (TextView) findViewById(R.id.tv_des_title);
mPointContainer = (LinearLayout) findViewById(R.id.ll_point_container); } private void initData() {
//初始化轮播图片
mImageIds = new int[]{R.drawable.bannerone, R.drawable.bannertwo, R.drawable.bannerthree};
//初始化描述标题
mDesTitles = new String[]{"描述标题1", "描述标题2", "描述标题3"};
//初始化ImageView集合
mImageViewList = new ArrayList<>();
//for循环,添加ImageView和小圆点
ImageView imageView;
View pointView;
LinearLayout.LayoutParams layoutParams;
for (int i = 0; i < mImageIds.length; i++) {
//添加ImageView
imageView = new ImageView(this);
imageView.setBackgroundResource(mImageIds[i]);
mImageViewList.add(imageView);
//添加小圆点
pointView = new View(this);
pointView.setBackgroundResource(R.drawable.point_selector);
//设置小圆点的布局参数,宽和高
layoutParams = new LinearLayout.LayoutParams(dp2px(5), dp2px(5));
//设置enable状态,默认都是false 灰色。
pointView.setEnabled(false);
if (i != 0) {
layoutParams.leftMargin = dp2px(10);
}
//将小圆点添加到LinearLayout中
mPointContainer.addView(pointView, layoutParams);
} } private void initAdapter() {
mViewPager.setAdapter(new BannerAdapter());
//设置默认显示第一个标题
mTvDesTitle.setText(mDesTitles[0]);
//设置第一个小圆点为白色
mPointContainer.getChildAt(0).setEnabled(true);
//设置在中间某个位置
int pos = Integer.MAX_VALUE / 2 - (Integer.MAX_VALUE / 2 % mImageViewList.size());
mViewPager.setCurrentItem(pos);//可以实现左右无限轮播
//ViewPager设置滑动监听
mViewPager.addOnPageChangeListener(new OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { } @Override
public void onPageSelected(int position) {
/* //滑到某个位置
mTvDesTitle.setText(mDesTitles[position]);
//将上一次选中的置为false
mPointContainer.getChildAt(previousSelectPos).setEnabled(false);
//新选中的置为true
mPointContainer.getChildAt(position).setEnabled(true);
//更新选中的记录
previousSelectPos = position;*/
//实现无限轮播,positon会变,要更新位置
//滑到某个位置
int newPosition = position % mImageViewList.size();
mTvDesTitle.setText(mDesTitles[newPosition]);
//将上一次选中的置为false
mPointContainer.getChildAt(previousSelectPos).setEnabled(false);
//新选中的置为true
mPointContainer.getChildAt(newPosition).setEnabled(true);
//更新选中的记录
previousSelectPos = newPosition; } @Override
public void onPageScrollStateChanged(int state) { }
}); } class BannerAdapter extends PagerAdapter { @Override
public int getCount() {
//return mImageViewList.size();
//实现无限轮播
return Integer.MAX_VALUE;
} @Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
} @Override
public Object instantiateItem(ViewGroup container, int position) {
//ImageView imageView = mImageViewList.get(position);
//container.addView(imageView);
//return imageView;
//实现无限轮播
final int newPosition = position % mImageViewList.size();
ImageView imageView = mImageViewList.get(newPosition);
/**
* 我在轮播的时候同时手动滑动, java.lang.IllegalStateException:
* The specified child already has a parent. You must call removeView() on the child's parent first.
*/
imageView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(MainActivity.this, "你点击了"+newPosition, Toast.LENGTH_SHORT).show();
}
});
container.addView(imageView);
return imageView;
} @Override
public void destroyItem(ViewGroup container, int position, Object object) {
//这一句在只有三张图片的时候出现了滑动出现空白情况
container.removeView((View) object);
}
} /**
* px转dp
*/
public int px2dp(float pxValue) {
float scale = this.getResources().getDisplayMetrics().density;
return (int) (pxValue / scale + 0.5f);
} /**
* dp转px
*/
public int dp2px(float dpValue) {
final float scale = this.getResources().getDisplayMetrics().density;
return (int) (dpValue * scale + 0.5f);
} @Override
protected void onDestroy() {
super.onDestroy();
isRunning = false;
}
}

  

布局文件

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.zhiji.bannerdemo.MainActivity">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="180dp">
<android.support.v4.view.ViewPager
android:id="@+id/view_pager"
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:orientation="vertical"
android:layout_alignParentBottom="true"
android:paddingTop="5dp"
android:paddingBottom="6dp"
android:gravity="center_horizontal"
android:background="#66000000">
<TextView
android:id="@+id/tv_des_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:textColor="#fff"
android:textSize="16sp"
android:text="Hello World!" />
<LinearLayout
android:id="@+id/ll_point_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:orientation="horizontal"> </LinearLayout>
</LinearLayout>
</RelativeLayout> </RelativeLayout>

  小圆点

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<corners android:radius="5dp" />
<solid android:color="@android:color/darker_gray" /> </shape> <?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
<corners android:radius="5dp"/>
<solid android:color="@android:color/white"/> </shape> <?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:drawable="@drawable/point_white" android:state_enabled="true" />
<item android:drawable="@drawable/point_gray" android:state_enabled="false" />
</selector>

  

踩坑分析

1.笔者轮播图片使用了三张,也就是三张图片的轮回切换,上面代码基本实现了无限轮播的效果
但是运行过程中,在它自身无限自动轮播的同时,我同时手动进行了向左或者向右滑动,这时候程序崩溃了,报错如下:

java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
询问度娘后,也参考了网上的一些方案,最终解决方案如下:

@Override
public Object instantiateItem(ViewGroup container, int position) {
//ImageView imageView = mImageViewList.get(position);
//container.addView(imageView);
//return imageView;
//实现无限轮播
final int newPosition = position % mImageViewList.size();
ImageView imageView = mImageViewList.get(newPosition); imageView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(MainActivity.this, "你点击了"+newPosition, Toast.LENGTH_SHORT).show();
}
}); //新增的代码,用于解决上面提出的错误
ViewGroup parent= (ViewGroup) imageView.getParent();
if(parent!=null){
parent.removeView(imageView);
} container.addView(imageView);
return imageView;
}

  

加上上面的代码后,笔者在滑动的时候确实不会发生崩溃了,但是左右滑动得时候,会出现一块空白区域,很是苦恼,最终询问度娘看了网友的一些解决方案,方案如下

@Override
public void destroyItem(ViewGroup container, int position, Object object) {
//这一句在只有三张图片的时候出现了滑动出现空白情况
//新增,将下面这行代码去除就可以解决上面的问题
//container.removeView((View) object);
}

  

好了。使用上面的方案后,确实不会发生白块的现象了。但是很纳闷,这个问题是为什么呢???接着笔者又把三张轮播图换成了4张、5张。神奇的现象发生了,竟然没有出现上面的两种错误问题。

总结

ViewPager实现无限轮播,图片在三张及以下,使用的时候要注意,出现笔者的问题可参考我的解决方案,如果大家有更好的方案,或者针对我的问题,能指出我的问题所在,很是感谢。滑动图片如果在3上以上就可以直接使用我上面的代码。

ViewPager实现无限轮播踩坑记的更多相关文章

  1. 踩石行动:ViewPager无限轮播的坑

    2016-6-19 前言 View轮播效果在app中很常见,一想到左右滑动的效果就很容易想到使用ViewPager来实现.对于像我们常说的banner这样的效果,具备无限滑动的功能是可以用ViewPa ...

  2. ViewPager无限轮播与自定义切换动画

    一直在寻求一个能用得长久的ViewPager,寻寻觅觅终于发现,ViewPager有这一个就够了. 注:并非完全原创 先看一下效果: 淡入淡出: 旋转: 无限轮播的ViewPager 主要设计思路(以 ...

  3. 利用RecyclerView实现无限轮播广告条

    代码地址如下:http://www.demodashi.com/demo/14771.html 前言: 公司产品需要新增悬浮广告条的功能,要求是可以循环滚动,并且点击相应的浮条会跳转到相应的界面,在实 ...

  4. 【踩坑记】从HybridApp到ReactNative

    前言 随着移动互联网的兴起,Webapp开始大行其道.大概在15年下半年的时候我接触到了HybridApp.因为当时还没毕业嘛,所以并不清楚自己未来的方向,所以就投入了HybridApp的怀抱. Hy ...

  5. ViewPage实现无限轮播画廊效果

    1. 效果图 2. 布局文件 主要使用的 android:clipChildren的意思:是否限制子View在其范围内.再父布局和viewpager中设置该属性  ,要显示三个界面 ,还要设置marg ...

  6. iOS 两种不同的图片无限轮播

    代码地址如下:http://www.demodashi.com/demo/11608.html 前记 其实想写这个关于无限轮播的记录已经很久很久了,只是没什么时间,这只是一个借口,正如:时间就像海绵, ...

  7. Android实现广告页图片无限轮播

    一.概述 对于一个联网的Android应用, 首页广告无限轮播基本已经成为标配了. 那么它是怎么实现的呢? 有几种实现方式呢? 二.无限轮播的实现 1.最常规的手段是用 ViewPager来实现 2. ...

  8. Spark踩坑记——Spark Streaming+Kafka

    [TOC] 前言 在WeTest舆情项目中,需要对每天千万级的游戏评论信息进行词频统计,在生产者一端,我们将数据按照每天的拉取时间存入了Kafka当中,而在消费者一端,我们利用了spark strea ...

  9. Spark踩坑记——数据库(Hbase+Mysql)

    [TOC] 前言 在使用Spark Streaming的过程中对于计算产生结果的进行持久化时,我们往往需要操作数据库,去统计或者改变一些值.最近一个实时消费者处理任务,在使用spark streami ...

随机推荐

  1. cmd 菜单学习

    @ECHO OFF&PUSHD %~DP0 &TITLE 标题是随意的 mode con cols=36 lines=20 color 2C :menu cls echo. echo ...

  2. Spring Boot快速建立HelloWorld项目

    Spring Boot使我们更容易去创建基于Spring的独立和产品级的可以”即时运行“的应用和服务.支持约定大于配置,目的是尽可能快地构建和运行Spring应用. 构建环境 JDK 6+ Maven ...

  3. windows10 建立ODBC数据源

    为了使用dbExportDoc导出数据库表结构工具,需要建立windows 的ODBC源. 1.安装(如果已经安装oracle客户端则不必执行) instantclient-basic-windows ...

  4. ios随机数不重复

     NSMutableArray* Valuearr=[NSMutableArray new];     int counN=9;    for(int i=0;i<counN;i++)  //创 ...

  5. 【SoDiaoEditor电子病历编辑器】阶段性更新--新增复选框、日期控件、表格排版支持等

    转眼距离上一次v2正式发布已经过去一个半月了.github期间不定期push了二十几次,同时感谢分布在广州.福建.上海.北京的一众小伙伴,正是你们给出的建议,才让SoDiaoEditor不断完善. 我 ...

  6. java虚拟机--jvm client模式与server模式的区别

    JVM Server模式与client模式启动,最主要的差别在于:-Server模式启动时,速度较慢,但是一旦运行起来后,性能将会有很大的提升.JVM如果不显式指定是-Server模式还是-clien ...

  7. 用 Vue 全家桶二次开发 V2EX 社区

    一.开发背景 为了全面的熟悉Vue+Vue-router+Vuex+axios技术栈,结合V2EX的开放API开发了这个简洁版的V2EX. 在线预览 (为了实现跨域,直接npm run dev部署的, ...

  8. Day4-内置函数--未完待续,慢慢写

    内置函数:https://docs.python.org/3/library/functions.html?highlight=built#ascii 未完待续....

  9. 把ipad作为电脑的第二显示器

    需要:1,iPad          2,ios端需要软件idisplay(在pp助手里搜索idisplay下载即可)       3,windows需要软件iDisplay(链接http://www ...

  10. 并串转换FPGA电路结构的探讨

    如题,并串转换时FPGA设计里,一个很常用的模块,这里有一个小的探讨. 一般情况下我们可以使用一个计数器与数据选择器进行并串转换,如下图的的结构.这个结构通过计数器不断的改变数据选择器的地址端,从而使 ...