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

Android实现自定义轮播图片控件详解

程序员文章站 2024-03-03 17:36:10
首先上效果图 实现原理 要完成一个轮播图片,首先想到的应该是使用viewpager来实现。viewpager已经有了滑动的功能,我们只要让它自己滚动。再加上下方的小...

首先上效果图

Android实现自定义轮播图片控件详解

实现原理

要完成一个轮播图片,首先想到的应该是使用viewpager来实现。viewpager已经有了滑动的功能,我们只要让它自己滚动。再加上下方的小圆点就行了。所以我们本次的自定义控件就是由viewpagerlinearlayout叠加起来组成的。

一、创建一个自定义的viewpager

先上完整的代码

package com.kcode.autoscrollviewpager.view;

import android.content.context;
import android.os.message;
import android.support.v4.view.viewpager;
import android.util.attributeset;
import android.util.log;
import android.view.motionevent;

import java.util.timer;
import java.util.timertask;

/**
 * created by caik on 2016/10/10.
 */

public class autoviewpager extends viewpager {

 private static final string tag = "autoviewpager";

 private int currentitem;

 private timer mtimer;
 private autotask mtask;

 private boolean isfirst = true;

 public autoviewpager(context context) {
  super(context);
 }

 public autoviewpager(context context, attributeset attrs) {
  super(context, attrs);
 }


 public void start(){
  if (mtimer == null) {
   mtimer = new timer();
  }
  mtimer.schedule(new autotask(),3000,3000);

 }

 private runnable runnable = new runnable() {
  @override
  public void run() {
   currentitem = getcurrentitem();
   if(currentitem == getadapter().getcount() - 1){
    currentitem = 0 ;
   }else {
    currentitem++ ;
   }
   setcurrentitem(currentitem);
  }
 };

 private autohandler mhandler = new autohandler();

 public void updatepointview(int size) {
  if (getparent() instanceof autoscrollviewpager){
   autoscrollviewpager pager = (autoscrollviewpager) getparent();
   pager.initpointview(size);
  }else {
   log.e(tag,"parent view not be autoscrollviewpager");
  }
 }

 public void onpageselected(int position) {
  autoscrollviewpager pager = (autoscrollviewpager) getparent();
  pager.updatepointview(position);
 }

 private class autotask extends timertask{

  @override
  public void run() {
   mhandler.post(runnable);
  }
 }

 private final static class autohandler extends android.os.handler{
  @override
  public void handlemessage(message msg) {
   super.handlemessage(msg);

  }
 }

 public void onstop(){
  //先取消定时器
  if (mtimer != null) {
   mtimer.cancel();
   mtimer = null;
  }
 }

 public void ondestroy(){
  onstop();
 }

 public void onresume(){
  start();
 }

 @override
 public boolean ontouchevent(motionevent ev) {
  switch (ev.getaction()){
   case motionevent.action_down:
    log.i(tag,"down");
    onstop();
    break;
   case motionevent.action_move:
    log.i(tag,"move");
    break;
   case motionevent.action_up:
    log.i(tag,"up");
    onresume();
    break;
  }
  return super.ontouchevent(ev);
 }
}

autoviewpager 继承至viewpager,我们通过timer来启动一个定时器。

public void start(){
  if (mtimer == null) {
   mtimer = new timer();
  }
  mtimer.schedule(new autotask(),3000,3000);

 }

 private runnable runnable = new runnable() {
  @override
  public void run() {
   currentitem = getcurrentitem();
   if(currentitem == getadapter().getcount() - 1){
    currentitem = 0 ;
   }else {
    currentitem++ ;
   }
   setcurrentitem(currentitem);
  }
 };

每隔三秒去更新一下页面。这样就能起到一个自己滚动的效果。

二、设置adapter

要实现无限循环,只要把adapter中的getcount()方法返回无限大,直接返回integer.max_value就可以了。

完整的adapter代码:

package com.kcode.autoscrollviewpager.view;

import android.content.context;
import android.support.v4.view.pageradapter;
import android.support.v4.view.viewpager;
import android.view.layoutinflater;
import android.view.view;
import android.view.viewgroup;
import android.widget.imageview;

import com.kcode.autoscrollviewpager.r;

