Android简单实现无限滚动自动滚动的ViewPager

 更新时间:2016年12月27日 10:55:36   作者:Burnner  
这篇文章主要介绍了Android简单实现无限滚动自动滚动的ViewPager,百度谷歌上面也有很多关于这方面的教程,但是感觉都略显麻烦,而且封装的都不是很彻底。所以试着封装一个比较好用的ViewPager,实现思路一起通过本文学习吧

经常我们会在应用中看到一个可以自动滚动,并且无限滚动的一个ViewPager,百度谷歌上面也有很多关于这方面的教程,但是感觉都略显麻烦,而且封装的都不是很彻底。所以试着封装一个比较好用的ViewPager

效果如下:

简单的说一下实现思路,要实现无限滚动的话就要在PagerAdapter上面做一些手脚,在PagerAdapter的getCount的函数的返回值设置成Integer.MXA_VALUE就可以实现向右无限滚动,但是要实现向左无限滚动呢?就是一开始的时候setCurrentItem的时候设置一个非常大的值(大到你向左滚动了一万年还是有东西)

@Override 
    public int getCount() { 
      return Integer.MAX_VALUE; 
    } 
mPager.setCurrentItem(10000 * mDatas.size());//一开始设置成这样的话就可以向左无限滚动了 

然后另外一个就是底部的游标了:

底部的游标是用一个自定义视图:无非就是画一个背景,然后在画一个高亮的游标

/** 
  * 指示游标 
  */ 
  private class TipView extends View { 
    private int mPadding; 
    private int mCount; 
    private int mCurPos; 
    private Paint mNorPaint;//未被选中的颜色 
    private Paint mSelPaint;//被选中的颜色 白色 
    private int mHeight; 
    public TipView(Context context, int count) { 
      super(context); 
      mNorPaint = new Paint(); 
      mNorPaint.setAntiAlias(true); 
      int selHeight = ShowUtils.dip2px(2); 
      int norHeight = ShowUtils.dip2px(1); 
      mHeight = ShowUtils.dip2px(2); 
      mNorPaint.setStrokeWidth(norHeight); 
      mNorPaint.setColor(Color.argb(80, 255, 255, 255)); 
      mSelPaint = new Paint(); 
      mSelPaint.setAntiAlias(true); 
      mSelPaint.setStrokeWidth(selHeight); 
      mSelPaint.setColor(Color.WHITE); 
      mCount = count; 
      mPadding = ShowUtils.dip2px(0); 
    } 
    @Override 
    protected void onDraw(Canvas canvas) { 
      super.onDraw(canvas); 
      int ow = (getWidth()-2 * mPadding)/ mCount; 
      int y = getHeight() / 2; 
      canvas.drawLine(mPadding, y, mCurPos * ow + mPadding, y, mNorPaint); 
      canvas.drawLine(mCurPos * ow + mPadding, y, (mCurPos + 1) * ow + mPadding, y, mSelPaint); 
      canvas.drawLine((mCurPos + 1) * ow + mPadding, y, getWidth() - mPadding, y, mNorPaint); 
    } 
    @Override 
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 
      ViewGroup.LayoutParams vp = getLayoutParams(); 
      vp.width = ViewGroup.LayoutParams.MATCH_PARENT; 
      vp.height = mHeight; 
      super.onMeasure(widthMeasureSpec, heightMeasureSpec); 
    } 
    public void setCurPostion(int pos) { 
      mCurPos = pos; 
      invalidate(); 
    } 
    public void setCount(int count) { 
      mCount = count; 
    } 
  } 

R.layout.layout_recommend_item的布局:

