打造史上最简单的广告轮播图Banner

来源:互联网 发布:淘宝销售宣传标语 编辑:程序博客网 时间:2024/05/22 07:52

个人警语: 一份耕耘,一份收获,努力越大,收获越多。动眼不动手都是假把式,没事多敲敲 , 收获的不只是更多!

转载请注明出处:http://blog.csdn.net/u014239140/article/details/52658486

我将之前写的知识点类文章全部删掉了,以后只提供项目干货,帮你快速的开发app 。介于是首次写干活类文章,表达不清楚多多包涵!O(∩_∩)O~

言归正传回到今天的主题上吧!之前想写个广告轮播是不是要考虑很多啊?那我们先来列下要做到兼容大多数的情况需要考虑的那些点:

  1.是否支持无限滚动,滚动方式类型(1.普通的正向滚动   到最后一页直接回第一页 2.正向滚动到最后一页后是否能够反向滚动回来)。

  2.是否支持用户按住时停止滚动 (处理事件类问题)。

  3 滚动的处理方式:使用普通的Timer做定时任务?还是使用线程池,安全类问题。

  3.是否支持点击图片给出回调方法(比如:你点击了第三张时候将点击的position返回回来)。

  4.追求效果的动画效果肯定少不了,那肯定就得添加10多种动画效果 供开发者使用吧!

  5.是否支持对图片ImageView.ScaleType的设置。

  6.是否支持indicator的显示,显示方式在代码中写死还是交给布局文件?

  7.都要支持什么类型的图片:本地?资源文件下?网络?当然这三种我们肯定都要支持才人性化叁。

 下面我就随便选择一个翻页来看下demo效果图吧:


好了,我们大致分析了下要考虑的点下面我们就动手躁起来吧!首先我们先来看下如何使用吧?然后在来看一步一怎么实现的。

第一步先来创建我们的布局文件吧,来吧字母走起。

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    tools:context="${relativePackage}.${activityClass}" >    <com.example.androidviewpageutil.View.ZZHViewPager        android:id="@+id/vip_show"        android:layout_width="match_parent"        android:layout_height="match_parent" />            <LinearLayout                android:id="@+id/ll_point"                android:layout_width="wrap_content"                android:layout_height="wrap_content"                android:layout_alignParentBottom="true"                android:layout_centerHorizontal="true"                android:layout_marginBottom="25dp"                android:orientation="horizontal"></LinearLayout></RelativeLayout>

布局文件中LinearLayout即为指示器的容器,这里就把指示器交给布局文件了,so,你的indicator是不是就可以谁便你放了,是不是很灵活。

第二步就是装数据 ,初始化控件,当然在项目中我们肯定少不了的一个接口来获取数据吧!这里就不写接口,就在百度上随便找了几个图片地址,将就用吧! 不要嫌我偷懒哦。这篇文章写下来会很长的。先来看下Activity吧。

private List<String> listurl = new ArrayList<String>();  //用于测试网络图片private ZZHViewPager viewPage; //自定义viewpageint[] mImg = { R.drawable.a, R.drawable.b, R.drawable.c, R.drawable.d };//用于测试资源图片   private int[] isdots = new int[]{R.drawable.login_point_selected, R.drawable.login_point};//准备好的指示器   private LinearLayout ll_point; //指示器容器   @Override   protected void onCreate(Bundle savedInstanceState) {       super.onCreate(savedInstanceState);       setContentView(R.layout.activity_main);       listurl.add("http://pic.qiantucdn.com/58pic/13/04/21/31D58PICVAH.jpg");       listurl.add("http://img0.imgtn.bdimg.com/it/u=1149180775,4094747667&fm=21&gp=0.jpg");       listurl.add("http://img.taopic.com/uploads/allimg/120625/201826-1206251Z15872.jpg");       listurl.add("http://pic15.nipic.com/20110630/6322714_111532514304_2.jpg");       viewPage = (ZZHViewPager)findViewById(R.id.vip_show);       ll_point = (LinearLayout)findViewById(R.id.ll_point);       initdata(TransitionEffect.RotateUp);   }   

第三步重点来了配置我们的banner了,一如既往代码走起。

