浏览代码

Support set Indicator Style.
add DashIndicatorView.

张攀 5 年之前
父节点
当前提交
cfa33b4dc8

+ 0 - 149
app/src/main/java/com/example/zhpan/circleviewpager/RectangleIndicatorView.java

@@ -1,149 +0,0 @@
-package com.example.zhpan.circleviewpager;
-
-import android.content.Context;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Paint;
-import android.util.AttributeSet;
-import android.view.View;
-
-import com.zhpan.bannerview.enums.IndicatorSlideMode;
-import com.zhpan.bannerview.indicator.IIndicator;
-import com.zhpan.bannerview.utils.DpUtils;
-
-/**
- * Created by zhpan on 2017/12/6.
- */
-public class RectangleIndicatorView extends View implements IIndicator {
-    private int normalColor;
-    private int checkedColor;
-    private Paint mPaint;
-    private int mPageSize;
-    private float sliderWidth;
-    private float sliderHeight;
-    private int currentPosition;
-    private float mMargin;
-    private IndicatorSlideMode mSlideStyle = IndicatorSlideMode.SMOOTH;
-    private float slideProgress;
-
-    public RectangleIndicatorView(Context context) {
-        this(context, null);
-    }
-
-    public RectangleIndicatorView(Context context, AttributeSet attrs) {
-        this(context, attrs, 0);
-    }
-
-    public RectangleIndicatorView(Context context, AttributeSet attrs, int defStyleAttr) {
-        super(context, attrs, defStyleAttr);
-        normalColor = Color.parseColor("#8C18171C");
-        checkedColor = Color.parseColor("#8C6C6D72");
-        mPaint = new Paint();
-        mPaint.setColor(normalColor);
-        mPaint.setAntiAlias(true);
-        sliderWidth = DpUtils.dp2px(context, 5);
-        sliderHeight = sliderWidth / 2;
-        mMargin = sliderWidth;
-    }
-
-    @Override
-    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
-        super.onSizeChanged(w, h, oldw, oldh);
-    }
-
-    @Override
-    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
-        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
-        setMeasuredDimension((int) ((mPageSize - 1) * mMargin + sliderWidth * mPageSize),
-                (int) (sliderHeight));
-    }
-
-    @Override
-    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
-        super.onLayout(changed, left, top, right, bottom);
-    }
-
-    @Override
-    protected void onDraw(Canvas canvas) {
-        super.onDraw(canvas);
-        mPaint.setColor(normalColor);
-        for (int i = 0; i < mPageSize; i++) {
-            mPaint.setColor(normalColor);
-            canvas.drawRect(i * (sliderWidth) + i * +mMargin, 0, i * (sliderWidth) + i * +mMargin + sliderWidth, sliderHeight, mPaint);
-        }
-        drawSliderStyle(canvas);
-    }
-
-    @Override
-    public void onPageSelected(int position) {
-        if (mSlideStyle == IndicatorSlideMode.NORMAL) {
-            this.currentPosition = position;
-            invalidate();
-        }
-    }
-
-    @Override
-    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
-        if (mSlideStyle == IndicatorSlideMode.SMOOTH) {
-            slideProgress = positionOffset;
-            currentPosition = position;
-            invalidate();
-        }
-    }
-
-    @Override
-    public void onPageScrollStateChanged(int state) {
-
-    }
-
-    private void drawSliderStyle(Canvas canvas) {
-        switch (mSlideStyle) {
-            case NORMAL:
-                slideProgress = 0;
-            case SMOOTH:
-                slideProgress = (currentPosition == mPageSize - 1) ? 0 : slideProgress;
-                break;
-        }
-        mPaint.setColor(checkedColor);
-        canvas.drawRect(currentPosition * (sliderWidth) + currentPosition * +mMargin + (sliderWidth + mMargin) * slideProgress, 0, currentPosition * (sliderWidth) + currentPosition * +mMargin + (sliderWidth + mMargin) * slideProgress + sliderWidth, sliderHeight, mPaint);
-    }
-
-
-    public RectangleIndicatorView setNormalColor(int normalColor) {
-        this.normalColor = normalColor;
-        return this;
-    }
-
-    public RectangleIndicatorView setCheckedColor(int checkedColor) {
-        this.checkedColor = checkedColor;
-        return this;
-    }
-
-    public RectangleIndicatorView setPageSize(int pageSize) {
-        this.mPageSize = pageSize;
-        requestLayout();
-        return this;
-    }
-
-    public RectangleIndicatorView setIndicatorMargin(float margin) {
-        if (margin > 0) {
-            this.mMargin = DpUtils.dp2px(getContext(), margin);
-        }
-        return this;
-    }
-
-    public RectangleIndicatorView setSliderWidth(float sliderWidth) {
-        this.sliderWidth = DpUtils.dp2px(getContext(), sliderWidth);
-        return this;
-    }
-
-    public RectangleIndicatorView setSliderHeight(float sliderHeight) {
-        this.sliderHeight = DpUtils.dp2px(getContext(), sliderHeight);
-        return this;
-    }
-
-    public RectangleIndicatorView setSlideStyle(IndicatorSlideMode slideStyle) {
-        mSlideStyle = slideStyle;
-        return this;
-    }
-}

+ 9 - 6
app/src/main/java/com/example/zhpan/circleviewpager/activity/CustomIndicatorActivity.java

@@ -5,7 +5,7 @@ import androidx.appcompat.app.AppCompatActivity;
 import android.os.Bundle;
 
 import com.example.zhpan.circleviewpager.R;