<?xml version="1.0" encoding="utf-8"?> 
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
  android:orientation="vertical" 
  android:layout_width="match_parent" 
  android:layout_height="match_parent"> 
  <ImageView 
    android:id="@+id/iv_pic" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:contentDescription="@null" 
    android:scaleType="fitXY"/> 
  <LinearLayout 
    android:layout_width="match_parent" 
    android:layout_height="48dp" 
    android:orientation="vertical" 
    android:layout_alignParentBottom="true" 
    android:background="@drawable/recommend" 
    android:gravity="center"> 
    <TextView 
      android:id="@+id/tv_desc" 
      android:layout_width="match_parent" 
      android:layout_height="wrap_content" 
      android:textColor="@color/white" 
      android:textSize="@dimen/text_normal" 
      android:maxLines="1" 
      android:ellipsize="end" 
      android:shadowColor="#ff333333" 
      android:shadowDx="2" 
      android:shadowDy="2" 
      android:paddingRight="8dp" 
      android:paddingLeft="8dp" 
      android:shadowRadius="1" /> 
  </LinearLayout> 
</RelativeLayout> 

还有一个是实现自动滚动,自动滚动的话就是监听OnPagerChangeListener里面的函数,在ViewPager状态改变的时候利用Handler发送一个切换界面的消息:

@Override 
    public void onPageScrollStateChanged(int i) { 
      curState = i; 
      if(i == ViewPager.SCROLL_STATE_DRAGGING){  //viewpager正在被拖动的时候 
        stopAnimation(); 
      }else { //没有可执行消息时候添加消息 实现自动滚动 
        if(!(sHandler.hasMessages(START_SCROLL)&&sHandler.hasMessages(SCROLL_NEXT))){ 
          startAnimation(); 
        } 
      } 
    } 
    @Override 
    public void onPageSelected(final int i) {  //页面跳转后得到调用 
      sHandler.removeMessages(SCROLL_NEXT); 
      sHandler.removeMessages(START_SCROLL); 
      if(curState == ViewPager.SCROLL_STATE_DRAGGING){ 
        return; 
      } 
      Message msg = sHandler.obtainMessage(SCROLL_NEXT); 
      msg.arg1 = i + 1; 
      msg.obj = mPager; 
      sHandler.sendMessageDelayed(msg, SHOW_TIME); 
      mTipView.setCurPostion(i % mDatas.size()); 
    } 

整体的代码:

