欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

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

程序员文章站 2024-02-25 19:17:15
经常我们会在应用中看到一个可以自动滚动,并且无限滚动的一个viewpager,百度谷歌上面也有很多关于这方面的教程,但是感觉都略显麻烦,而且封装的都不是很彻底。所以试着封装...

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

效果如下:

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

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

@override 
    public int getcount() { 
      return integer.max_value; 
    } 
mpager.setcurrentitem(10000 * mdatas.size());//一开始设置成这样的话就可以向左无限滚动了 

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

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

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

/** 
  * 指示游标 
  */ 
  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,希望对大家有所帮助