Android中用RxJava和ViewPager实现轮播图

前言

很多人要实现轮播图都会想到使用ViewPager + Handler来完成轮播图的效果。但是在RxJava快速发展的情况下,已经可以使用RxJava来代替Handler完成这样任务了。

下面我们就来介绍如何实现RxJava+ViewPager的轮播图。

效果图如下

ViewPager的操作

说到ViwePager应该大家都不陌生,它可以结合普通的View也可以结合Fragment一起使用。在此我也就不对它的使用方法进行过多的介绍了。直接开始介绍轮播的方法。

常见的轮播操作

private class ImageAdapter extends PagerAdapter{

 private ArrayList<ImageView> viewlist;

 public ImageAdapter(ArrayList<ImageView> viewlist) {
  this.viewlist = viewlist;
 }

 @Override
 public int getCount() {
  //设置成最大,使用户看不到边界
  return Integer.MAX_VALUE;
 }
 ....
}
private static class ImageHandler extends Handler{
 ...
 @Override
 public void handleMessage(Message msg) {
  super.handleMessage(msg);
  //检查消息队列并移除未发送的消息,这主要是避免在复杂环境下消息出现重复等问题。
  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);
    //准备下次播放
    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;
  }
 }
 ...
}

以上就是比较常见的轮播图的代码,我只是在网上随便找的。首先它的代码中将PagerAdapter的getCount()返回了一个Integer.MAX_VALUE;它的目的是为了让图片一直的播放下去,但是在一些极限情况下还是会crash的,并且它返回的数量太大了在一定程度上对内存也造成了较大的消耗。其次我们可以看到handler的代码极其的冗杂,不仅多而且逻辑也比较麻烦。 现在我们针对刚才的问题来进行优化

更好的轮播操作

更好的无限播放:设置页卡视图列表时,在前后额外各加一个页卡。最前面加最后一张图片,最后面加第1张图片。然后每当切换到最前的页卡时,就替换成倒数第2个页卡;每当切换到最后的页卡时,就替换成第2个页卡。这样一来就形成了连贯,自然实现了无限滑动的功能。

1)设置ViewPager的视图列表时,在前后各加一个页卡。

for (int i = 0; i < count + 2; i++) {
 if (i == 0) {// 将最前面一页设置成本来最后的那页
  Glide.with(context).
    load(imageTitleBeanList.get(count - 1).getImageUrl()).into(ivImage);
  tvTitle.setText(imageTitleBeanList.get(count - 1).getTitle());
 } else if (i == count + 1) {// 将最后面一页设置成本来最前的那页
  Glide.with(context).
    load(imageTitleBeanList.get(0).getImageUrl()).into(ivImage);
  tvTitle.setText(imageTitleBeanList.get(0).getTitle());
 } else {
  Glide.with(context).
    load(imageTitleBeanList.get(i - 1).getImageUrl()).into(ivImage);
  tvTitle.setText(imageTitleBeanList.get(i - 1).getTitle());
 }
 // 将设置好的View添加到View列表中
 viewList.add(view);
}

2)在监听ViewPager的页卡状态改变中,当滑动到第1个页卡时替换成倒数第2个页卡;当滑动到最后一个页卡时替换成第2个页卡。

@Override
public void onPageScrollStateChanged(int state) {
 switch (state) {
  // 闲置中
  case ViewPager.SCROLL_STATE_IDLE:
   // “偷梁换柱”
   if (vpImageTitle.getCurrentItem() == 0) {
    vpImageTitle.setCurrentItem(count, false);
   } else if (vpImageTitle.getCurrentItem() == count + 1) {
    vpImageTitle.setCurrentItem(1, false);
   }
   currentItem = vpImageTitle.getCurrentItem();
   break;
 }
}

Handler现在就该由RxJava来替代了。

Interval 操作符

创建一个按固定时间间隔发射整数序列的Observable

Interval操作符返回一个Observable,它按固定的时间间隔发射一个无限递增的整数序列。

RxJava将这个操作符实现为interval方法。它接受一个表示时间间隔的参数和一个表示时间单位的参数。

Javadoc: interval(long,TimeUnit)

Javadoc: interval(long,TimeUnit,Scheduler)

interval默认在computation调度器上执行。你也可以传递一个可选的Scheduler参数来指定调度器。