import android.content.Context; 
import android.graphics.Canvas; 
import android.graphics.Color; 
import android.graphics.Paint; 
import android.os.Handler; 
import android.os.Message; 
import android.support.v4.view.PagerAdapter; 
import android.support.v4.view.ViewPager; 
import android.util.DisplayMetrics; 
import android.view.View; 
import android.view.ViewGroup; 
import android.widget.ImageView; 
import android.widget.RelativeLayout; 
import android.widget.TextView; 
import com.nostra13.universalimageloader.core.DisplayImageOptions; 
import com.nostra13.universalimageloader.core.ImageLoader; 
import com.papau.show.R; 
import com.papau.show.entity.HeadViewEntity; 
import com.papau.show.utils.ShowUtils; 
import java.util.ArrayList; 
import java.util.List; 
public class RecommendView extends RelativeLayout implements IRecommend { 
  private static final int START_SCROLL = 1; 
  private static final int SCROLL_NEXT = 2; 
  private static final int SHOW_TIME = 5000; 
  private List<HeadViewEntity> mDatas = new ArrayList<>(); 
  private ViewPager mPager; 
  private Context mContext; 
  private int mWidth, mHeight; 
  private ImageLoader mLoader; 
  private DisplayImageOptions mOptions; 
  private int mTitleHeight; 
  private TipView mTipView; 
  private static Handler sHandler = new Handler() { 
    @Override 
    public void handleMessage(Message msg) { 
      int w = msg.what; 
      ViewPager pager = (ViewPager) msg.obj; 
      switch (w) { 
        case START_SCROLL: 
          pager.setCurrentItem(msg.arg1, true); 
          break; 
        case SCROLL_NEXT: 
          pager.setCurrentItem(msg.arg1, true); 
          break; 
      } 
    } 
  }; 
  public RecommendView(Context context) { 
    super(context); 
  } 
  public RecommendView(Context context, int w, int h) { 
    super(context); 
    mContext = context; 
    mWidth = w; 
    mHeight = h; 
    initView(); 
//    mPager.setAdapter(new RecommendAdapter()); 
    mPager.setOnPageChangeListener(new MOnPagerChangeListener()); 
    mLoader = ImageLoaderManager.getImageLoader(mContext); 
    mOptions = ImageLoaderManager.getCacheOnDiskOptions(mContext); 
    init(); 
//    DisplayMetrics dm = mContext.getResources().getDisplayMetrics(); 
    mTitleHeight = ShowUtils.dip2px(48);//设置游标高度 
  } 
  @Override 
  protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 
    ViewGroup.LayoutParams vp = getLayoutParams(); 
    if (vp != null) {  //设置视图的宽高 
      vp.width = mWidth; 
      vp.height = mHeight; 
    } 
    super.onMeasure(widthMeasureSpec, heightMeasureSpec); 
  } 
  private void initView() { 
    mPager = new ViewPager(mContext); 
    RelativeLayout.LayoutParams rp = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT); 
    addView(mPager, rp); 
  } 
  /** 
   * 初始化指示游标 
   */ 
  private void initTipView() { 
    if (mTipView == null) { 
      RelativeLayout.LayoutParams rp = new RelativeLayout.LayoutParams(10, 10); 
      rp.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);//显示在父控件的底部 
      rp.bottomMargin = mTitleHeight;//游标的高度 
      mTipView = new TipView(mContext, mDatas.size()); 
      addView(mTipView, rp); 
    } else { 
      mTipView.setCount(mDatas.size()); 
    } 
  } 
  @Override 
  public void upDate() { 
    getData(); 
  } 
  @Override 
  public void init() { 
    getData(); 
  } 
  @Override 
  public void startAnimation() { 
    if (mDatas.size() == 0) { 
      return; 
    } 
    Message msg = sHandler.obtainMessage(START_SCROLL); 
    msg.obj = mPager; 
    msg.arg1 = (mPager.getCurrentItem() + 1); 
    sHandler.sendMessageDelayed(msg, SHOW_TIME); 
  } 
  @Override 
  public void stopAnimation() { 
    sHandler.removeMessages(START_SCROLL); 
    sHandler.removeMessages(SCROLL_NEXT); 
  } 
  /** 
   * 获取viewpager要显示的数据 
   */ 
  private void getData() { 
    String[] imageData = new String[]{"http://f.hiphotos.baidu.com/image/h%3D360/sign=e105b9f1d61b0ef473e89e58edc651a1/b151f8198618367a9f738e022a738bd4b21ce573.jpg", 
        "http://c.hiphotos.baidu.com/image/h%3D360/sign=b8cea9e92b738bd4db21b437918b876c/f7246b600c3387448982f948540fd9f9d72aa0bb.jpg", 
        "http://a.hiphotos.baidu.com/image/h%3D360/sign=3da95d01e7dde711f8d245f097eecef4/71cf3bc79f3df8dc39cb6295cf11728b461028c4.jpg", 
        "http://d.hiphotos.baidu.com/image/h%3D360/sign=410c3c96a60f4bfb93d09852334f788f/10dfa9ec8a136327a1de913a938fa0ec08fac78c.jpg", 
        "http://e.hiphotos.baidu.com/image/h%3D360/sign=f6600b1613dfa9ece22e501152d1f754/342ac65c10385343ff41ee2b9113b07eca808829.jpg"}; 
    for (int i = 0; i < 5; i++) { 
      HeadViewEntity info = new HeadViewEntity(); 
      info.setImageUrl(imageData[i]); 
      info.setTitle("我不做大哥好多年"+i); 
      info.setUrl("www.baidu.com"); 
      mDatas.add(info); 
    } 
    sHandler.postDelayed(new Runnable() { 
      @Override 
      public void run() { 
        stopAnimation(); 
        initTipView(); 
        mPager.setAdapter(new RecommendAdapter()); 
        mPager.setCurrentItem(10000 * mDatas.size());//一开始设置成这样的话就可以向左无限滚动了 
      } 
    },2000); 
  } 
  /** 
   * viewpager子项内容 
   */ 
  private class RecommendAdapter extends PagerAdapter { 
    /** 
     * 填充子项视图的内容 
     * @param container 父控件 viewpager 
     * @param position 子项的位置 
     * @return 返回子项视图 
     */ 
    @Override 
    public Object instantiateItem(ViewGroup container, int position) { 
      int curPos = position % mDatas.size(); 
      View view = View.inflate(mContext, R.layout.layout_recommend_item, null); 
      ViewGroup.LayoutParams vp = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); 
      ImageView iv = (ImageView) view.findViewById(R.id.iv_pic); 
      TextView tv = (TextView) view.findViewById(R.id.tv_desc); 
      tv.setText(mDatas.get(curPos).getTitle()); 
      mLoader.displayImage(mDatas.get(curPos).getImageUrl(), iv, mOptions); 
      container.addView(view, vp); 
      view.setTag(curPos); 
      view.setOnClickListener(new OnClickListener() { 
        @Override 
        public void onClick(View v) { 
        } 
      }); 
      return view; 
    } 
    @Override 
    public void destroyItem(ViewGroup container, int position, Object object) { 
      container.removeView((View) object); 
    } 
    @Override 
    public int getCount() { 
      return Integer.MAX_VALUE; 
    } 
    @Override 
    public boolean isViewFromObject(View view, Object o) { 
      return view == o; 
    } 
  } 
  private class MOnPagerChangeListener implements ViewPager.OnPageChangeListener { 
    private int curState; 
    @Override 
    public void onPageScrolled(int i, float v, int i1) { 
    } 
    @Override 
    public void onPageScrollStateChanged(int i) { 
      curState = i; 
      if(i == ViewPager.SCROLL_STATE_DRAGGING){  //viewpager正在被拖动的时候 
        stopAnimation(); 
      }else { //没有可执行消息时候添加消息 实现自动滚动 
        if(!(sHandler.hasMessages(START_SCROLL)&&sHandler.hasMessages(SCROLL_NEXT))){ 
          startAnimation(); 
        } 
      } 
    } 
    @Override 
    public void onPageSelected(final int i) {  //页面跳转后得到调用 
      sHandler.removeMessages(SCROLL_NEXT); 
      sHandler.removeMessages(START_SCROLL); 
      if(curState == ViewPager.SCROLL_STATE_DRAGGING){ 
        return; 
      } 
      Message msg = sHandler.obtainMessage(SCROLL_NEXT); 
      msg.arg1 = i + 1; 
      msg.obj = mPager; 
      sHandler.sendMessageDelayed(msg, SHOW_TIME); 
      mTipView.setCurPostion(i % mDatas.size()); 
    } 
  } 
  /** 
   * 指示游标 
   */ 
  private class TipView extends View { 
    private int mPadding; 
    private int mCount; 
    private int mCurPos; 
    private Paint mNorPaint;//未被选中的颜色 
    private Paint mSelPaint;//被选中的颜色 白色 
    private int mHeight; 
    public TipView(Context context, int count) { 
      super(context); 
      mNorPaint = new Paint(); 
      mNorPaint.setAntiAlias(true); 
      int selHeight = ShowUtils.dip2px(2); 
      int norHeight = ShowUtils.dip2px(1); 
      mHeight = ShowUtils.dip2px(2); 
      mNorPaint.setStrokeWidth(norHeight); 
      mNorPaint.setColor(Color.argb(80, 255, 255, 255)); 
      mSelPaint = new Paint(); 
      mSelPaint.setAntiAlias(true); 
      mSelPaint.setStrokeWidth(selHeight); 
      mSelPaint.setColor(Color.WHITE); 
      mCount = count; 
      mPadding = ShowUtils.dip2px(0); 
    } 
    @Override 
    protected void onDraw(Canvas canvas) { 
      super.onDraw(canvas); 
      int ow = (getWidth()-2 * mPadding)/ mCount; 
      int y = getHeight() / 2; 
      canvas.drawLine(mPadding, y, mCurPos * ow + mPadding, y, mNorPaint); 
      canvas.drawLine(mCurPos * ow + mPadding, y, (mCurPos + 1) * ow + mPadding, y, mSelPaint); 
      canvas.drawLine((mCurPos + 1) * ow + mPadding, y, getWidth() - mPadding, y, mNorPaint); 
    } 
    @Override 
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 
      ViewGroup.LayoutParams vp = getLayoutParams(); 
      vp.width = ViewGroup.LayoutParams.MATCH_PARENT; 
      vp.height = mHeight; 
      super.onMeasure(widthMeasureSpec, heightMeasureSpec); 
    } 
    public void setCurPostion(int pos) { 
      mCurPos = pos; 
      invalidate(); 
    } 
    public void setCount(int count) { 
      mCount = count; 
    } 
  } 
} 

