十分钟写一个Android轮播控件

轮播控件的组成部分

我们以知乎日报Android客户端的轮播控件为例,分析一下轮播控件的主要组成:

《十分钟写一个Android轮播控件》

首先我们要有用来显示图片的View对象,根据上图中底部中央的5个圆点,我们知道需要5个ImageView来显示需要轮播的图片,图片上的文字用TextView来显示即可,由于图片和文字是“堆叠”在一起的,因此用一个FrameLayout来盛放ImageView和TextView。另外还需要5个ImageView来显示那5个圆点。一个轮播控件应该具有以下行为:首先需要每隔一定时间间隔自动切换到下一张图片,并且图片间切换的效果应该是平滑的,就像“翻书”一样。由此我们可以想到使用ViewPager,这样图片切换时自然会有平滑的效果。接下来,我们还要给底部的5个小点找一个父容器,由于它们是线性排列的,所以用LinearLayout即可。接下来,我们还要把ViewPager和容纳5个点的LinearLayout放入一个父容器中,这里我们选择使用垂直排列子View的LinearLayout。
这样一来,我们就得到了轮播控件的布局文件(carousel_layout.xml):

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout             
    xmlns:android="http://schemas.android.com/apk/res/android"     
    android:layout_width="match_parent" 
    android:layout_height="match_parent"  
    android:orientation="vertical">   
    <android.support.v4.view.ViewPager    
        android:id="@+id/view_pager"    
        android:layout_width="match_parent"    
        android:layout_height="match_parent" />   
    <LinearLayout    
        android:id="@+id/dots"    
        android:layout_width="match_parent"    
        android:layout_height="wrap_content"    
        android:layout_gravity="bottom"    
        android:gravity="center"    
        android:orientation="horizontal"    
        android:padding="8dp" > 
    </LinearLayout>
</LinearLayout>

通过对轮播控件的组成部分进行分析,我们已经确定了轮播控件的用户界面,那么接下来,我们要做的就是实现轮播控件的业务逻辑。

轮播控件的行为分析

轮播控件首先要具有的行为是自动播放,也就是每隔一定时间间隔(通常是3到5秒),便自动”翻到下一页“。为了实现这一点,我们可以维护一个currentItem变量来记录当前正在显示的页面,然后设置一个定时任务,每隔一定时间间隔做以下两件事:

  • 调用ViewPager的setCurrentItem方法将currentItem设置为当前要显示的页面;
  • 将currentItem设为下一张要显示的页面。

有一点需要我们注意的便是播放到最后一张页面时,下一个被显示的应该是第一个页面,以实现循环播放。
除了自动播放外,轮播控件还要能响应我们的滑动手势,也就是我们能够通过左右滑动来在不同的页面之间切换,这个行为ViewPager自动为我们提供了。另外还有一个轮播控件应该具备的行为是:当切换到指定页面时,相应的圆点应该以区别其他4个圆点的颜色显示,以便用户能够知道当前正在播放的是第几个页面。要实现这一点也不复杂,只需要为ViewPager添加一个OnPageChangeListener监听器,然后重写相应的回调方法即可,这样当用户选定了某个Page时,onPageSelected方法会被回调,系统会传入当前Page的索引,我们便可以根据这个索引设置相应的圆点颜色。

轮播控件的具体实现

经过以上的分析,我们已经清楚的了解了轮播控件的表示逻辑及业务逻辑,接下来我们只要把这些逻辑清楚无歧义地描述出来就大功告成了。

定时任务

我们需要定时执行 “改变ViewPager当前页面为下一页面” 这一任务,这里我们采用Handler来实现,代码如下:

mHandler.postDelayed(task, DELAY);
private final Runnable task=new Runnable() {  
  @Override  
  public void run() {    
    if (isAutoPlay) {      
      currentItem=(currentItem+1)%(mTopStories.size());      
      mVP.setCurrentItem(currentItem);      
      mHandler.postDelayed(task, DELAY);    
    } else {      
      mHandler.postDelayed(task, DELAY);    
    }  
  }
};

在以上代码中,DELAY代表我们设置的一个延迟常量(单位ms)。由于我们需要的是循环播放,因此第5张显示完毕后应该显示第一张,所以我们在计算currentItem时要像上面那样进行一个模运算,这样currentItem就在0到4之间不停变化了。注意到上面的代码中有一个isAutoPlay变量,这个变量表示当前是否应该自动播放。那么什么时候不应该自动播放呢?我们知道当我们滑动手指切换图片时,图片会“跟随”着我们的手,就好比我们翻书页的时候,只有松开了手书页才能落下。所以我们正在“拖动”图片时,也就是我们的手还没松开时,轮播控件是不应该自动播放的。为了实现这一点,我们只需重写OnPageChangeListener中的onPageScrollStateChanged方法,在当前状态为“拖动”时设置isAutoPlay变量为false。而当autoPlay为false时,不会改变当前显示的图片,仅仅会等过了DELAY指定的时间后再执行下一次定时任务。

OnPageChangeListener

上面我们提到了要给ViewPager添加一个OnPageChangeListener监听器对象,来实现小圆点颜色的改变以及autoPlay变量的赋值。具体的实现请看以下代码:

class TopOnPageChangeListener implements ViewPager.OnPageChangeListener {  
  @Override  
  public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {  
  }   
  @Override  
  public void onPageSelected(int position) {    
    for (int i = 0; i < mDotsIV.size(); i++) {      
      if(i==position){        
        mDotsIV.get(i).setImageResource(R.drawable.dot_focus);      
      } else {        
        mDotsIV.get(i).setImageResource(R.drawable.dot_blur);      
      }    
    }  
  }   
  @Override  public void onPageScrollStateChanged(int state) {    
    switch (state) {      
      //SCROLL_STATE_DRAGGING      
      case 1:        
        isAutoPlay = false;        
        break;      
      //SCROLL_STATE_SETTLING2      
      case 2:        
        isAutoPlay = true;        
        break;      
      default:       
        break;
    }  
  }
}

在以上代码中,我们重写了onPageSelected方法,position参数表示当前Page的索引。这个方法中,我们设置当前页面对应的圆点图片为dot_focus,设置其他页面对应圆点的图片为dot_blur,这样用户就能知道当前的位置。同时我们重写了onPageScrollStateChanged方法,state参数代表了当前的“滚动状态“,这个值为1表示当前用户正在”拖动“的过程中,因此要设置isAutoPlay为false;这个值为2表示用户松开了手,图片正在”滚动“中,这时我们就要把isAutoPlay设回默认值true,恢复自动播放。
现在我们已经实现了一个Android轮播控件啦,是不是很简单呢。完整的代码请见这里:https://github.com/absfree/CarouselDemo

长按或扫描二维码关注我们,让您利用每天等地铁的时间就能学会怎样写出优质app。

《十分钟写一个Android轮播控件》

    原文作者:absfree
    原文地址: https://www.jianshu.com/p/2e0810b2189f
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