import java.util.arraylist;
import java.util.list;

/**
 * created by caik on 2016/10/11.
 */

public abstract class baseviewpageradapter<t> extends pageradapter implements viewpager.onpagechangelistener{

 private list<t> data = new arraylist<>();

 private context mcontext;
 private autoviewpager mview;

 private onautoviewpageritemclicklistener listener;

 public baseviewpageradapter(list<t> t) {
  this.data = t;
 }

 public baseviewpageradapter(context context, autoviewpager viewpager) {
  this.mcontext = context;
  mview = viewpager;
  mview.setadapter(this);
  mview.addonpagechangelistener(this);
  mview.setcurrentitem(0);
 }


 public baseviewpageradapter(context context, autoviewpager viewpager,onautoviewpageritemclicklistener listener) {
  this.mcontext = context;
  mview = viewpager;
  this.listener = listener;
  mview.setadapter(this);
  mview.addonpagechangelistener(this);
  mview.setcurrentitem(0);
 }

 public baseviewpageradapter(context context, list<t> data,autoviewpager viewpager,onautoviewpageritemclicklistener listener) {
  this.mcontext = context;
  mview = viewpager;
  this.data = data;
  this.listener = listener;
  mview.setadapter(this);
  mview.addonpagechangelistener(this);
  mview.setcurrentitem(0);

  mview.start();
  mview.updatepointview(getrealcount());
 }

 public void add(t t){
  data.add(t);
  notifydatasetchanged();
  mview.updatepointview(getrealcount());
 }

 @override
 public int getcount() {
  return data == null ? 0 : integer.max_value;
 }

 public int getrealcount(){
  return data == null ? 0 : data.size();
 }

 @override
 public void destroyitem(viewgroup container, int position, object object) {
  container.removeview((imageview) object);
 }

 @override
 public object instantiateitem(viewgroup container, final int position) {
  imageview view = (imageview) layoutinflater.from(mcontext)
    .inflate(r.layout.imageview,container,false);
  view.setonclicklistener(new view.onclicklistener() {
   @override
   public void onclick(view view) {
    if (listener != null) {
     listener.onitemclick(position % getrealcount(),data.get(position % getrealcount()));
    }
   }
  });

  loadimage(view,position, data.get(position % getrealcount()));
  container.addview(view);

  return view;
 }

 public abstract void loadimage(imageview view,int position,t t);

 @override
 public boolean isviewfromobject(view view, object object) {
  return view == object;
 }

 @override
 public void onpagescrolled(int position, float positionoffset, int positionoffsetpixels) {

 }

 @override
 public void onpageselected(int position) {
  mview.onpageselected(position % getrealcount());
 }

 @override
 public void onpagescrollstatechanged(int state) {

 }

 public interface onautoviewpageritemclicklistener<t> {
  void onitemclick(int position,t t);
 }
}

这里我们使用了泛型,因为有时候我们可能只传一个url集合进来,也可能是对象集合,方便拓展。加载图片的方法也是一个抽象方法

public abstract void loadimage(imageview view,int position,t t);

因为每个app使用的图片加载框架都不一样,所以这里的加载就留个app自己实现。使用的时候创建adapter只要继承这里的baseviewpageradapter,然后重写loadimage(imageview view,int position,t t)方法,在这里进行图片的加载就行了。

如果你需不要底部的小圆点标示的话,这里就已经完成了。

使用的时候,直接使用

 <com.kcode.autoscrollviewpager.view.autoviewpager
  android:layout_width="match_parent"
  android:layout_height="200dp">
  
 </com.kcode.autoscrollviewpager.view.autoviewpager>

代替

 <android.support.v4.view.viewpager
  android:layout_width="match_parent"
  android:layout_height="match_parent">

 </android.support.v4.view.viewpager>

就可以了。需要底部的小圆点标示的话,继续往下

三、添加小圆点标示

需要添加小圆点标示的话。其实就是在viewpager上再加一层。我们新建一个view,继承至relativelayout

完整代码如下:

package com.kcode.autoscrollviewpager.view;

import android.content.context;
import android.util.attributeset;
import android.view.viewgroup;
import android.widget.imageview;
import android.widget.linearlayout;
import android.widget.relativelayout;

