在项目中只要涉及到滑动的地方,很多时候都需要用到指示器。那么今天就通过自定义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"/>
<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)
}
})
到此。一个指示器就全部完成了。