Android 自定义轮播图片控件

shanxin 8年前
   <h3><strong>效果图</strong></h3>    <p>直接先上效果图。</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/1d236db5c503c799818870d500c99fce.gif"></p>    <p style="text-align:center">轮播图.gif</p>    <h3><strong>实现原理</strong></h3>    <p>要完成一个轮播图片,首先想到的应该是使用ViewPager来实现。ViewPager已经有了滑动的功能,我们只要让它自己滚动。再加上下方的小圆点就行了。所以我们本次的自定义控件就是由ViewPager和LinearLayout叠加起来组成的。</p>    <h3><strong>创建一个自定义的ViewPager</strong></h3>    <p>先上完整的代码</p>    <pre>  <code class="language-java">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);      }  }</code></pre>    <p>AutoViewPager 继承至ViewPager,我们通过Timer来启动一个定时器。</p>    <pre>  <code class="language-java">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);          }      };</code></pre>    <p>每隔三秒去更新一下页面。这样就能起到一个自己滚动的效果。</p>    <h3><strong>设置Adapter</strong></h3>    <p>要实现无限循环,只要把Adapter中的 getCount() 方法返回无限大,直接返回 Integer.MAX_VALUE 就可以了。</p>    <p>完整的Adapter代码:</p>    <pre>  <code class="language-java">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);      }  }</code></pre>    <p>这里我们使用了泛型,因为有时候我们可能只传一个url集合进来,也可能是对象集合,方便拓展。加载图片的方法也是一个抽象方法</p>    <pre>  <code class="language-java">public abstract void loadImage(ImageView view,int position,T t);</code></pre>    <p>因为每个App使用的图片加载框架都不一样,所以这里的加载就留个App自己实现。使用的时候创建Adapter只要继承这里的BaseViewPagerAdapter,然后重写 loadImage(ImageView view,int position,T t) 方法,在这里进行图片的加载就行了。</p>    <p>如果你需不要底部的小圆点标示的话,这里就已经完成了。使用的时候,直接使用</p>    <pre>  <code class="language-java"><com.kcode.autoscrollviewpager.view.AutoViewPager          android:layout_width="match_parent"          android:layout_height="200dp">        </com.kcode.autoscrollviewpager.view.AutoViewPager></code></pre>    <p>代替</p>    <pre>  <code class="language-java"><android.support.v4.view.ViewPager          android:layout_width="match_parent"          android:layout_height="match_parent">        </android.support.v4.view.ViewPager></code></pre>    <p>就可以了。需要底部的小圆点标示的话,继续往下</p>    <h3><strong>添加小圆点标示</strong></h3>    <p>需要添加小圆点标示的话。其实就是在ViewPager上再加一层。我们新建一个View,继承至 RelativeLayout</p>    <p>完整代码如下:</p>    <pre>  <code class="language-java">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);              }            }      }    }</code></pre>    <p>初始化的时候创建一个ViewPager,一个LinearLayout(用来放小圆点)</p>    <pre>  <code class="language-java">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);      }</code></pre>    <p>再通过 addView(mViewPager); 添加。</p>    <p>需要准备两张图片,这里用Shape进行绘制,Shape的使用可以查看Android Shape使用.</p>    <p>初始化小圆点:</p>    <pre>  <code class="language-java">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);      }</code></pre>    <p>更新小圆点:</p>    <pre>  <code class="language-java">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);              }            }      }</code></pre>    <p>带小圆点的使用以下控件</p>    <pre>  <code class="language-java"><com.kcode.autoscrollviewpager.view.AutoScrollViewPager          android:id="@+id/viewPager"          android:layout_width="match_parent"          android:layout_height="220dp">        </com.kcode.autoscrollviewpager.view.AutoScrollViewPager></code></pre>    <p>以上就是主要的代码了。</p>    <h3> </h3>    <p> </p>    <p>来自:http://www.jianshu.com/p/5c47cb6afe0f</p>    <p> </p>