用RxJava取代Handler

public void start() {
 mViewPagerSubscribe = Observable.interval(5, 5, TimeUnit.SECONDS) // 5s的延迟,5s的循环时间
  .subscribeOn(AndroidSchedulers.mainThread())
  .observeOn(AndroidSchedulers.mainThread())
  .subscribe(new Action1<Long>() {
   @Override
   public void call(Long aLong) {
    // 进行轮播操作
    if (mWeeklyMovieInfos != null && mWeeklyMovieInfos.size() > 0 && isAutoPlay) {
     mCurrentPage++;
     mWeeklyViewPager.setCurrentItem(mCurrentPage);
    }
   }
  });
}

为了更好的用户体验,在用户进行滑动操作的时候,应该停止自动轮播

mPager.setOnTouchListener(new View.OnTouchListener() {
 @Override
 public boolean onTouch(View v, MotionEvent event) {
 //监听ViewPager的触摸事件,当用户按下的时候取消注册,当用户手抬起的时候再注册
  switch (event.getAction()){
   case MotionEvent.ACTION_DOWN:
    stop();
    break;
   case MotionEvent.ACTION_UP:
    start();
    break;
  }
  return false;
 }});

public void stop() {
 if(mViewPagerSubscribe.isUnsubscribed()) {
  mViewPagerSubscribe.unsubscribe();
 }
}

总结

这篇文章主要是对ViewPager实现轮播图的一种总结。首先提出更好的轮播图的方法,其实讲解了RxJava中interval操作符的使用,最后用该操作符替换掉Handler完美实现轮播图。以上就是这篇文章的全部内容,希望本文的内容能对大家有所帮助,如果有疑问大家可以留言交流。

(0)