import com.kcode.autoscrollviewpager.r;

import static android.view.gravity.center;

/**
 * created by caik on 2016/10/17.
 */

public class autoscrollviewpager extends relativelayout{

 private autoviewpager mviewpager;

 private context mcontext;

 private linearlayout layout;

 public autoscrollviewpager(context context) {
  super(context);
  init(context);
 }

 public autoscrollviewpager(context context, attributeset attrs) {
  super(context, attrs);
  init(context);
 }

 private void init(context context){
  mcontext = context;
  mviewpager = new autoviewpager(context);
  layout = new linearlayout(mcontext);
  addview(mviewpager);
 }

 public autoviewpager getviewpager() {
  return mviewpager;
 }

 public void initpointview(int size){

  layout = new linearlayout(mcontext);
  for (int i = 0; i < size; i++) {
   imageview imageview = new imageview(mcontext);
   linearlayout.layoutparams params = new linearlayout.layoutparams(20,20);
   params.leftmargin = 8;
   params.gravity = center;
   imageview.setlayoutparams(params);
   if (i == 0) {
    imageview.setbackgroundresource(r.drawable.point_checked);
   }else {
    imageview.setbackgroundresource(r.drawable.point_normal);
   }

   layout.addview(imageview);
  }

  layoutparams layoutparams = new layoutparams(viewgroup.layoutparams.wrap_content, viewgroup.layoutparams.wrap_content);
  layoutparams.addrule(align_parent_bottom);
  layoutparams.addrule(align_parent_right);
  layoutparams.setmargins(12,20,12,20);
  layout.setlayoutparams(layoutparams);
  addview(layout);
 }

 public void updatepointview(int position) {
  int size = layout.getchildcount();
  for (int i = 0; i < size; i++) {
   imageview imageview = (imageview) layout.getchildat(i);
   if (i == position){
    imageview.setbackgroundresource(r.drawable.point_checked);
   }else {
    imageview.setbackgroundresource(r.drawable.point_normal);
   }

  }
 }

}

初始化的时候创建一个viewpager,一个linearlayout(用来放小圆点)

 public autoscrollviewpager(context context) {
  super(context);
  init(context);
 }

 public autoscrollviewpager(context context, attributeset attrs) {
  super(context, attrs);
  init(context);
 }

 private void init(context context){
  mcontext = context;
  mviewpager = new autoviewpager(context);
  layout = new linearlayout(mcontext);
  addview(mviewpager);
 }

再通过addview(mviewpager);添加。

需要准备两张图片,这里用shape进行绘制,shape的使用可以查看android shape使用.

初始化小圆点:

 public void initpointview(int size){

  layout = new linearlayout(mcontext);
  for (int i = 0; i < size; i++) {
   imageview imageview = new imageview(mcontext);
   linearlayout.layoutparams params = new linearlayout.layoutparams(20,20);
   params.leftmargin = 8;
   params.gravity = center;
   imageview.setlayoutparams(params);
   if (i == 0) {
    imageview.setbackgroundresource(r.drawable.point_checked);
   }else {
    imageview.setbackgroundresource(r.drawable.point_normal);
   }

   layout.addview(imageview);
  }

  layoutparams layoutparams = new layoutparams(viewgroup.layoutparams.wrap_content, viewgroup.layoutparams.wrap_content);
  layoutparams.addrule(align_parent_bottom);
  layoutparams.addrule(align_parent_right);
  layoutparams.setmargins(12,20,12,20);
  layout.setlayoutparams(layoutparams);
  addview(layout);
 }

更新小圆点:

 public void updatepointview(int position) {
  int size = layout.getchildcount();
  for (int i = 0; i < size; i++) {
   imageview imageview = (imageview) layout.getchildat(i);
   if (i == position){
    imageview.setbackgroundresource(r.drawable.point_checked);
   }else {
    imageview.setbackgroundresource(r.drawable.point_normal);
   }

  }
 }

带小圆点的使用以下控件

 <com.kcode.autoscrollviewpager.view.autoscrollviewpager
  android:id="@+id/viewpager"
  android:layout_width="match_parent"
  android:layout_height="220dp">

 </com.kcode.autoscrollviewpager.view.autoscrollviewpager>

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流。