通过自定义View,创建一个圆形指示器

在项目中只要涉及到滑动的地方,很多时候都需要用到指示器。那么今天就通过自定义View来创建一个属于自己的指示器。

效果图:
在这里插入图片描述
首先,在res - values下新建一个attr文件, 可命名为:attr_indicator.xml 代码如下:

<resources>
    <declare-styleable name="PageIndicatorView">
        <!-- 指示器间隔 -->
        <attr name="circleInterval" format="dimension"/>
        <!-- 指示器大小 -->
        <attr name="circleSizi" format="dimension"/>
        <!-- 指示器数量 -->
        <attr name="circleNumber" format="integer"/>
        <!-- 指示器初始化选中位置(从1开始) -->
        <attr name="selectIndex" format="integer"/>
        <!-- 指示器选中颜色 -->
        <attr name="circleSelectColor" format="color"/>
        <!-- 指示器未选中颜色 -->
        <attr name="circleUnSelectColor" format="color"/>
    </declare-styleable>
</resources>

然后。新建一个类,继承View,这里命名为:PageIndicatorView

代码如下:

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.View;

import com.yikelive.R;

import androidx.annotation.Nullable;

public class PageIndicatorView extends View {
    
    
    private Paint mPaint;
    private int mCircleInterval;//设置圆和点圆之间的间隔
    private int mCircleRadius;//设置圆的大小
    private int mCircleNumber;//设置圆的个数
    private int mSelectIndex = 1;//设置选中的圆
    private int mScreenWidht;
    private int mScreenHeight;
    private int mWidht;
    private int mHeight;
    private int mSelectColor;
    private int mUnSelectColor;


    public void setmCircleNumber(int mCircleNumber) {
    
    
        this.mCircleNumber = mCircleNumber;
    }

    public void setIndex(int selectIndex) {
    
    
        if (selectIndex > mCircleNumber) {
    
    
            this.mSelectIndex = mCircleNumber;
        } else {
    
    
            this.mSelectIndex = selectIndex;
        }
        postInvalidate();
    }

    public void setmSelectColor(int mSelectColor) {
    
    
        this.mSelectColor = mSelectColor;
    }

    public void setmUnSelectColor(int mUnSelectColor) {
    
    
        this.mUnSelectColor = mUnSelectColor;
    }

    public PageIndicatorView(Context context) {
    
    
        this(context, null);
    }

    public PageIndicatorView(Context context, @Nullable AttributeSet attrs) {
    
    
        this(context, attrs, 0);
    }

    public PageIndicatorView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
    
    
        super(context, attrs, defStyleAttr);
        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setColor(Color.BLACK);
        mPaint.setStrokeWidth(20);
        mPaint.setStyle(Paint.Style.FILL);
        mScreenWidht = context.getResources().getDisplayMetrics().widthPixels;
        mScreenHeight = context.getResources().getDisplayMetrics().heightPixels;

        TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.PageIndicatorView, defStyleAttr, 0);
        int count = ta.getIndexCount();
        for (int i = 0; i < count; i++) {
    
    
            int index = ta.getIndex(i);
            switch (index) {
    
    
                case R.styleable.PageIndicatorView_circleInterval:
                    mCircleInterval = ta.getDimensionPixelSize(index, (int) TypedValue.applyDimension
                            (TypedValue.COMPLEX_UNIT_PX, 12, context.getResources().getDisplayMetrics()));
                    break;
                case R.styleable.PageIndicatorView_circleNumber:
                    mCircleNumber = ta.getInt(index, 4);
                    break;
                case R.styleable.PageIndicatorView_circleSizi:
                    mCircleRadius = ta.getDimensionPixelOffset(index, (int) TypedValue.applyDimension
                            (TypedValue.COMPLEX_UNIT_DIP, 12, context.getResources().getDisplayMetrics()));
                    break;
                case R.styleable.PageIndicatorView_selectIndex:
                    mSelectIndex = ta.getInt(index, 1);
                    break;
                case R.styleable.PageIndicatorView_circleSelectColor:
                    mSelectColor = ta.getColor(index, Color.WHITE);
                    break;
                case R.styleable.PageIndicatorView_circleUnSelectColor:
                    mUnSelectColor = ta.getColor(index, Color.BLACK);
                    break;
            }
        }
        ta.recycle();
    }
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    
    
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int wMode = MeasureSpec.getMode(widthMeasureSpec);
        int wSize = MeasureSpec.getSize(widthMeasureSpec);
        int hMode = MeasureSpec.getMode(heightMeasureSpec);
        int hSize = MeasureSpec.getSize(heightMeasureSpec);
        int viewWidht = 0;
        int viewHeight = 0;
        switch (wMode) {
    
    
            case MeasureSpec.EXACTLY:
                viewWidht = wSize;
                break;
            case MeasureSpec.AT_MOST:
                viewWidht = mCircleInterval + getPaddingLeft() + getPaddingRight() + mCircleRadius * 2;
                break;
            case MeasureSpec.UNSPECIFIED:
                viewWidht = wSize;
                break;
        }
        switch (hMode) {
    
    
            case MeasureSpec.EXACTLY:
                viewHeight = wSize;
                break;
            case View.MeasureSpec.AT_MOST:
                viewHeight = getPaddingBottom() + getPaddingTop() +  mCircleRadius * 2;
                break;
            case MeasureSpec.UNSPECIFIED:
                viewHeight = wSize;
                break;
        }
        setMeasuredDimension(resolveSize(viewWidht, widthMeasureSpec), resolveSize(viewHeight, heightMeasureSpec));
    }
    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    
    
        super.onSizeChanged(w, h, oldw, oldh);
        mWidht = w;
        mHeight = h;
    }
    @Override
    protected void onDraw(Canvas canvas) {
    
    
        super.onDraw(canvas);
        int mViewWidht;
        for (int i = 1; i <= mCircleNumber; i++) {
    
    
            if (mSelectIndex == i) {
    
    
                mPaint.setColor(mSelectColor);
                canvas.drawCircle((2 * i - 1) * mCircleRadius + mCircleInterval * (i - 1), mCircleRadius, mCircleRadius, mPaint);
                continue;
            }
            mPaint.setColor(mUnSelectColor);
            canvas.drawCircle((2 * i - 1) * mCircleRadius + mCircleInterval * (i - 1), mCircleRadius, mCircleRadius, mPaint);
        }
    }
}

下面就是在xml布局文件文件中的应用:

 <com.yikelive.ui.vip.newVip.assets.PageIndicatorView
            android:id="@+id/pv_point"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:circleInterval="3dp"
            app:circleSelectColor="#fbe29c"
            app:circleSizi="3dp"
            app:circleUnSelectColor="#666"/>

最后说一下在控制器中的使用,初始化一下指示器数量和默认选中位置,然后即是改变逻辑,以ViewPager为例,在ViewPager的翻页完成监听 ( onPageSelected() )中执行 指示器的**setIndex(position + 1)**方法即可。

代码如下:

 // 设置指示器数量
 host.pv_point.setmCircleNumber(users.size)
 //设置指示器初始选中位置(从1开始)
 host.pv_point.setIndex(1)
 // ViewPager监听
 host.rv_head.setOnPageChangeListener(object : ViewPager.OnPageChangeListener {
    
    
            override fun onPageScrollStateChanged(state: Int) {
    
    
            }

            override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {
    
    
            }
			//翻页完成后执行
            override fun onPageSelected(position: Int) {
    
    
				//指示器选中位置改变
                host.pv_point.setIndex(position + 1)
            }
        })

到此。一个指示器就全部完成了。

猜你喜欢

转载自blog.csdn.net/lixinxiaos/article/details/103780188