-import com.example.zhpan.circleviewpager.RectangleIndicatorView;
+import com.zhpan.bannerview.indicator.DashIndicatorView;
 import com.example.zhpan.circleviewpager.viewholder.SlideModeViewHolder;
 import com.zhpan.bannerview.BannerViewPager;
 
@@ -25,13 +25,16 @@ public class CustomIndicatorActivity extends AppCompatActivity {
         setTitle(getString(R.string.custom_indicator_view));
         BannerViewPager<String, SlideModeViewHolder> viewPager = findViewById(R.id.banner_view);
         List<String> list = Arrays.asList(picUrls);
-        RectangleIndicatorView indicatorView = new RectangleIndicatorView(this);
-        indicatorView.setPageSize(list.size()).setSliderWidth(8f).setSliderHeight(3.5f)
-                .setIndicatorMargin(5f).setCheckedColor(getResources().getColor(R.color.colorAccent))
-                .setNormalColor(getResources().getColor(R.color.colorPrimary));
+        DashIndicatorView indicatorView = new DashIndicatorView(this);
+        indicatorView.setPageSize(list.size());
+        indicatorView.setIndicatorWidth(8f,8f);
+        indicatorView.setSliderHeight(3.5f);
+        indicatorView.setIndicatorGap(5f);
+        indicatorView.setCheckedColor(getResources().getColor(R.color.colorAccent));
+        indicatorView.setNormalColor(getResources().getColor(R.color.colorPrimary));
         viewPager.setAutoPlay(false).setCanLoop(true)
                 .setRoundCorner(15f)
-                .setIndicatorView(indicatorView)
+                .setCustomIndicatorView(indicatorView)
                 .setHolderCreator(SlideModeViewHolder::new).create(list);
     }
 }

+ 5 - 2
app/src/main/java/com/example/zhpan/circleviewpager/activity/IndicatorSlideModeActivity.java

@@ -11,6 +11,7 @@ import com.example.zhpan.circleviewpager.R;
 import com.example.zhpan.circleviewpager.viewholder.SlideModeViewHolder;
 import com.zhpan.bannerview.BannerViewPager;
 import com.zhpan.bannerview.enums.IndicatorSlideMode;
+import com.zhpan.bannerview.enums.IndicatorStyle;
 
 import java.util.Arrays;
 import java.util.List;
@@ -31,9 +32,11 @@ public class IndicatorSlideModeActivity extends AppCompatActivity {
         mList = Arrays.asList(picUrls);
         mViewPager.setAutoPlay(true).setCanLoop(true)
                 .setRoundCorner(5f)
-                .setIndicatorGap(50f)
+                .setIndicatorGap(7f)
                 .setScrollDuration(1000)
-                .setIndicatorRadius(6f, 8f)
+                .setIndicatorStyle(IndicatorStyle.CIRCLE)
+//                .setIndicatorStyle(IndicatorStyle.DASH)
+                .setIndicatorWidth(12f)
                 .setHolderCreator(SlideModeViewHolder::new)
                 .setIndicatorColor(Color.parseColor("#935656"), Color.parseColor("#CCFF4C39")).create(mList);
     }

+ 117 - 50
bannerview/src/main/java/com/zhpan/bannerview/BannerViewPager.java

@@ -19,7 +19,10 @@ import android.view.View;
 import android.widget.FrameLayout;
 import android.widget.RelativeLayout;
 
+import com.zhpan.bannerview.enums.IndicatorStyle;
+import com.zhpan.bannerview.indicator.BaseIndicatorView;
 import com.zhpan.bannerview.indicator.IIndicator;
+import com.zhpan.bannerview.indicator.IndicatorFactory;
 import com.zhpan.bannerview.utils.DpUtils;
 import com.zhpan.bannerview.adapter.BannerPagerAdapter;
 import com.zhpan.bannerview.enums.IndicatorSlideMode;
@@ -70,9 +73,9 @@ public class BannerViewPager<T, VH extends ViewHolder> extends FrameLayout imple
     // 选中时选点颜色
     private int indicatorCheckedColor;
     // 指示器圆点半径
-    private float normalIndicatorRadius;
+    private float normalIndicatorWidth;
     // 选中时指示器圆点半径
-    private float checkedIndicatorRadius;
+    private float checkedIndicatorWidth;
 
     // 页面点击事件监听
     private OnPageClickListener mOnPageClickListener;
@@ -80,6 +83,14 @@ public class BannerViewPager<T, VH extends ViewHolder> extends FrameLayout imple
     private IIndicator mIndicatorView;
     //  存放IndicatorView的容器
     RelativeLayout mRelativeLayout;
+    /**
+     * 指示器Style样式
+     *
+     * @see IndicatorStyle#CIRCLE 圆形指示器
+     * @see IndicatorStyle#DASH  虚线指示器
+     */
+    private IndicatorStyle mIndicatorStyle = IndicatorStyle.CIRCLE;
+
 
     private HolderCreator<VH> holderCreator;
     // IndicatorView的滑动模式
@@ -107,7 +118,7 @@ public class BannerViewPager<T, VH extends ViewHolder> extends FrameLayout imple
 
     public static final int DEFAULT_SCROLL_DURATION = 800;
 