然后提供了一个接口调用:

/** 
 * RecommendView接口 
 */ 
public interface IRecommend { 
  void upDate(); 
  void init(); 
  void startAnimation(); 
  void stopAnimation(); 
}

图片的加载用到了ImageLoad库:

import android.content.Context; 
import android.graphics.Bitmap; 
import com.nostra13.universalimageloader.cache.disc.impl.UnlimitedDiskCache; 
import com.nostra13.universalimageloader.core.DisplayImageOptions; 
import com.nostra13.universalimageloader.core.ImageLoader; 
import com.nostra13.universalimageloader.core.ImageLoaderConfiguration; 
import com.nostra13.universalimageloader.core.assist.ImageScaleType; 
import com.papau.show.constant.Constants; 
import java.io.File; 
public class ImageLoaderManager { 
  /** 
   * 不带硬盘缓存的options 
   * 
   * @param context 
   * @return 
   */ 
  public static synchronized DisplayImageOptions getCacheOnMemoryOptions(Context context) { 
    DisplayImageOptions options = new DisplayImageOptions.Builder() 
        .cacheInMemory(true) 
        .cacheOnDisk(false) 
        .imageScaleType(ImageScaleType.EXACTLY_STRETCHED) 
        .bitmapConfig(Bitmap.Config.ARGB_8888) 
//        .showImageOnLoading( 
//            context.getResources().getDrawable( 
//                R.drawable.loading_wait)) 
//        .showImageOnFail( 
//            context.getResources().getDrawable( 
//                R.drawable.loading_wait)) 
        .build(); 
    return options; 
  } 
  public static synchronized DisplayImageOptions getCircleOptions(Context context) { 
    DisplayImageOptions options = new DisplayImageOptions.Builder() 
        .cacheInMemory(true) 
        .cacheOnDisk(false) 
        .imageScaleType(ImageScaleType.EXACTLY_STRETCHED) 
        .bitmapConfig(Bitmap.Config.ARGB_8888) 
//        .showImageOnLoading( 
//            context.getResources().getDrawable( 
//                R.drawable.ic_user_head_hint)) 
//        .showImageOnFail( 
//            context.getResources().getDrawable( 
//                R.drawable.ic_user_head_hint)) 
        .build(); 
    return options; 
  } 
  /** 
   * 获取在硬盘中缓存options 
   * 
   * @param context 
   * @return options 
   */ 
  public static synchronized DisplayImageOptions getCacheOnDiskOptions( 
      Context context) { 
    DisplayImageOptions options = new DisplayImageOptions.Builder() 
        .cacheInMemory(true) 
        .cacheOnDisk(true) 
        .imageScaleType(ImageScaleType.EXACTLY) 
        .bitmapConfig(Bitmap.Config.ARGB_8888) 
//        .showImageOnLoading( 
//            context.getResources().getDrawable( 
//                R.drawable.loading_wait)) 
//        .showImageOnFail( 
//            context.getResources().getDrawable( 
//                R.drawable.loading_wait)) 
        .build(); 
    return options; 
  } 
  /** 
   * 获取imageLoader 单例 
   * 
   * @param context 
   * @return 
   */ 
  public static synchronized ImageLoader getImageLoader(Context context) { 
    ImageLoader imageLoader = ImageLoader.getInstance(); 
    File cacheDir = new File(Constants.sPicCacheLocalPath); 
    ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder( 
        context).diskCache(new UnlimitedDiskCache(cacheDir)) 
        .threadPoolSize(3) 
        .diskCacheExtraOptions(480, 320, null) 
        .build(); 
    imageLoader.init(config); 
    return imageLoader; 
  } 
} 

