Android轮播循环Banner修正进度条同步图片切换
2016-08-13 14:16
411 查看
上次更新的一个Banner的轮播循环,经过测试,发现存在一定的问题,就是当用户手动切换banner图片的时候,banner的计时没有重新开始。
具体说一下问题所在,设置3s更换一张banner,如果我在2s的时候手动滑动banner,到下一张banner的图片,那么只需要1s就对当前的图片进行切换了,对于追求完美的程序员来说,是不可以忍受的,所以我查阅了多方资料,进行了修正更改。
具体分析原因的话就是因为Thread线程,当你手动的时候,这个线程并没有暂停结束,还在继续运行着,所以当用户手动滑动的话,线程还在继续,3s的时间跑完继续currentItem+1,导致问题的所在,我们现在要解决的问题就是当用户滑动的时候,要将线程暂停,然后重新计时3s,重新开始运行这个线程。
原因分析完了,最新的这部分代码,加了一个进度条来进行监控,可以让我们的进度条跟随着图片一起进行切换,图片切换,进度条走满,手动切换图片,进度条重新开始走,并且图片计时重新开始3s的计时。
废话了这么多了,上ImageHandler的代码吧:
个人重点记录一下线程中的东西,其他地方的代码很好理解。以后可以参考使用。
线程中的Onn.isOff,是我们自己定义的一个全局变量。
这个全局变量是判断我们的线程状态。默认状态是false。for循环中,走的就是我们的进度条的一个动态效果。但是手动切换图片的话,我们的进度条要归零,并且从0开始重新走。这是我们的需求。实现的逻辑就是,当我们手动切换图片的时候,isOff设为true,然后将进度条归零,再将isOff设为false,continue,就继续开始走我们的进度条了。如果正常状态,没有切换,那我们就不走if,直接走我们的进度条啦。
具体的activity中的操作代码如下:
这里为什么又单独写了一个Thread线程来走我们的进度条呢,如果按照上述的操作完,你会发现,进来以后的第一张图片是没有进度条的,所以刚进到这个页面我们就需要单独跑一起这个进度条。
还有我们的ImageViewAdapter:
这样就实现了我们的循环轮播加进度条监控的效果了。大家可以根据自己的需求进行修改,如果不需要进度条的可以自己将Thread的代码删除就可以单独的实现轮播循环的banner。我主要还是为了记录一下自己,所以加上了这个进度条的效果状态。
如果转载,请标明出处。谢谢。
具体说一下问题所在,设置3s更换一张banner,如果我在2s的时候手动滑动banner,到下一张banner的图片,那么只需要1s就对当前的图片进行切换了,对于追求完美的程序员来说,是不可以忍受的,所以我查阅了多方资料,进行了修正更改。
具体分析原因的话就是因为Thread线程,当你手动的时候,这个线程并没有暂停结束,还在继续运行着,所以当用户手动滑动的话,线程还在继续,3s的时间跑完继续currentItem+1,导致问题的所在,我们现在要解决的问题就是当用户滑动的时候,要将线程暂停,然后重新计时3s,重新开始运行这个线程。
原因分析完了,最新的这部分代码,加了一个进度条来进行监控,可以让我们的进度条跟随着图片一起进行切换,图片切换,进度条走满,手动切换图片,进度条重新开始走,并且图片计时重新开始3s的计时。
废话了这么多了,上ImageHandler的代码吧:
import android.os.Handler; import android.os.Message; import java.lang.ref.WeakReference; /** * Created by Administrator on 2016/8/12 0012. */ public class ImageHandler extends Handler { /** * 请求更新显示的View */ protected static final int MSG_UPDATE_IMAGE = 1; /** * 请求暂停轮播 */ protected static final int MSG_KEEP_SILENT = 2; /** * 请求恢复轮播 */ protected static final int MSG_BREAK_SILENT = 3; /** * 记录最新的页号,当用户手动滑动时需要记录新页号,否则会使轮播的页面出错。 * 例如当前如果在第一页,本来准备播放的是第二页,而这时候用户滑动到了末页, * 则应该播放的是第一页,如果继续按照原来的第二页播放,则逻辑上有问题。 */ protected static final int MSG_PAGE_CHANGED = 4; //轮播间隔时间 protected static final long MSG_DELAY = 6000; //使用弱引用避免Handler泄露.这里的泛型参数可以不是Activity,也可以是Fragment等 private WeakReference<IndexActivity> weakReference; private int currentItem = 0; protected ImageHandler(WeakReference<IndexActivity> wk) { weakReference = wk; } @Override public void handleMessage(Message msg) { super.handleMessage(msg); final IndexActivity activity = weakReference.get(); if (activity == null) { //Activity已经回收,无需再处理UI了 return; } //检查消息队列并移除未发送的消息,这主要是避免在复杂环境下消息出现重复等问题。 if (activity.handler.hasMessages(MSG_UPDATE_IMAGE)) { activity.handler.removeMessages(MSG_UPDATE_IMAGE); } switch (msg.what) { case MSG_UPDATE_IMAGE: currentItem++; activity.viewPager.setCurrentItem(currentItem); new Thread(new Runnable() { @Override public void run() { for (int i = 0; i <= 100; i++) { if (Onn.isOff) { activity.progressBar.setProgress(0); i=0; Onn.isOff = false; continue; } activity.progressBar.setProgress(i); try { Thread.sleep(60); } catch (InterruptedException e) { e.printStackTrace(); } } } }).start(); //准备下次播放 activity.handler.sendEmptyMessageDelayed(MSG_UPDATE_IMAGE, MSG_DELAY); break; case MSG_KEEP_SILENT: //只要不发送消息就暂停了 break; case MSG_BREAK_SILENT: activity.handler.sendEmptyMessageDelayed(MSG_UPDATE_IMAGE, MSG_DELAY); break; case MSG_PAGE_CHANGED: //记录当前的页号,避免播放的时候页面显示不正确。 currentItem = msg.arg1; break; default: break; } } }
个人重点记录一下线程中的东西,其他地方的代码很好理解。以后可以参考使用。
线程中的Onn.isOff,是我们自己定义的一个全局变量。
/** * Created by Administrator on 2016/8/12 0012. */ public class Onn { public static boolean isOff = false; }
这个全局变量是判断我们的线程状态。默认状态是false。for循环中,走的就是我们的进度条的一个动态效果。但是手动切换图片的话,我们的进度条要归零,并且从0开始重新走。这是我们的需求。实现的逻辑就是,当我们手动切换图片的时候,isOff设为true,然后将进度条归零,再将isOff设为false,continue,就继续开始走我们的进度条了。如果正常状态,没有切换,那我们就不走if,直接走我们的进度条啦。
具体的activity中的操作代码如下:
ImageHandler handler = new ImageHandler(new WeakReference<IndexActivity>(this));
LayoutInflater inflater = LayoutInflater.from(this); ImageView view1 = (ImageView) inflater.inflate(R.layout.item_viewpager, null); ImageView view2 = (ImageView) inflater.inflate(R.layout.item_viewpager, null); ImageView view3 = (ImageView) inflater.inflate(R.layout.item_viewpager, null); view1.setImageResource(R.mipmap.banner_test); view2.setImageResource(R.mipmap.banner_test); view3.setImageResource(R.mipmap.banner_test); ArrayList<ImageView> views = new ArrayList<ImageView>(); views.add(view1); views.add(view2); views.add(view3); viewPager.setAdapter(new ImageAdapter(views)); viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() { //配合Adapter的currentItem字段进行设置。 @Override public void onPageSelected(int arg0) { handler.sendMessage(Message.obtain(handler, ImageHandler.MSG_PAGE_CHANGED, arg0, 0)); } @Override public void onPageScrolled(int arg0, float arg1, int arg2) { } //覆写该方法实现轮播效果的暂停和恢复 @Override public void onPageScrollStateChanged(int arg0) { switch (arg0) { case ViewPager.SCROLL_STATE_DRAGGING: handler.sendEmptyMessage(ImageHandler.MSG_KEEP_SILENT); Onn.isOff = true; break; case ViewPager.SCROLL_STATE_IDLE: handler.sendEmptyMessageDelayed(ImageHandler.MSG_UPDATE_IMAGE, ImageHandler.MSG_DELAY); break; default: break; } } }); viewPager.setCurrentItem(0);//默认在中间,使用户看不到边界 new Thread(new Runnable() { @Override public void run() { for (int i = 0; i <= 100; i++) { progressBar.setProgress(i); try { Thread.sleep(60); } catch (InterruptedException e) { e.printStackTrace(); } } } }).start(); //开始轮播效果 handler.sendEmptyMessageDelayed(ImageHandler.MSG_UPDATE_IMAGE, ImageHandler.MSG_DELAY);
这里为什么又单独写了一个Thread线程来走我们的进度条呢,如果按照上述的操作完,你会发现,进来以后的第一张图片是没有进度条的,所以刚进到这个页面我们就需要单独跑一起这个进度条。
还有我们的ImageViewAdapter:
import android.support.v4.view.PagerAdapter; import android.view.View; import android.view.ViewGroup; import android.view.ViewParent; import android.widget.ImageView; import java.util.ArrayList; /** * Created by Administrator on 2016/8/10 0010. */ public class ImageAdapter extends PagerAdapter { private ArrayList<ImageView> viewlist; public ImageAdapter(ArrayList<ImageView> viewlist) { this.viewlist = viewlist; } @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) { //Warning:不要在这里调用removeView } @Override public Object instantiateItem(ViewGroup container, int position) { //对ViewPager页号求模取出View列表中要显示的项 position %= viewlist.size(); if (position<0){ position = viewlist.size()+position; } ImageView view = viewlist.get(position); //如果View已经在之前添加到了一个父组件,则必须先remove,否则会抛出IllegalStateException。 ViewParent vp =view.getParent(); if (vp!=null){ ViewGroup parent = (ViewGroup)vp; parent.removeView(view); } container.addView(view); //add listeners here if necessary return view; } }
这样就实现了我们的循环轮播加进度条监控的效果了。大家可以根据自己的需求进行修改,如果不需要进度条的可以自己将Thread的代码删除就可以单独的实现轮播循环的banner。我主要还是为了记录一下自己,所以加上了这个进度条的效果状态。
如果转载,请标明出处。谢谢。
相关文章推荐
- Android实现Banner界面广告图片循环轮播
- Android实现Banner界面广告图片循环轮播(包括实现手动滑动循环)
- Android广告图片轮播,支持无限循环和设置轮播样式、切换时间等
- Android实现Banner界面广告图片循环轮播(包括实现手动滑动循环)
- Android实现Banner界面广告图片循环轮播(包括实现手动滑动循环)
- Android实现Banner界面广告图片循环轮播(包括实现手动滑动循环)
- Android实现Banner界面广告图片循环轮播(包括实现手动滑动循环)
- Android 循环切换图片 ConvenientBanner简单应用
- Android实现Banner界面广告图片循环轮播
- Android实现Banner界面广告图片循环轮播(包括实现手动滑动循环)
- Android实现Banner图片循环轮播
- android实现banner界面广告图片循环轮播(包括手动活动轮播)
- Android实现Banner界面广告图片循环轮播(包括实现手动滑动循环)
- Android实现一款不错Banner界面广告图片循环轮播
- Android实现Banner界面广告图片循环轮播(包括实现手动滑动循环)
- android无限轮播banner图片--viewpager
- Android使用ViewPager实现图片轮播(高度自适应,左右循环,自动轮播)
- 移动端 图片切换 轮播(banner)
- Android广告图片轮播控件,支持无限循环和5种主题,可以灵活设置轮播样式、时间、位置、图片加载框架等!
- Android自动播放Banner图片轮播效果