private void initdata(TransitionEffect effect) {    viewPage.setTransitionEffect(effect);//添加动画效果。目前只提供了12种动画    ViewPageAdapter adapter = new ViewPageAdapter(this,viewPage,listurl);    adapter.setImageType(SelectImageType.NETWORK); //指定为网络图片    adapter.setImageScaleType(ImageView.ScaleType.FIT_XY);//设置图片缩放模式    adapter.showTips(ll_point, isdots);//设置显示指示器    adapter.startChangePage(6,false);//设置开始滚动  参数1:间隔毫秒数滚动 2.true即支持反向滚动,false则不支持。    viewPage.setAdapter(adapter);   //图片的点击事件 可供开发者处理    adapter.setOnclikListener(new ImageClickLstener() {      @Override      public void setImageOnclikliseter(int position,int allsize) {         Toast.makeText(getApplicationContext(), "position:"+position+"allsize:"+allsize, 1).show();      }   });}

我靠是不是很简单。其实这三部就已经完成上图的功能了。是不是很酷O(∩_∩)O~

咳咳,偷个懒内部封装的方法api就不在一一介绍了,你看上面的代码吧。我把注释都写的很清楚了!不清楚请邮箱联系...

到此我们的用法就结束了,是不是很想知道内部怎么搞的?来吧往下看。

    首先在布局文件看到我们的ZZHViewPage,这是什么鬼?其实就是我们继承ViewPage来写的一个自定义ViewPage。那自定义是什么鬼?这里就不在赘述基础了。其实你记住自定义的基本步骤就好办了。来吧说下步骤:

1.自定义属性。(就是在你Values文件下建立属性文件)

2.在继承的view的构造函数里获取属性值。

3.重写onMesure方法,当然测量不是必要操作。

4.重写onDraw方法(关键点)。清楚就这么四步走策略就可以了。

屁话整了一大堆我想说啥来着?哦哦整到自定义ViewPage了,我们要实现各种动画,各种事件以及预加载view是不是我们都应该在这里做啊?那是当然,来吧看代码:介于篇幅问题,方法我就不单独讲了,我在代码里把关注的方法打上注释

public class ZZHViewPager extends ViewPager{   public static final String TAG = "ViewPager";   private boolean mEnabled = true;   private boolean mFadeEnabled = false;   private boolean mOutlineEnabled = false;   public static int sOutlineColor = Color.WHITE;   private TransitionEffect mEffect = TransitionEffect.Standard;      private HashMap<Integer, Object> mObjs = new LinkedHashMap<Integer, Object>();   private static final float SCALE_MAX = 0.5f;   private static final float ZOOM_MAX = 0.5f;   private static final float ROT_MAX = 15.0f;   /**    * 是否正在触摸状态,用以防止触摸滑动和自动轮播冲突    */   public static boolean mIsTouching = false;   public enum TransitionEffect { //提供的12种动画      Standard,      Tablet,       CubeIn,      CubeOut,      FlipVertical,      FlipHorizontal,      Stack,      ZoomIn,      ZoomOut,      RotateUp,      RotateDown,      Accordion   }   private static final boolean API_11;   static {      API_11 = Build.VERSION.SDK_INT >= 11;   }   public ZZHViewPager(Context context) {      this(context, null);   }   @SuppressWarnings("incomplete-switch") //在构造函数中获取属性值   public ZZHViewPager(Context context, AttributeSet attrs) {      super(context, attrs);      setClipChildren(false);      TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.ViewPager);      int effect = ta.getInt(R.styleable.ViewPager_style, 0);      String[] transitions = getResources().getStringArray(R.array.jazzy_effects);      setTransitionEffect(TransitionEffect.valueOf(transitions[effect]));      setFadeEnabled(ta.getBoolean(R.styleable.ViewPager_fadeEnabled, false));      setOutlineEnabled(ta.getBoolean(R.styleable.ViewPager_outlineEnabled, false));      setOutlineColor(ta.getColor(R.styleable.ViewPager_outlineColor, Color.WHITE));      switch (mEffect) {      case Stack:      case ZoomOut:         setFadeEnabled(true);      }      ta.recycle();       Util.initImagLoad(context);   }   @Override   public boolean onTouchEvent(MotionEvent ev) { 用于处理是否要阻止滚动的冲突事件      switch (ev.getAction()) {         case MotionEvent.ACTION_DOWN:            mIsTouching = true;         case MotionEvent.ACTION_MOVE:            mIsTouching = true;            break;         case MotionEvent.ACTION_CANCEL:         case MotionEvent.ACTION_UP:            mIsTouching = false;            break;      }      return super.onTouchEvent(ev);   }   @Override   protected void onDetachedFromWindow() {  //取消定时任务 安全问题      super.onDetachedFromWindow();      if(ViewPageAdapter.scheduledexecutorservice != null && ViewPageAdapter.scheduledexecutorservice.isShutdown() == false){         ViewPageAdapter.scheduledexecutorservice.shutdown();      }      ViewPageAdapter.scheduledexecutorservice = null;   }   public void setTransitionEffect(TransitionEffect effect) {      mEffect = effect;   }   public void setPagingEnabled(boolean enabled) {      mEnabled = enabled;   }   public void setFadeEnabled(boolean enabled) {      mFadeEnabled = enabled;   }      public boolean getFadeEnabled() {      return mFadeEnabled;   }   public void setOutlineEnabled(boolean enabled) {      mOutlineEnabled = enabled;      wrapWithOutlines();   }   public void setOutlineColor(int color) {      sOutlineColor = color;   }   private void wrapWithOutlines() {      for (int i = 0; i < getChildCount(); i++) {         View v = getChildAt(i);         if (!(v instanceof OutlineContainer)) {            removeView(v);            super.addView(wrapChild(v), i);         }      }   }   private View wrapChild(View child) {      if (!mOutlineEnabled || child instanceof OutlineContainer) return child;      OutlineContainer out = new OutlineContainer(getContext());      out.setLayoutParams(generateDefaultLayoutParams());      child.setLayoutParams(new OutlineContainer.LayoutParams(            LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));      out.addView(child);      return out;   }   public void addView(View child) {      super.addView(wrapChild(child));   }   public void addView(View child, int index) {      super.addView(wrapChild(child), index);   }   public void addView(View child, LayoutParams params) {      super.addView(wrapChild(child), params);   }   public void addView(View child, int width, int height) {      super.addView(wrapChild(child), width, height);   }   public void addView(View child, int index, LayoutParams params) {      super.addView(wrapChild(child), index, params);   }   @Override   public boolean onInterceptTouchEvent(MotionEvent arg0) {      return mEnabled ? super.onInterceptTouchEvent(arg0) : false;   }   private State mState;   private int oldPage;   private View mLeft;   private View mRight;   private float mRot;   private float mTrans;   private float mScale;   private enum State {      IDLE,      GOING_LEFT,      GOING_RIGHT   }       private void logState(View v, String title) {      Log.v(TAG, title + ": ROT (" + ViewHelper.getRotation(v) + ", " +            ViewHelper.getRotationX(v) + ", " +            ViewHelper.getRotationY(v) + "), TRANS (" +            ViewHelper.getTranslationX(v) + ", " +            ViewHelper.getTranslationY(v) + "), SCALE (" +            ViewHelper.getScaleX(v) + ", " +             ViewHelper.getScaleY(v) + "), ALPHA " +            ViewHelper.getAlpha(v));   }   protected void animateScroll(int position, float positionOffset) {      if (mState != State.IDLE) {         mRot = (float)(1-Math.cos(2*Math.PI*positionOffset))/2*30.0f;         ViewHelper.setRotationY(this, mState == State.GOING_RIGHT ? mRot : -mRot);         ViewHelper.setPivotX(this, getMeasuredWidth()*0.5f);         ViewHelper.setPivotY(this, getMeasuredHeight()*0.5f);      }   }   protected void animateTablet(View left, View right, float positionOffset) {             if (mState != State.IDLE) {         if (left != null) {            manageLayer(left, true);            mRot = 30.0f * positionOffset;            mTrans = getOffsetXForRotation(mRot, left.getMeasuredWidth(),                  left.getMeasuredHeight());            ViewHelper.setPivotX(left, left.getMeasuredWidth()/2);            ViewHelper.setPivotY(left, left.getMeasuredHeight()/2);            ViewHelper.setTranslationX(left, mTrans);            ViewHelper.setRotationY(left, mRot);            logState(left, "Left");         }         if (right != null) {            manageLayer(right, true);            mRot = -30.0f * (1-positionOffset);            mTrans = getOffsetXForRotation(mRot, right.getMeasuredWidth(),                   right.getMeasuredHeight());            ViewHelper.setPivotX(right, right.getMeasuredWidth()*0.5f);            ViewHelper.setPivotY(right, right.getMeasuredHeight()*0.5f);            ViewHelper.setTranslationX(right, mTrans);            ViewHelper.setRotationY(right, mRot);            logState(right, "Right");         }      }   }   private void animateCube(View left, View right, float positionOffset, boolean in) {      if (mState != State.IDLE) {         if (left != null) {            manageLayer(left, true);            mRot = (in ? 90.0f : -90.0f) * positionOffset;            ViewHelper.setPivotX(left, left.getMeasuredWidth());            ViewHelper.setPivotY(left, left.getMeasuredHeight()*0.5f);            ViewHelper.setRotationY(left, mRot);         }         if (right != null) {            manageLayer(right, true);            mRot = -(in ? 90.0f : -90.0f) * (1-positionOffset);            ViewHelper.setPivotX(right, 0);            ViewHelper.setPivotY(right, right.getMeasuredHeight()*0.5f);            ViewHelper.setRotationY(right, mRot);         }      }   }   private void animateAccordion(View left, View right, float positionOffset) {      if (mState != State.IDLE) {         if (left != null) {            manageLayer(left, true);            ViewHelper.setPivotX(left, left.getMeasuredWidth());            ViewHelper.setPivotY(left, 0);            ViewHelper.setScaleX(left, 1-positionOffset);         }         if (right != null) {            manageLayer(right, true);            ViewHelper.setPivotX(right, 0);            ViewHelper.setPivotY(right, 0);            ViewHelper.setScaleX(right, positionOffset);         }      }   }   private void animateZoom(View left, View right, float positionOffset, boolean in) {      if (mState != State.IDLE) {         if (left != null) {            manageLayer(left, true);            mScale = in ? ZOOM_MAX + (1-ZOOM_MAX)*(1-positionOffset) :               1+ZOOM_MAX - ZOOM_MAX*(1-positionOffset);            ViewHelper.setPivotX(left, left.getMeasuredWidth()*0.5f);            ViewHelper.setPivotY(left, left.getMeasuredHeight()*0.5f);            ViewHelper.setScaleX(left, mScale);            ViewHelper.setScaleY(left, mScale);         }         if (right != null) {            manageLayer(right, true);            mScale = in ? ZOOM_MAX + (1-ZOOM_MAX)*positionOffset :               1+ZOOM_MAX - ZOOM_MAX*positionOffset;            ViewHelper.setPivotX(right, right.getMeasuredWidth()*0.5f);            ViewHelper.setPivotY(right, right.getMeasuredHeight()*0.5f);            ViewHelper.setScaleX(right, mScale);            ViewHelper.setScaleY(right, mScale);         }      }   }   private void animateRotate(View left, View right, float positionOffset, boolean up) {      if (mState != State.IDLE) {         if (left != null) {            manageLayer(left, true);            mRot = (up ? 1 : -1) * (ROT_MAX * positionOffset);            mTrans = (up ? -1 : 1) * (float) (getMeasuredHeight() - getMeasuredHeight()*Math.cos(mRot*Math.PI/180.0f));            ViewHelper.setPivotX(left, left.getMeasuredWidth()*0.5f);            ViewHelper.setPivotY(left, up ? 0 : left.getMeasuredHeight());            ViewHelper.setTranslationY(left, mTrans);            ViewHelper.setRotation(left, mRot);         }         if (right != null) {            manageLayer(right, true);            mRot = (up ? 1 : -1) * (-ROT_MAX + ROT_MAX*positionOffset);            mTrans = (up ? -1 : 1) * (float) (getMeasuredHeight() - getMeasuredHeight()*Math.cos(mRot*Math.PI/180.0f));            ViewHelper.setPivotX(right, right.getMeasuredWidth()*0.5f);            ViewHelper.setPivotY(right, up ? 0 : right.getMeasuredHeight());            ViewHelper.setTranslationY(right, mTrans);            ViewHelper.setRotation(right, mRot);         }      }   }   private void animateFlipHorizontal(View left, View right, float positionOffset, int positionOffsetPixels) {      if (mState != State.IDLE) {         if (left != null) {            manageLayer(left, true);            mRot = 180.0f * positionOffset;            if (mRot > 90.0f) {               left.setVisibility(View.INVISIBLE);            } else {               if (left.getVisibility() == View.INVISIBLE)                  left.setVisibility(View.VISIBLE);               mTrans = positionOffsetPixels;               ViewHelper.setPivotX(left, left.getMeasuredWidth()*0.5f);               ViewHelper.setPivotY(left, left.getMeasuredHeight()*0.5f);               ViewHelper.setTranslationX(left, mTrans);               ViewHelper.setRotationY(left, mRot);            }         }         if (right != null) {            manageLayer(right, true);            mRot = -180.0f * (1-positionOffset);            if (mRot < -90.0f) {               right.setVisibility(View.INVISIBLE);            } else {               if (right.getVisibility() == View.INVISIBLE)                  right.setVisibility(View.VISIBLE);               mTrans = -getWidth()-getPageMargin()+positionOffsetPixels;               ViewHelper.setPivotX(right, right.getMeasuredWidth()*0.5f);               ViewHelper.setPivotY(right, right.getMeasuredHeight()*0.5f);               ViewHelper.setTranslationX(right, mTrans);               ViewHelper.setRotationY(right, mRot);            }         }      }   }      private void animateFlipVertical(View left, View right, float positionOffset, int positionOffsetPixels) {      if(mState != State.IDLE) {         if (left != null) {            manageLayer(left, true);            mRot = 180.0f * positionOffset;            if (mRot > 90.0f) {               left.setVisibility(View.INVISIBLE);            } else {               if (left.getVisibility() == View.INVISIBLE)                  left.setVisibility(View.VISIBLE);               mTrans = positionOffsetPixels;               ViewHelper.setPivotX(left, left.getMeasuredWidth()*0.5f);               ViewHelper.setPivotY(left, left.getMeasuredHeight()*0.5f);               ViewHelper.setTranslationX(left, mTrans);               ViewHelper.setRotationX(left, mRot);            }         }         if (right != null) {            manageLayer(right, true);            mRot = -180.0f * (1-positionOffset);            if (mRot < -90.0f) {               right.setVisibility(View.INVISIBLE);            } else {               if (right.getVisibility() == View.INVISIBLE)                  right.setVisibility(View.VISIBLE);               mTrans = -getWidth()-getPageMargin()+positionOffsetPixels;               ViewHelper.setPivotX(right, right.getMeasuredWidth()*0.5f);               ViewHelper.setPivotY(right, right.getMeasuredHeight()*0.5f);               ViewHelper.setTranslationX(right, mTrans);               ViewHelper.setRotationX(right, mRot);            }         }      }   }   protected void animateStack(View left, View right, float positionOffset, int positionOffsetPixels) {            if (mState != State.IDLE) {         if (right != null) {            manageLayer(right, true);            mScale = (1-SCALE_MAX) * positionOffset + SCALE_MAX;            mTrans = -getWidth()-getPageMargin()+positionOffsetPixels;            ViewHelper.setScaleX(right, mScale);            ViewHelper.setScaleY(right, mScale);            ViewHelper.setTranslationX(right, mTrans);         }         if (left != null) {            left.bringToFront();         }      }   }   private void manageLayer(View v, boolean enableHardware) {      if (!API_11) return;      int layerType = enableHardware ? View.LAYER_TYPE_HARDWARE : View.LAYER_TYPE_NONE;      if (layerType != v.getLayerType())         v.setLayerType(layerType, null);   }   private void disableHardwareLayer() {      if (!API_11) return;      View v;      for (int i = 0; i < getChildCount(); i++) {         v = getChildAt(i);         if (v.getLayerType() != View.LAYER_TYPE_NONE)            v.setLayerType(View.LAYER_TYPE_NONE, null);      }   }   private Matrix mMatrix = new Matrix();   private Camera mCamera = new Camera();   private float[] mTempFloat2 = new float[2];   protected float getOffsetXForRotation(float degrees, int width, int height) {      mMatrix.reset();      mCamera.save();      mCamera.rotateY(Math.abs(degrees));      mCamera.getMatrix(mMatrix);      mCamera.restore();      mMatrix.preTranslate(-width * 0.5f, -height * 0.5f);      mMatrix.postTranslate(width * 0.5f, height * 0.5f);      mTempFloat2[0] = width;      mTempFloat2[1] = height;      mMatrix.mapPoints(mTempFloat2);      return (width - mTempFloat2[0]) * (degrees > 0.0f ? 1.0f : -1.0f);   }   protected void animateFade(View left, View right, float positionOffset) {      if (left != null) {         ViewHelper.setAlpha(left, 1-positionOffset);      }      if (right != null) {         ViewHelper.setAlpha(right, positionOffset);      }   }   protected void animateOutline(View left, View right) {      if (!(left instanceof OutlineContainer))         return;      if (mState != State.IDLE) {         if (left != null) {            manageLayer(left, true);            ((OutlineContainer)left).setOutlineAlpha(1.0f);         }         if (right != null) {            manageLayer(right, true);            ((OutlineContainer)right).setOutlineAlpha(1.0f);         }      } else {         if (left != null)            ((OutlineContainer)left).start();         if (right != null)            ((OutlineContainer)right).start();      }   }   @Override   public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {      if (mState == State.IDLE && positionOffset > 0) {         oldPage = getCurrentItem();         mState = position == oldPage ? State.GOING_RIGHT : State.GOING_LEFT;      }      boolean goingRight = position == oldPage;                 if (mState == State.GOING_RIGHT && !goingRight)         mState = State.GOING_LEFT;      else if (mState == State.GOING_LEFT && goingRight)         mState = State.GOING_RIGHT;      float effectOffset = isSmall(positionOffset) ? 0 : positionOffset;      //    mLeft = getChildAt(position);//    mRight = getChildAt(position+1);      mLeft = findViewFromObject(position);      mRight = findViewFromObject(position+1);            if (mFadeEnabled)         animateFade(mLeft, mRight, effectOffset);      if (mOutlineEnabled)         animateOutline(mLeft, mRight);            switch (mEffect) {      case Standard:         break;      case Tablet:         animateTablet(mLeft, mRight, effectOffset);         break;      case CubeIn:         animateCube(mLeft, mRight, effectOffset, true);         break;      case CubeOut:         animateCube(mLeft, mRight, effectOffset, false);         break;      case FlipVertical:         animateFlipVertical(mLeft, mRight, positionOffset, positionOffsetPixels);         break;      case FlipHorizontal:         animateFlipHorizontal(mLeft, mRight, effectOffset, positionOffsetPixels);      case Stack:         animateStack(mLeft, mRight, effectOffset, positionOffsetPixels);         break;      case ZoomIn:         animateZoom(mLeft, mRight, effectOffset, true);         break;      case ZoomOut:         animateZoom(mLeft, mRight, effectOffset, false);         break;      case RotateUp:         animateRotate(mLeft, mRight, effectOffset, true);         break;      case RotateDown:         animateRotate(mLeft, mRight, effectOffset, false);         break;      case Accordion:         animateAccordion(mLeft, mRight, effectOffset);         break;      }      super.onPageScrolled(position, positionOffset, positionOffsetPixels);      if (effectOffset == 0) {         disableHardwareLayer();         mState = State.IDLE;      }   }   private boolean isSmall(float positionOffset) {      return Math.abs(positionOffset) < 0.0001;   }      public void setObjectForPosition(Object obj, int position) {      mObjs.put(Integer.valueOf(position), obj);   }      public View findViewFromObject(int position) {      Object o = mObjs.get(Integer.valueOf(position));      if (o == null) {         return null;      }      PagerAdapter a = getAdapter();      View v;      for (int i = 0; i < getChildCount(); i++) {         v = getChildAt(i);         if (a.isViewFromObject(v, o))            return v;      }      return null;   }   }

到这我们的自定义ViewPage就结束了。下面来看我们的PageAdapter呢 ! 要实支持那么多功能adapter的逻辑可定不会简单。同上解释在代码里。

/** * @author zhengzaihong */public class ViewPageAdapter extends PagerAdapter{   private Context context;   private ImageView[] imageviews;   private int mImg[];   private List<String> listUrl;   private ZZHViewPager viewpage;   private SelectImageType enumtype = SelectImageType.NETWORK;;   private ImageView.ScaleType scaleType;   private boolean isreverse=false;   private boolean isend=false;   private ImageView tips[];   private ViewGroup viewGroup;   private int[] dots;   private int beginPosition;   private int returnPosition=0;   private int allsize=0;   public Timer timer = new Timer();   //这里采用线程池  原因:如果你采用的TimerTask方式 就得考虑两点问题:1 如果采用Timer Timer只会创建一个线程并且不会捕获异常,因此当TimerTask抛出未检查的异常时将会终止Timer   // 这种情形下,Timer将因无法恢复线程执行行,而是错误地促使整个Timer被取消了,那么整个定时任务就无法调度来。   //SingleThreadScheduledExecutor不会有这些问题,当线程池中的唯一线程因特殊原因挂掉,线程池会自动开启一个新线程,保证定时任务继续。   public static ScheduledExecutorService scheduledexecutorservice = Executors.newSingleThreadScheduledExecutor();;   /**    * @param enumtype 图片来源类型   NETWORK:网络图片,APPID:资源图片id类型,LOCATION:手机存储图片    * 此方法一定是在setadapter()之前调用  否则会报错    */   public enum SelectImageType {      NETWORK,      APPID,      LOCATION   }   public void setImageType(SelectImageType enumtype){      this.enumtype=enumtype;      initImageView();   }   /**    *@param scaleType 图片的缩放模式(不建议使用该方法)     */   public void setImageScaleType(ImageView.ScaleType scaleType){      this.scaleType=scaleType;      initImageView();   }   /**    * @see 是否支持显示提示点    * @param viewGroup 装提示点的容器  此处采用的是linerlayout 可方便用户自定义 提示点的位置在  完全交给用户在xml文件中配置    * @param dots 装有选中和没选中的两张图片    */   public void showTips(ViewGroup viewGroup,int dots[]){      this.viewGroup=viewGroup;      this.dots=dots;      if(enumtype==SelectImageType.NETWORK ||enumtype==SelectImageType.LOCATION){         creatDot(listUrl.size());      }else if(enumtype==SelectImageType.APPID){         creatDot(mImg.length);      }   }   /**    * @param howlong 设置多少秒翻页    * @param isreverse 设置是否顺序轮播 true表示在轮播到最后一页时倒着轮播回来  false表示每次轮播完毕都从开始位置起。    */   public void startChangePage(int howlong,final boolean isreverse){      this.isreverse=isreverse;      scheduledexecutorservice.scheduleAtFixedRate(new Runnable() {         @Override         public void run() {            handler.sendEmptyMessage(0X1515);         }      },howlong*1000,howlong*1000, TimeUnit.MILLISECONDS);   }   //这段逻辑复杂了点 劲量看吧。此处待优化,后期处理。。   Handler handler = new Handler(){      public void handleMessage(android.os.Message msg) {         if(!(ZZHViewPager.mIsTouching)){            if(isreverse){               if(beginPosition==(allsize-1)){                  isend=true;                  beginPosition--;               }else{                  if(beginPosition==0){                     beginPosition++;                     isend=false;                  }else{                     if(isend){                        beginPosition--;                     }else{                        beginPosition++;                     }                  }               }            }else{               beginPosition++;            }            int position = 0;            if(enumtype==SelectImageType.NETWORK ||enumtype==SelectImageType.LOCATION){               position=beginPosition % listUrl.size();            }else if(enumtype==SelectImageType.APPID){               position=beginPosition % mImg.length;            }            if(isreverse){               if(beginPosition==allsize){                  beginPosition = returnPosition+1;               }            }            viewpage.setCurrentItem(position);         }      };   };   /**    * @param context 上下文    * @param viewpage viewpage传进来    * @param mImg 资源图片id    */   public ViewPageAdapter(Context context,ZZHViewPager viewpage,int mImg[]){      this.context=context;      this.viewpage=viewpage;      this.mImg=mImg;   }   /**    * @param context 上下文    * @param viewpage viewpage传进来    * @param listUrl 网络图片地址集合    */   public ViewPageAdapter(Context context,ZZHViewPager viewpage,List<String> listUrl){      this.context=context;      this.viewpage=viewpage;      this.listUrl=listUrl;   }      private void initImageView(){      int length=0;      if(enumtype==SelectImageType.NETWORK ||enumtype==SelectImageType.LOCATION){         length=listUrl.size();      }else if(enumtype==SelectImageType.APPID){         length=mImg.length;      }      allsize =length;      imageviews = new ImageView[length];      for(int i=0;i<length;i++){         ImageView imageView = new ImageView(context);         if( scaleType instanceof ImageView.ScaleType && scaleType !=null){            imageView.setScaleType(scaleType);         }         imageView.setOnClickListener(new OnClickListener() {            @Override            public void onClick(View v) {               listener.setImageOnclikliseter(returnPosition,allsize);            }         });         imageviews[i]=imageView;      }   }   @Override   public Object instantiateItem(ViewGroup container, final int position) {      ImageView imageView =imageviews[position];      beginPosition=position-1;      try{         switch (enumtype) {         case NETWORK:            Util.drowNetWorkImage(listUrl.get(position), imageView);            break;         case APPID:            imageView.setBackgroundResource(mImg[position]);//如果是资源图片就直接设置背景了            break;         case LOCATION:            Util.drowLocationImage(listUrl.get(position), imageView);            break;         }      }catch(Exception e){         e.printStackTrace();      }      container.addView(imageView, LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);      viewpage.setObjectForPosition(imageView, position);      return imageView;   }   @Override   public void destroyItem(ViewGroup container, int position, Object obj) {      container.removeView(viewpage.findViewFromObject(position));   }   @Override   public int getCount() {      if(enumtype==SelectImageType.NETWORK ||enumtype==SelectImageType.LOCATION){         return listUrl.size();      }else if(enumtype==SelectImageType.APPID){         return mImg.length;      }      return 0;   }   @Override   public boolean isViewFromObject(View view, Object obj) {      if (view instanceof OutlineContainer) {         return ((OutlineContainer) view).getChildAt(0) == obj;      } else {         return view == obj;      }   }   /* * 初始化 提示点数量 */    private void creatDot(int size){       setViewPageChangeListener();       tips = new ImageView[size];       for (int i = 0; i < tips.length; i++) {           ImageView imageView = new ImageView(context);           imageView.setLayoutParams(new ViewGroup.LayoutParams(15, 15));           tips[i] = imageView;           if (i == 0) {               tips[i].setBackgroundResource(dots[0]);           } else {               tips[i].setBackgroundResource(dots[1]);           }           LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(new ViewGroup.LayoutParams(                   ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));           layoutParams.leftMargin = 8;           layoutParams.rightMargin = 8;           viewGroup.addView(imageView, layoutParams);       }     }     @SuppressWarnings("deprecation")   private void setViewPageChangeListener() {        viewpage.setOnPageChangeListener(new OnPageChangeListener() {         @Override         public void onPageSelected(int position) {             setTipsBackgroud(position, dots);             returnPosition=position;         }         @Override         public void onPageScrolled(int arg0, float arg1, int arg2) {         }         @Override         public void onPageScrollStateChanged(int position) {         }      });   }   /*     * 让图片和提示点联动     */   private  void setTipsBackgroud(int position, int dot[]) {           for (int i = 0; i < tips.length; i++) {               if (i == position) {                   tips[i].setBackgroundResource(dot[0]);               } else {                   tips[i].setBackgroundResource(dot[1]);               }           }       }   private ImageClickLstener listener;   /**    * @see 为每张图片添加点击事件 返回当前的图片位置 和总的图片数    * @param 传进来 ImageClickLstener监听对象    */   public void setOnclikListener(ImageClickLstener listener){      this.listener=listener;   }   public interface ImageClickLstener{      void setImageOnclikliseter(int returnPosition,int allsize);   }}

好了真正的核心代码已经完成了,仔细看的童鞋们是不发现在上面分析的7点在代码里都作出了解释呢?

接下来看下另外两个辅助类吧。首先上我们的动画辅助类!

public class OutlineContainer extends FrameLayout implements Animatable {   private Paint mOutlinePaint;      private boolean mIsRunning = false;    private long mStartTime;   private float mAlpha = 1.0f;   private static final long ANIMATION_DURATION = 500;   private static final long FRAME_DURATION = 1000 / 60;   private final Interpolator mInterpolator = new Interpolator() {      public float getInterpolation(float t) {         t -= 1.0f;         return t * t * t + 1.0f;      }   };   public OutlineContainer(Context context) {      super(context);      init();   }   public OutlineContainer(Context context, AttributeSet attrs) {      super(context, attrs);      init();   }   public OutlineContainer(Context context, AttributeSet attrs, int defStyle) {      super(context, attrs, defStyle);      init();   }   private void init() {      mOutlinePaint = new Paint();      mOutlinePaint.setAntiAlias(true);      mOutlinePaint.setStrokeWidth(Util.dpToPx(getResources(), 2));      mOutlinePaint.setColor(getResources().getColor(R.color.holo_blue));      mOutlinePaint.setStyle(Style.STROKE);      int padding = Util.dpToPx(getResources(), 10);      setPadding(padding, padding, padding, padding);   }   @Override   protected void dispatchDraw(Canvas canvas) {      super.dispatchDraw(canvas);      int offset = Util.dpToPx(getResources(), 5);      if (mOutlinePaint.getColor() != ZZHViewPager.sOutlineColor) {         mOutlinePaint.setColor(ZZHViewPager.sOutlineColor);      }      mOutlinePaint.setAlpha((int)(mAlpha * 255));      Rect rect = new Rect(offset, offset, getMeasuredWidth()-offset, getMeasuredHeight()-offset);      canvas.drawRect(rect, mOutlinePaint);   }      public void setOutlineAlpha(float alpha) {      mAlpha = alpha;   }   @Override   public boolean isRunning() {      return mIsRunning;   }   @Override   public void start() {      if (mIsRunning)         return;      mIsRunning = true;      mStartTime = AnimationUtils.currentAnimationTimeMillis();        post(mUpdater);   }   @Override   public void stop() {      if (!mIsRunning)         return;      mIsRunning = false;   }      private final Runnable mUpdater = new Runnable() {        @Override        public void run() {            long now = AnimationUtils.currentAnimationTimeMillis();            long duration = now - mStartTime;            if (duration >= ANIMATION_DURATION) {                mAlpha = 0.0f;                invalidate();                stop();                return;            } else {               mAlpha = mInterpolator.getInterpolation(1 - duration / (float) ANIMATION_DURATION);                invalidate();            }            postDelayed(mUpdater, FRAME_DURATION);        }    };}

好了动画辅助类完了,然后是图片加载类了,这里就没用自己动手写图片加载类了,偷个懒下面是利用第三方 Universal-Image-Loader做了个超简单的util,更多的配置请查阅官网。

public class Util {   public static int dpToPx(Resources res, int dp) {      return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, res.getDisplayMetrics());   }      public static void initImagLoad(Context context){      File cacheDir = StorageUtils.getOwnCacheDirectory(context, "imageloader/Cache");      ImageLoader imageLoader = ImageLoader.getInstance();           if (!imageLoader.isInited()) {               ImageLoaderConfiguration configuration = new ImageLoaderConfiguration.Builder(context)                  .defaultDisplayImageOptions(new DisplayImageOptions.Builder().build())                 //   .discCache(new UnlimitedDiscCache(cacheDir))//自定义缓存路径                  .build();               imageLoader.init(configuration);           }   }       public static void drowLocationImage(String uri, ImageView image) {       displayImage("file://"+uri, image);    }        public static void drowNetWorkImage(String uri, ImageView image) {       displayImage(uri, image);    }       public static void displayImage(String uri, ImageView imageView) {      displayImage(uri, imageView, new SimpleImageLoadingListener());   }   public static void displayImage(String uri, ImageView image, DisplayImageOptions options) {      ImageLoader imageLoader = ImageLoader.getInstance();      imageLoader.displayImage(uri, image, options);   }   public static void displayImage(String uri, ImageView imageView, ImageLoadingListener imageLoadingListener) {      displayImage(uri, imageView, imageLoadingListener, false);   }   public static void displayImage(String uri, ImageView imageView, ImageLoadingListener imageLoadingListener,         boolean isFadeIn) {      ImageLoader imageLoader = ImageLoader.getInstance();      if (!TextUtils.isEmpty(uri) && (uri.startsWith("/mnt/sdcard") || uri.startsWith("/storage"))) {         uri = "file://".concat(uri);      }      imageLoader.displayImage(uri, imageView, imageLoadingListener);   }   public static void displayImage(String uri, ImageView imageView, boolean isFadeIn) {      displayImage(uri, imageView, new SimpleImageLoadingListener() {      }, isFadeIn);   }
好了辅助类也完了。还有个就是我们的属性文件了,下面给出.xml文件

<declare-styleable name="ViewPager">    <attr name="style">        <enum name="standard" value="0" />        <enum name="tablet" value="1" />        <enum name="cubein" value="2" />        <enum name="cubeout" value="3" />        <enum name="flipvertical" value="4" />        <enum name="fliphorizontal" value="5" />        <enum name="stack" value="6" />        <enum name="zoomin" value="7" />        <enum name="zoomout" value="8" />        <enum name="rotateup" value="9" />        <enum name="rotatedown" value="10" />        <enum name="accordion" value="11" />    </attr>    <attr name="fadeEnabled" format="boolean" />    <attr name="outlineEnabled" format="boolean" />    <attr name="outlineColor" format="color|reference" /></declare-styleable>
      说下我们定义属性文件还是规范下呀。虽然attrs在底部是给你包装好了<declare-styleable> 标签,虽然可以不用写这玩意,我们还是要做到规范化,也把属性模块化了,很清楚哪些属性是哪个的,公共的你可以提出来。看也一目了然。不然多了你会昏的.......

     好了到此文章就全部结束了。谢谢观读!欢迎指出待优化的部分。谢谢O(∩_∩)O~

本文用到的了nineoldandroids-2.4.0和universal-image-loader-1.9.2两个jar夹包 可以去百度下载或者点击下面链接http://download.csdn.net/detail/u014239140/9639219

2 0