相关推荐

  • android使用RxJava实现预加载

    在上一篇文章中介绍了使用非RxJava环境下,使用Handler机制SyncBarrier的特性实现预加载功能的方法. 在RxJava的环境下使用BehaviorSubject的特性来实现也是很方便的. BehaviorSubject内部会缓存消息流中最近的一个消息, 在后续有Subscriber订阅时,会直接将缓存的消息发送给Subscriber. RxPreLoader.java封装如下: import android.support.annotation.NonNull; import j

  • 一篇文章就能了解Rxjava

    前言: 第一次接触RxJava是在前不久,一个新Android项目的启动,在评估时选择了RxJava.RxJava是一个基于事件订阅的异步执行的一个类库.听起来有点复杂,其实是要你使用过一次,就会大概明白它是怎么回事了!为是什么一个Android项目启动会联系到RxJava呢?因为在RxJava使用起来得到广泛的认可,又是基于Java语言的.自然会有善于组织和总结的开发者联想到Android!没错,RxAndroid就这样在RxJava的基础上,针对Android开发的一个库.今天我们主要是来讲

  • Android中通过RxJava进行响应式程序设计的入门指南

    错误处理 到目前为止,我们都没怎么介绍onComplete()和onError()函数.这两个函数用来通知订阅者,被观察的对象将停止发送数据以及为什么停止(成功的完成或者出错了). 下面的代码展示了怎么使用这两个函数: Observable.just("Hello, world!") .map(s -> potentialException(s)) .map(s -> anotherPotentialException(s)) .subscribe(new Subscrib

  • Android中的Retrofit+OkHttp+RxJava缓存架构使用

    RxJava如何与Retrofit结合 先扔出build.gradle文件的内容 dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) testCompile 'junit:junit:4.12' compile 'com.android.support:appcompat-v7:23.2.0' compile 'io.reactivex:rxjava:1.1.0' compile 'io.reactivex:rxand

  • Android Retrofit和Rxjava的网络请求

    Android  Retrofit和Rxjava的网络请求 去年的时候好多公司就已经使用Rxjava和Retrofit了,最近自自己学习了一下,感觉真的是很好用,让自己的网络请求变得更简单了,而且封装性极强. 首先做一下准备工作,导入需要引用的文件 compile 'com.android.support:appcompat-v7:25.1.0' testCompile 'junit:junit:4.12' compile 'io.reactivex:rxjava:1.1.0' compile

  • Android中用RxJava和ViewPager实现轮播图

    前言 很多人要实现轮播图都会想到使用ViewPager + Handler来完成轮播图的效果.但是在RxJava快速发展的情况下,已经可以使用RxJava来代替Handler完成这样任务了. 下面我们就来介绍如何实现RxJava+ViewPager的轮播图. 效果图如下 ViewPager的操作 说到ViwePager应该大家都不陌生,它可以结合普通的View也可以结合Fragment一起使用.在此我也就不对它的使用方法进行过多的介绍了.直接开始介绍轮播的方法. 常见的轮播操作 private

  • Android 使用ViewPager实现轮播图效果

    写这篇文章只是对今天所学的知识进行加深印象,对ViewPager的一些处理,比如适配器和各个方法的作用等. 先看效果图 这里我是在xml中写的圆点 Drawable文件夹下的xml代码: Shape_yes.xml: <?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android">

  • Android ViewPager实现轮播图效果

    先上一张效果图: 说到ViewPager实现轮播图效果,那么肯定会用到PagerAdapter,下面先介绍下这个类. PagerAdapter简介 PagerAdapter是Android.support.v4包中的类,是一个抽象类,直接继承于Object,导入包android.support.v4.view.PagerAdapter即可使用. PagerAdapter主要是viewpager的适配器,而viewPager则也是在android.support.v4扩展包中新添加的一个强大的控件

  • Android ViewPager自定义轮播图并解决播放冲突

    本文实例为大家分享了Android ViewPager自定义轮播图,并解决播放冲突,供大家参考 首先介绍一下这篇小代码: 注释全面,简单易学,适用初学者,图片自拟!!! 一定要将ArrayList集合&Handler机制传到适配器,否则无法完成展示,也解决不了滑动冲突,代码有点多,但是它通俗易懂啊 layout布局内写法: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:

  • 浅谈Viewpager和轮播图的冲突解决方法

    实例如下: //解决ViewPager和轮播图滑动冲突 @Override public boolean dispatchTouchEvent(MotionEvent ev) { switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: // 让当前viewpager的父控件不去拦截touch事件 getParent().requestDisallowInterceptTouchEvent(true); downX = (int) ev.ge

  • android控件Banner实现简单轮播图效果

    本文实例为大家分享了android控件Banner实现简单轮播图效果的具体代码,供大家参考,具体内容如下 实现这个轮播图是在Fragment里实现的,所以要想实现,首先要创建Fragment 首先是布局文件中的展示 <com.youth.banner.Banner android:id="@+id/banner" android:layout_width="match_parent" android:layout_height="500dp"

  • Android自定义控件实现优雅的广告轮播图

    前言 今天给大家带来一个新的控件–轮播图,网上已经有很多这类的博客来讲解如何实现的,那么我的这个有哪些特点呢?或是说有哪些不同呢? 满足了轮播图的基本要求,循环滑动,在最后一张切到第一张时可以平稳的过渡 简洁简洁简洁 扩展性强 如何使用 下面我们先展示两种效果图 1 默认效果 代码实现 //布局代码 <com.landptf.view.BannerM android:id="@+id/bm_banner" android:layout_width="match_pare

  • Android仿一号店货物详情轮播图动画效果

    还不是很完全,目前只能点中间图片才能位移,图片外的其他区域没有..(属性动画),对了,图片加载用得是facebook的一款android图片加载库,感觉非常NB啊,完爆一切. 1.先看布局 <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:t

  • ViewPager打造轮播图Banner/引导页Guide

    前言 去年7月时,在Github发布了一个开源的Banner库,虽然Star不多,但还是有少部分人使用. Banner效果: Github链接地址:https://github.com/Allure0/LMBanners 昨天,有使用此库的同学提出需求,想在引导页的时候用这个库并且最后一页有进入按钮如何实现,为满足他的需求,也方便更多开发者是快速实现.进行了简单的扩展支持Guide模式的使用. Guide效果图: OK,效果如图所以,咱们此库满足了既可在Banner上使用也可以快速在第一次安装应

  • Android实现ViewPage轮播图效果

    在android移动端的开发中,首页轮播图是一个特别常见的功能,所以今天就来将最近写的一个小demo记录一下. 首先当然是新建一个项目代码如下: activity_main.xml文件: <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:to

随机推荐