-    private float indicatorMargin = 0;
+    private float indicatorGap = 0;
 
     public BannerViewPager(Context context) {
         this(context, null);
@@ -146,9 +157,10 @@ public class BannerViewPager<T, VH extends ViewHolder> extends FrameLayout imple
             indicatorNormalColor =
                     typedArray.getColor(R.styleable.BannerViewPager_indicator_normal_color,
                             Color.parseColor("#8C6C6D72"));
-            normalIndicatorRadius = typedArray.getDimension(R.styleable.BannerViewPager_indicator_radius,
-                    DpUtils.dp2px(context, 4));
-            checkedIndicatorRadius = normalIndicatorRadius;
+            normalIndicatorWidth = typedArray.getDimension(R.styleable.BannerViewPager_indicator_radius,
+                    DpUtils.dp2px(8));
+            indicatorGap = normalIndicatorWidth;
+            checkedIndicatorWidth = normalIndicatorWidth;
             isAutoPlay = typedArray.getBoolean(R.styleable.BannerViewPager_isAutoPlay, true);
             isCanLoop = typedArray.getBoolean(R.styleable.BannerViewPager_isCanLoop, true);
             gravity = typedArray.getInt(R.styleable.BannerViewPager_indicator_gravity, 0);
@@ -174,7 +186,7 @@ public class BannerViewPager<T, VH extends ViewHolder> extends FrameLayout imple
     private void initData() {
         if (mList.size() > 0) {
             if (mIndicatorView == null && mList.size() > 1 && showIndicator) {
-                initIndicator(getDefaultIndicatorView());
+                initIndicator(getIndicatorView());
             }
             if (isCanLoop) {
                 currentPosition = 1;
@@ -183,11 +195,16 @@ public class BannerViewPager<T, VH extends ViewHolder> extends FrameLayout imple
         }
     }
 
-    private View getDefaultIndicatorView() {
-        CircleIndicatorView indicatorView = new CircleIndicatorView(getContext());
-        indicatorView.setPageSize(mList.size()).setIndicatorRadius(normalIndicatorRadius, checkedIndicatorRadius)
-                .setIndicatorMargin(indicatorMargin).setCheckedColor(indicatorCheckedColor)
-                .setNormalColor(indicatorNormalColor).setSlideStyle(mIndicatorSlideMode).invalidate();
+    private BaseIndicatorView getIndicatorView() {
+        BaseIndicatorView indicatorView = IndicatorFactory.createIndicatorView(getContext(), mIndicatorStyle);
+        indicatorView.setPageSize(mList.size());
+
+        indicatorView.setIndicatorWidth(DpUtils.px2dp(normalIndicatorWidth), DpUtils.px2dp(checkedIndicatorWidth));
+        indicatorView.setIndicatorGap(DpUtils.px2dp(indicatorGap));
+        indicatorView.setCheckedColor(indicatorCheckedColor);
+        indicatorView.setNormalColor(indicatorNormalColor);
+        indicatorView.setSlideStyle(mIndicatorSlideMode);
+        indicatorView.invalidate();
         return indicatorView;
     }
 
@@ -239,7 +256,6 @@ public class BannerViewPager<T, VH extends ViewHolder> extends FrameLayout imple
         }
     }
 
-
     private void setupViewPager() {
         if (holderCreator != null) {
             BannerPagerAdapter<T, VH> bannerPagerAdapter =
@@ -273,9 +289,9 @@ public class BannerViewPager<T, VH extends ViewHolder> extends FrameLayout imple
 
     @Override
     public void onPageScrollStateChanged(int state) {
-        if (mIndicatorView != null)
+        if (showIndicator && mIndicatorView != null) {
             mIndicatorView.onPageScrollStateChanged(state);
-
+        }
         if (isCanLoop) {
             switch (state) {
                 case ViewPager.SCROLL_STATE_IDLE:
@@ -300,7 +316,7 @@ public class BannerViewPager<T, VH extends ViewHolder> extends FrameLayout imple
 
     @Override
     public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
-        if (mIndicatorView != null) {
+        if (showIndicator && mIndicatorView != null) {
             mIndicatorView.onPageScrolled(getRealPosition(position), positionOffset, positionOffsetPixels);
         }
     }
@@ -331,7 +347,6 @@ public class BannerViewPager<T, VH extends ViewHolder> extends FrameLayout imple
         return mList;
     }
 
-
     /**
      * 开启轮播
      */
@@ -354,7 +369,7 @@ public class BannerViewPager<T, VH extends ViewHolder> extends FrameLayout imple
 
     /**
      * 必须为BannerViewPager设置HolderCreator,HolderCreator中创建ViewHolder,
-     * 在ViewHolder中管理BannerViewPager的页面ItemView.
+     * 在ViewHolder中管理BannerViewPager的ItemView.
      *
      * @param holderCreator HolderCreator
      */
@@ -384,7 +399,7 @@ public class BannerViewPager<T, VH extends ViewHolder> extends FrameLayout imple
     public BannerViewPager<T, VH> setRoundCorner(float radiusDp) {
         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
             ViewStyleSetter viewStyleSetter = new ViewStyleSetter(this);
-            viewStyleSetter.setRoundCorner(DpUtils.dp2px(getContext(), radiusDp));
+            viewStyleSetter.setRoundCorner(DpUtils.dp2px(radiusDp));
         }
         return this;
     }
@@ -437,19 +452,11 @@ public class BannerViewPager<T, VH extends ViewHolder> extends FrameLayout imple
         return this;
     }
 
-    /**
-     * @param transformer PageTransformer that will modify each page's animation properties
-     */
-    public BannerViewPager<T, VH> setPageTransformer(ViewPager.PageTransformer transformer) {
-        mViewPager.setPageTransformer(true, transformer);
-        return this;
-    }
-
     /**
      * 设置页面Transformer内置样式
      */
     public void setPageTransformerStyle(TransformerStyle style) {
-        setPageTransformer(new PageTransformerFactory().createPageTransformer(style));
+        mViewPager.setPageTransformer(true, new PageTransformerFactory().createPageTransformer(style));
     }
 
 
@@ -464,37 +471,79 @@ public class BannerViewPager<T, VH extends ViewHolder> extends FrameLayout imple
     }
 
     /**
-     * 设置指示器半径大小
+     * 设置指示器半径
+     * 你可以在{@link BannerViewPager#mIndicatorStyle}=={@link IndicatorStyle#CIRCLE}
+     * 时使用此方法设置圆的半径
+     *
+     * @param indicatorRadius 指示器圆点半径
+     */
+    public BannerViewPager<T, VH> setIndicatorRadius(float indicatorRadius) {
+        this.normalIndicatorWidth = 2 * DpUtils.dp2px(indicatorRadius);
+        this.checkedIndicatorWidth = normalIndicatorWidth;
+        return this;
+    }
+
+    /**
+     * 设置指示器半径
+     * 你可以在{@link BannerViewPager#mIndicatorStyle}=={@link IndicatorStyle#CIRCLE}
+     * 时使用此方法设置圆的半径
      *
-     * @param radiusDp 指示器圆点半径
+     * @param indicatorWidth 指示器圆点半径,单位dp
      */
-    public BannerViewPager<T, VH> setIndicatorRadius(float radiusDp) {
-        this.normalIndicatorRadius = DpUtils.dp2px(getContext(), radiusDp);
-        this.checkedIndicatorRadius = normalIndicatorRadius;
+    public BannerViewPager<T, VH> setIndicatorWidth(float indicatorWidth) {
+        this.normalIndicatorWidth = DpUtils.dp2px(indicatorWidth);
+        this.checkedIndicatorWidth = normalIndicatorWidth;
         return this;
     }
 
     /**
      * 设置指示器半径大小,单位dp
+     * 你可以在{@link BannerViewPager#mIndicatorStyle}=={@link IndicatorStyle#CIRCLE}时使用此方法设置圆的半径
      *
-     * @param normalRadius 未选中是半径大小
-     * @param checkRadius  选中时半径大小
+     * @param normalRadius  未选中是半径大小
+     * @param checkedRadius 选中时半径大小
      */
-    public BannerViewPager<T, VH> setIndicatorRadius(float normalRadius, float checkRadius) {
-        this.normalIndicatorRadius = DpUtils.dp2px(getContext(), normalRadius);
-        this.checkedIndicatorRadius = DpUtils.dp2px(getContext(), checkRadius);
+    public BannerViewPager<T, VH> setIndicatorRadius(float normalRadius, float checkedRadius) {
+        this.normalIndicatorWidth = 2 * DpUtils.dp2px(normalRadius);
+        this.checkedIndicatorWidth = 2 * DpUtils.dp2px(checkedRadius);
         return this;
     }
 
+    /**
+     * 设置指示器宽度,单位dp
+     * 如果{@link BannerViewPager#mIndicatorStyle}=={@link IndicatorStyle#CIRCLE}则为圆的直径
+     * 如果{@link BannerViewPager#mIndicatorStyle}=={@link IndicatorStyle#DASH}则为Indicator的直径
+     *
+     * @param normalIndicatorWidth  未选中时宽度/直径大小
+     * @param checkedIndicatorWidth 选中时宽度/直径大小
+     */
+    public BannerViewPager<T, VH> setIndicatorWidth(float normalIndicatorWidth, float checkedIndicatorWidth) {
+        this.normalIndicatorWidth = DpUtils.dp2px(normalIndicatorWidth);
+        this.checkedIndicatorWidth = DpUtils.dp2px(checkedIndicatorWidth);
+        return this;
+    }
 
     /**
      * 设置指示器半径大小,选中与未选中半径大小相等
      *
      * @param radiusRes 指示器圆点半径
+     * @param radiusRes
+     * @return
      */
     public BannerViewPager<T, VH> setIndicatorRadius(@DimenRes int radiusRes) {
-        this.normalIndicatorRadius = getContext().getResources().getDimension(radiusRes);
-        this.checkedIndicatorRadius = normalIndicatorRadius;
+        this.normalIndicatorWidth = getContext().getResources().getDimension(radiusRes);
+        this.checkedIndicatorWidth = normalIndicatorWidth;
+        return this;
+    }
+
+    /**
+     * 设置单个Indicator宽度,如果是圆则为圆的直径
+     *
+     * @param indicatorWidth 单个Indicator宽度/直径
+     */
+    public BannerViewPager<T, VH> setIndicatorWidth(@DimenRes int indicatorWidth) {
+        this.normalIndicatorWidth = DpUtils.px2dp(getContext().getResources().getDimension(indicatorWidth));
+        this.checkedIndicatorWidth = normalIndicatorWidth;
         return this;
     }
 
@@ -505,8 +554,20 @@ public class BannerViewPager<T, VH extends ViewHolder> extends FrameLayout imple
      * @param checkRadius  选中时半径
      */
     public BannerViewPager<T, VH> setIndicatorRadius(@DimenRes int normalRadius, @DimenRes int checkRadius) {
-        this.normalIndicatorRadius = getContext().getResources().getDimension(normalRadius);
-        this.checkedIndicatorRadius = getContext().getResources().getDimension(checkRadius);
+        this.normalIndicatorWidth = 2 * getContext().getResources().getDimension(normalRadius);
+        this.checkedIndicatorWidth = 2 * getContext().getResources().getDimension(checkRadius);
+        return this;
+    }
+
+    /**
+     * 设置单个Indicator宽度,如果是圆则为圆的直径
+     *
+     * @param normalRadius 未选中时宽度/直径
+     * @param checkRadius  选中时宽度/直径
+     */
+    public BannerViewPager<T, VH> setIndicatorWidth(@DimenRes int normalRadius, @DimenRes int checkRadius) {
+        this.normalIndicatorWidth = DpUtils.px2dp(getContext().getResources().getDimension(normalRadius));
+        this.checkedIndicatorWidth = DpUtils.px2dp(getContext().getResources().getDimension(checkRadius));
         return this;
     }
 
@@ -551,13 +612,13 @@ public class BannerViewPager<T, VH extends ViewHolder> extends FrameLayout imple
     }
 
     /**
-     * 设置指示器间隔
+     * 设置指示器间隔,单位dp
      *
      * @param indicatorGap 指示器间隔
      * @return BannerViewPager
      */
     public BannerViewPager<T, VH> setIndicatorGap(float indicatorGap) {
-        this.indicatorMargin = indicatorGap;
+        this.indicatorGap = DpUtils.dp2px(indicatorGap);
         return this;
     }
 
@@ -568,22 +629,28 @@ public class BannerViewPager<T, VH extends ViewHolder> extends FrameLayout imple
      * @return BannerViewPager
      */
     public BannerViewPager<T, VH> setIndicatorGap(@DimenRes int marginRes) {
-        this.indicatorMargin = getContext().getResources().getDimension(marginRes);
+        this.indicatorGap = DpUtils.px2dp(getContext().getResources().getDimension(marginRes));
         return this;
     }
 
     /**
-     * 设置自定义View指示器,自定义View需要需要实现IIndicator接口并自行绘制指示器。
+     * 设置自定义View指示器,自定义View需要需要继承BaseIndicator或者实现IIndicator接口自行绘制指示器。
+     * 注意,一旦设置了自定义IndicatorView,通过BannerViewPager设置的部分IndicatorView参数将失效。
      *
-     * @param indicatorView 自定义指示器
+     * @param customIndicator 自定义指示器
      */
-    public BannerViewPager<T, VH> setIndicatorView(IIndicator indicatorView) {
-        if (indicatorView instanceof View) {
-            initIndicator((View) indicatorView);
+    public BannerViewPager<T, VH> setCustomIndicatorView(IIndicator customIndicator) {
+        if (customIndicator instanceof View) {
+            initIndicator((View) customIndicator);
         }
         return this;
     }
 
+    public BannerViewPager<T, VH> setIndicatorStyle(IndicatorStyle indicatorStyle) {
+        mIndicatorStyle = indicatorStyle;
+        return this;
+    }
+
     /**
      * 构造ViewPager
      *

+ 1 - 1
bannerview/src/main/java/com/zhpan/bannerview/enums/IndicatorStyle.java

@@ -1,5 +1,5 @@
 package com.zhpan.bannerview.enums;
 
 public enum IndicatorStyle {
-    NORMAL, BIGGER
+    CIRCLE, DASH
 }

+ 127 - 2
bannerview/src/main/java/com/zhpan/bannerview/indicator/BaseIndicatorView.java

@@ -1,18 +1,66 @@
 package com.zhpan.bannerview.indicator;
 
 import android.content.Context;
+import android.graphics.Color;
 import android.util.AttributeSet;
 import android.view.View;
 
+import androidx.annotation.DimenRes;
 import androidx.annotation.Nullable;
 
+import com.zhpan.bannerview.enums.IndicatorSlideMode;
+import com.zhpan.bannerview.utils.DpUtils;
+
 /**
  * <pre>
  *   Created by zhangpan on 2019-09-04.
- *   Description:
+ *   Description:IndicatorView基类,处理了页面滑动。
  * </pre>
  */
 public class BaseIndicatorView extends View implements IIndicator {
+    /**
+     * 页面size
+     */
+    protected int mPageSize;
+    /**
+     * 未选中时Indicator颜色
+     */
+    protected int normalColor;
+    /**
+     * 选中时Indicator颜色
+     */
+    protected int checkedColor;
+    /**
+     * Indicator间距
+     */
+    protected float mIndicatorGap;
+    /**
+     * 从一个点滑动到另一个点的进度
+     */
+    protected float slideProgress;
+    /**
+     * 指示器当前位置
+     */
+    protected int currentPosition;
+    /**
+     * 指示器上一个位置
+     */
+    private int prePosition;
+    /**
+     * 是否是向右滑动,true向右,false向左
+     */
+    protected boolean slideToRight;
+    /**
+     * Indicator滑动模式,目前仅支持两种
+     *
+     * @see IndicatorSlideMode#NORMAL
+     * @see IndicatorSlideMode#SMOOTH
+     */
+    protected IndicatorSlideMode mSlideStyle = IndicatorSlideMode.SMOOTH;
+
+    protected float normalIndicatorWidth;
+    protected float checkedIndicatorWidth;
+
     public BaseIndicatorView(Context context) {
         super(context);
     }
@@ -23,16 +71,93 @@ public class BaseIndicatorView extends View implements IIndicator {
 
     public BaseIndicatorView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
         super(context, attrs, defStyleAttr);
+        normalIndicatorWidth = DpUtils.dp2px(8);
+        checkedIndicatorWidth = normalIndicatorWidth;
+        mIndicatorGap=normalIndicatorWidth;
+        normalColor = Color.parseColor("#8C18171C");
+        checkedColor = Color.parseColor("#8C6C6D72");
     }
 
     @Override
     public void onPageSelected(int position) {
-
+        if (mSlideStyle == IndicatorSlideMode.NORMAL) {
+            currentPosition = position;
+            slideProgress = 0;
+            invalidate();
+        } else if (mSlideStyle == IndicatorSlideMode.SMOOTH) {
+            if (position == 0 && slideToRight) {
+                currentPosition = 0;
+                slideProgress = 0;
+                invalidate();
+            } else if (position == mPageSize - 1 && !slideToRight) {
+                currentPosition = mPageSize - 1;
+                slideProgress = 0;
+                invalidate();
+            }
+        }
     }
 
     @Override
     public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
+        if (mSlideStyle == IndicatorSlideMode.SMOOTH) {
+            if ((prePosition == 0 && position == mPageSize - 1)) {
+                slideToRight = false;
+            } else if (prePosition == mPageSize - 1 && position == 0) {
+                slideToRight = true;
+            } else {
+                slideToRight = (position + positionOffset - prePosition) > 0;
+            }
+            //  TODO 解决滑动过快时positionOffset不会等0的情况
+            if (positionOffset == 0) {
+                prePosition = position;
+            }
+            if (!(position == mPageSize - 1 && slideToRight || (position == mPageSize - 1 && !slideToRight))) {
+                slideProgress = (currentPosition == mPageSize - 1) && slideToRight ? 0 : positionOffset;
+                currentPosition = position;
+                invalidate();
+            }
+        }
+    }
+
+    @Override
+    public void setPageSize(int pageSize) {
+        this.mPageSize = pageSize;
+        requestLayout();
+    }
+
+    @Override
+    public void setNormalColor(int normalColor) {
+        this.normalColor = normalColor;
+    }
 
+    @Override
+    public void setCheckedColor(int checkedColor) {
+        this.checkedColor = checkedColor;
+    }
+
+    @Override
+    public void setIndicatorGap(float gap) {
+        if (gap >= 0) {
+            this.mIndicatorGap = DpUtils.dp2px(gap);
+        }
+    }
+
+    public void setIndicatorGap(@DimenRes int gapRes) {
+        float indicatorGap = getContext().getResources().getDimension(gapRes);
+        if (indicatorGap >= 0) {
+            this.mIndicatorGap = indicatorGap;
+        }
+    }
+
+    @Override
+    public void setSlideStyle(IndicatorSlideMode slideStyle) {
+        mSlideStyle = slideStyle;
+    }
+
+    @Override
+    public void setIndicatorWidth(float normalIndicatorWidth,float checkedIndicatorWidth) {
+        this.normalIndicatorWidth = DpUtils.dp2px(normalIndicatorWidth);
+        this.checkedIndicatorWidth = DpUtils.dp2px(checkedIndicatorWidth);
     }
 
     @Override

+ 30 - 95
bannerview/src/main/java/com/zhpan/bannerview/indicator/CircleIndicatorView.java

@@ -2,32 +2,23 @@ package com.zhpan.bannerview.indicator;
 
 import android.content.Context;
 import android.graphics.Canvas;
-import android.graphics.Color;
 import android.graphics.Paint;
 import android.util.AttributeSet;
-import android.util.Log;
-import android.view.View;
 
-import com.zhpan.bannerview.enums.IndicatorSlideMode;
+import androidx.annotation.DimenRes;
+
 import com.zhpan.bannerview.utils.DpUtils;
 
 /**
  * Created by zhpan on 2017/12/6.
  */
-public class CircleIndicatorView extends View implements IIndicator {
+public class CircleIndicatorView extends BaseIndicatorView {
     private static final String tag = "IndicatorView";
-    private int normalColor;
-    private int checkedColor;
     private Paint mPaint;
-    private int mPageSize;
     private float mNormalRadius;
     private float mCheckedRadius;
     private float maxRadius;
     private int height;
-    private int currentPosition;
-    private float mMargin;
-    private IndicatorSlideMode mSlideStyle = IndicatorSlideMode.SMOOTH;
-    private float slideProgress;
 
     public CircleIndicatorView(Context context) {
         this(context, null);
@@ -39,14 +30,12 @@ public class CircleIndicatorView extends View implements IIndicator {
 
     public CircleIndicatorView(Context context, AttributeSet attrs, int defStyleAttr) {
         super(context, attrs, defStyleAttr);
-        normalColor = Color.parseColor("#8C18171C");
-        checkedColor = Color.parseColor("#8C6C6D72");
         mPaint = new Paint();
         mPaint.setColor(normalColor);
         mPaint.setAntiAlias(true);
-        mNormalRadius = DpUtils.dp2px(context, 4);
-        mCheckedRadius = mNormalRadius;
-        mMargin = mNormalRadius * 2;
+        mNormalRadius = normalIndicatorWidth / 2;
+        mCheckedRadius = checkedIndicatorWidth / 2;
+        mIndicatorGap = mNormalRadius * 2;
     }
 
     @Override
@@ -58,113 +47,59 @@ public class CircleIndicatorView extends View implements IIndicator {
     @Override
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
         super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+        mNormalRadius = normalIndicatorWidth / 2;
+        mCheckedRadius = checkedIndicatorWidth / 2;
         maxRadius = Math.max(mCheckedRadius, mNormalRadius);
-        setMeasuredDimension((int) ((mPageSize - 1) * mMargin + 2 * maxRadius * mPageSize),
+        setMeasuredDimension((int) ((mPageSize - 1) * mIndicatorGap + 2 * maxRadius * mPageSize),
                 (int) (2 * maxRadius));
     }
 
-    @Override
-    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
-        super.onLayout(changed, left, top, right, bottom);
-    }
-
     @Override
     protected void onDraw(Canvas canvas) {
         super.onDraw(canvas);
         for (int i = 0; i < mPageSize; i++) {
             mPaint.setColor(normalColor);
-            canvas.drawCircle(maxRadius + (2 * mNormalRadius + mMargin) * i, height / 2f, mNormalRadius, mPaint);
+            canvas.drawCircle(maxRadius + (2 * mNormalRadius + mIndicatorGap) * i, height / 2f, mNormalRadius, mPaint);
         }
-        drawSlideStyle(canvas);
+        drawSliderStyle(canvas);
     }
 
     @Override
     public void onPageSelected(int position) {
-        if (mSlideStyle == IndicatorSlideMode.NORMAL) {
-            currentPosition = position;
-            slideProgress = 0;
-            invalidate();
-        } else if (mSlideStyle == IndicatorSlideMode.SMOOTH) {
-            if (position == 0 && slideToRight) {
-                currentPosition = 0;
-                slideProgress = 0;
-                invalidate();
-            } else if (position == mPageSize - 1 && !slideToRight) {
-                currentPosition = mPageSize - 1;
-                slideProgress = 0;
-                invalidate();
-            }
-        }
+        super.onPageSelected(position);
     }
 
-    private boolean slideToRight;
-    private int prePosition;
-
     @Override
     public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
-        if (mSlideStyle == IndicatorSlideMode.SMOOTH) {
-            if ((prePosition == 0 && position == mPageSize - 1)) {
-                slideToRight = false;
-            } else if (prePosition == mPageSize - 1 && position == 0) {
-                slideToRight = true;
-            } else {
-                slideToRight = (position + positionOffset - prePosition) > 0;
-            }
-            //  TODO 解决滑动过快时positionOffset不会等0的情况
-            if (positionOffset == 0) {
-                prePosition = position;
-            }
-            if (!(position == mPageSize - 1 && slideToRight || (position == mPageSize - 1 && !slideToRight))) {
-                slideProgress = (currentPosition == mPageSize - 1) && slideToRight ? 0 : positionOffset;
-                currentPosition = position;
-                invalidate();
-            }
-        }
+        super.onPageScrolled(position, positionOffset, positionOffsetPixels);
     }
 
     @Override
     public void onPageScrollStateChanged(int state) {
-
+        super.onPageScrollStateChanged(state);
     }
 
-    private void drawSlideStyle(Canvas canvas) {
+    private void drawSliderStyle(Canvas canvas) {
         mPaint.setColor(checkedColor);
-        canvas.drawCircle(maxRadius + (2 * mNormalRadius + mMargin) * currentPosition + (2 * mNormalRadius + mMargin) * slideProgress,
+        canvas.drawCircle(maxRadius + (2 * mNormalRadius + mIndicatorGap) * currentPosition + (2 * mNormalRadius + mIndicatorGap) * slideProgress,
                 height / 2f, mCheckedRadius, mPaint);
     }
 
-
-    public CircleIndicatorView setNormalColor(int normalColor) {
-        this.normalColor = normalColor;
-        return this;
-    }
-
-    public CircleIndicatorView setCheckedColor(int checkedColor) {
-        this.checkedColor = checkedColor;
-        return this;
-    }
-
-    public CircleIndicatorView setPageSize(int pageSize) {
-        this.mPageSize = pageSize;
-        requestLayout();
-        return this;
-    }
-
-    public CircleIndicatorView setIndicatorRadius(float radiusDp, float checkedRadius) {
-        this.mNormalRadius = radiusDp;
-        this.mCheckedRadius = checkedRadius;
-        return this;
-    }
-
-    public CircleIndicatorView setIndicatorMargin(float margin) {
-        if (margin > 0) {
-            this.mMargin = margin;
-        }
-        return this;
+    /**
+     * @param normalRadius  未选中时Indicator半径,单位dp
+     * @param checkedRadius 选中时Indicator半径,单位dp
+     */
+    public void setIndicatorRadius(float normalRadius, float checkedRadius) {
+        this.mNormalRadius = DpUtils.dp2px(normalRadius);
+        this.mCheckedRadius = DpUtils.dp2px(checkedRadius);
     }
 
-    public CircleIndicatorView setSlideStyle(IndicatorSlideMode slideStyle) {
-        mSlideStyle = slideStyle;
-        return this;
+    /**
+     * @param normalRadius  未选中时Indicator半径
+     * @param checkedRadius 选中时Indicator半径
+     */
+    public void setIndicatorRadius(@DimenRes int normalRadius, @DimenRes int checkedRadius) {
+        this.mNormalRadius = getContext().getResources().getDimension(normalRadius);
+        this.mCheckedRadius = getContext().getResources().getDimension(checkedRadius);
     }
 }

+ 86 - 0
bannerview/src/main/java/com/zhpan/bannerview/indicator/DashIndicatorView.java

@@ -0,0 +1,86 @@
+package com.zhpan.bannerview.indicator;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.util.AttributeSet;
+
+import com.zhpan.bannerview.utils.DpUtils;
+
+/**
+ * Created by zhpan on 2017/12/6.
+ */
+public class DashIndicatorView extends BaseIndicatorView implements IIndicator {
+    private Paint mPaint;
+    private float sliderHeight;
+
+    public DashIndicatorView(Context context) {
+        this(context, null);
+    }
+
+    public DashIndicatorView(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public DashIndicatorView(Context context, AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+        mPaint = new Paint();
+        mPaint.setColor(normalColor);
+        mPaint.setAntiAlias(true);
+        sliderHeight = normalIndicatorWidth / 2;
+    }
+
+    @Override
+    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
+        super.onSizeChanged(w, h, oldw, oldh);
+    }
+
+    @Override
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+        setMeasuredDimension((int) ((mPageSize - 1) *mIndicatorGap  + normalIndicatorWidth * mPageSize),
+                (int) (sliderHeight));
+    }
+
+    @Override
+    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+        super.onLayout(changed, left, top, right, bottom);
+    }
+
+    @Override
+    protected void onDraw(Canvas canvas) {
+        super.onDraw(canvas);
+        mPaint.setColor(normalColor);
+        for (int i = 0; i < mPageSize; i++) {
+            mPaint.setColor(normalColor);
+            canvas.drawRect(i * (normalIndicatorWidth) + i * +mIndicatorGap, 0, i * (normalIndicatorWidth) + i * +mIndicatorGap + normalIndicatorWidth, sliderHeight, mPaint);
+        }
+        drawSliderStyle(canvas);
+    }
+
+    @Override
+    public void onPageSelected(int position) {
+        super.onPageSelected(position);
+    }
+
+    @Override
+    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
+        super.onPageScrolled(position, positionOffset, positionOffsetPixels);
+    }
+
+    @Override
+    public void onPageScrollStateChanged(int state) {
+        super.onPageScrollStateChanged(state);
+    }
+
+    private void drawSliderStyle(Canvas canvas) {
+        mPaint.setColor(checkedColor);
+        float left = currentPosition * (checkedIndicatorWidth) + currentPosition * +mIndicatorGap + (checkedIndicatorWidth + mIndicatorGap) * slideProgress;
+        canvas.drawRect(left, 0, left + checkedIndicatorWidth, sliderHeight, mPaint);
+    }
+
+    public DashIndicatorView setSliderHeight(float sliderHeight) {
+        this.sliderHeight = DpUtils.dp2px(sliderHeight);
+        return this;
+    }
+}

+ 14 - 0
bannerview/src/main/java/com/zhpan/bannerview/indicator/IIndicator.java

@@ -1,5 +1,7 @@
 package com.zhpan.bannerview.indicator;
 
+import com.zhpan.bannerview.enums.IndicatorSlideMode;
+
 /**
  * <pre>
  *   Created by zhangpan on 2019-09-02.
@@ -12,4 +14,16 @@ public interface IIndicator {
     void onPageScrolled(int position, float positionOffset, int positionOffsetPixels);
 
     void onPageScrollStateChanged(int state);
+
+    void setPageSize(int pageSize);
+
+    void setNormalColor(int normalColor);
+
+    void setCheckedColor(int checkedColor);
+
+    void setIndicatorGap(float gap);
+
+    void setSlideStyle(IndicatorSlideMode slideStyle);
+
+    void setIndicatorWidth(float normalIndicatorWidth,float checkedIndicatorWidth);
 }

+ 23 - 0
bannerview/src/main/java/com/zhpan/bannerview/indicator/IndicatorFactory.java

@@ -0,0 +1,23 @@
+package com.zhpan.bannerview.indicator;
+
+import android.content.Context;
+
+import com.zhpan.bannerview.enums.IndicatorStyle;
+
+public class IndicatorFactory {
+    public static BaseIndicatorView createIndicatorView(Context context, IndicatorStyle indicatorStyle) {
+        BaseIndicatorView indicatorView;
+        switch (indicatorStyle) {
+            case CIRCLE:
+                indicatorView = new CircleIndicatorView(context);
+                break;
+            case DASH:
+                indicatorView = new DashIndicatorView(context);
+                break;
+            default:
+                indicatorView = new CircleIndicatorView(context);
+                break;
+        }
+        return indicatorView;
+    }
+}

+ 22 - 4
bannerview/src/main/java/com/zhpan/bannerview/utils/DpUtils.java

@@ -1,6 +1,7 @@
 package com.zhpan.bannerview.utils;
 
 import android.content.Context;
+import android.content.res.Resources;
 import android.util.DisplayMetrics;
 
 /**
@@ -10,9 +11,26 @@ import android.util.DisplayMetrics;
  * </pre>
  */
 public class DpUtils {
-    public static int dp2px(Context context, float dpValue) {
-        DisplayMetrics metric = context.getResources().getDisplayMetrics();
-        float screenDensity = metric.density;
-        return (int) (dpValue * screenDensity + 0.5f);
+
+    public float density;
+
+    public DpUtils() {
+        this.density = Resources.getSystem().getDisplayMetrics().density;
+    }
+
+    public static int dp2px(float dpValue) {
+        return (int)(0.5F + dpValue * Resources.getSystem().getDisplayMetrics().density);
+    }
+
+    public static float px2dp(float pxValue) {
+        return pxValue / Resources.getSystem().getDisplayMetrics().density;
+    }
+
+    public int dip2px(float dpValue) {
+        return (int)(0.5F + dpValue * this.density);
+    }
+
+    public float px2dip(int pxValue) {
+        return (float)pxValue / this.density;
     }
 }