使用方法

DisplayMetrics dm = getActivity().getResources().getDisplayMetrics(); 
    RecommendView rv = new RecommendView(getActivity(),dm.widthPixels ,(dm.widthPixels)/2); 
    headViewPager.addView(rv); 

以上所述是小编给大家介绍的Android简单实现无限滚动自动滚动的ViewPager,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对脚本之家网站的支持!

相关文章

  • Android studio将Module打包成Jar的方法

    Android studio将Module打包成Jar的方法

    这篇文章主要介绍了Android studio将Module打包成Jar的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-10-10
  • Android使用Span打造丰富多彩的文本详解

    Android使用Span打造丰富多彩的文本详解

    在开发过程中经常需要使用文本,有时候需要对一段文字中的部分文字进行特殊的处理,如改变其中部分文字的大小、颜色、加下划线等。本文将为大家介绍如何实现这些效果,感兴趣的可以学习一下
    2022-01-01
  • Android 中实现ListView滑动隐藏标题栏的代码

    Android 中实现ListView滑动隐藏标题栏的代码

    本文通过实例代码给大家分享了android listview滑动隐藏标题栏的方法,代码简单易懂,需要的朋友参考下
    2017-01-01
  • Android保存多张图片到本地的实现方法

    Android保存多张图片到本地的实现方法

    这篇文章主要给大家介绍了关于Android保存多张图片到本地的实现方法,文中通过示例代码介绍的非常详细,对各位Android开发者们具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2019-06-06
  • Android编程实现播放MP3功能示例

    Android编程实现播放MP3功能示例

    这篇文章主要介绍了Android编程实现播放MP3功能,结合实例形式分析了Android播放MP3功能的界面布局与功能实现相关操作技巧,需要的朋友可以参考下
    2017-02-02
  • Android自定义View实现九宫格图形解锁(Kotlin版)

    Android自定义View实现九宫格图形解锁(Kotlin版)

    这篇文章主要为大家详细介绍了Android自定义View实现九宫格图形解锁,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-09-09
  • Android开发系列二之窗口Activity的生命周期

    Android开发系列二之窗口Activity的生命周期

    这篇文章主要介绍了Android学习系列二之窗口Activity的生命周期的相关资料,需要的朋友可以参考下
    2016-05-05
  • Kotlin如何捕获上下文中的变量与常量详解

    Kotlin如何捕获上下文中的变量与常量详解

    这篇文章主要给大家介绍了关于Kotlin如何捕获上下文中的变量与常量的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用Kotlin具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2019-08-08
  • Android中AsyncTask与handler用法实例分析

    Android中AsyncTask与handler用法实例分析

    这篇文章主要介绍了Android中AsyncTask与handler用法,以实例形式较为详细的分析了Android中AsyncTask与handler的功能、用法与相关注意事项,并附带完整实例源码供读者下载,需要的朋友可以参考下
    2015-10-10
  • Android多媒体应用使用SoundPool播放音频

    Android多媒体应用使用SoundPool播放音频

    这篇文章主要为大家详细介绍了Android多媒体应用使用SoundPool播放音频,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-12-12

最新评论