版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/wxw20147854/article/details/55135653
在values中国创建文件attrs文件
<?xml version="1.0" encoding="utf-8"?> <resources> <!-- 定义属性在布局文件里面动态配置 --> <declare-styleable name="IndexMatchView"> <attr name="count" format="integer" /> <attr name="shape"> <enum name="circle" value="1" /> <enum name="triangle" value="2" /> <enum name="rectangle" value="3" /> </attr> <attr name="nomalcolor" format="color" /> <attr name="selectedcolor" format="color" /> <attr name="radius" format="dimension" /> <attr name="index_padding" format="dimension" /> </declare-styleable> </resources>
自定义一个类,继承ImageView,由此即可在XML布局文件中设置属性(静态加载,动态加载未完成,敬请期待更新)
import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Path; import android.util.AttributeSet; import android.widget.LinearLayout; /** * 索引框架 */ public class IndexMatchView extends LinearLayout { /** * 索引的个数 */ private int count; /** * 索引的形状 * 默认是圆形 */ private Shape shape = Shape.Circle; /** * 未选中时的颜色 */ private int normalColor; /** * 选中时的颜色 */ private int selectedColor; /** * 索引之间的间距 */ private float index_padding; /** * 索引的大小 */ private float radius; /** * 当前的索引位置,默认是第一个索引 */ private int currentIndex = 0; /** * 第一个索引的位置 */ private float firstIndexX, firstIndexY; /** * 画笔 */ private Paint paint; /** * 动态创建 * * @param context */ public IndexMatchView(Context context) { super(context); // 初始化画笔工具 init(); } /** * 静态创建 * * @param context * @param attrs */ public IndexMatchView(Context context, AttributeSet attrs) { super(context, attrs); // 初始化画笔工具 init(); // 获取静态配置的属性集合 TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.IndexMatchView); // 给对应的属性赋值 // 索引个数,默认索引的个数是5个 count = typedArray.getInt(R.styleable.IndexMatchView_count, 5); // 索引未选中时的颜色,默认绿色 normalColor = typedArray.getColor(R.styleable.IndexMatchView_nomalcolor, Color.GREEN); // 索引被选中时的颜色,默认红色 selectedColor = typedArray.getColor(R.styleable.IndexMatchView_selectedcolor, Color.RED); // 索引的大小 radius = typedArray.getDimension(R.styleable.IndexMatchView_radius, 20f); // 索引之间的间距 index_padding = typedArray.getDimension(R.styleable.IndexMatchView_index_padding, 10f); // 索引的形状 int s = typedArray.getInt(R.styleable.IndexMatchView_shape, 1); switch (s) { case 1: shape = Shape.Circle; break; case 2: shape = Shape.Triangle; break; case 3: shape = Shape.Rectangle; break; } // 不需要使用的时候释放 typedArray.recycle(); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); // 获取控件的宽高 int width = MeasureSpec.getSize(widthMeasureSpec); int height = MeasureSpec.getSize(heightMeasureSpec); // 确定第一个索引的位置 firstIndexX = (width - 2 * radius * count - (count - 1) * index_padding) / 2 + radius; firstIndexY = height / 2; } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); // 画圆 if (shape == Shape.Circle) { // 循环画圆 for (int i = 0; i < count; i++) { if (i == currentIndex) { paint.setColor(selectedColor); } else { paint.setColor(normalColor); } // 圆心的X轴坐标 float indexX = i * (2 * radius + index_padding) + firstIndexX; canvas.drawCircle(indexX, firstIndexY, radius, paint); } // 画三角形 } else if (shape == Shape.Triangle) { for (int i = 0; i < count; i++) { if (i == currentIndex) { paint.setColor(selectedColor); } else { paint.setColor(normalColor); } // 圆心的X轴坐标 float indexX = i * (2 * radius + index_padding) + firstIndexX; // 第一个点的坐标 float point1_X = indexX; float point1_Y = firstIndexY - radius; // 第二个点的坐标 float point2_X = indexX - (float) (Math.sqrt(3.0) / 2 * radius); float point2_Y = firstIndexY + radius / 2; // 第三个点的坐标 float point3_X = indexX + (float) (Math.sqrt(3.0) / 2 * radius); float point3_Y = firstIndexY + radius / 2; // 创建一个轨迹对象 Path path = new Path(); // 移动到第一点 path.moveTo(point1_X, point1_Y); // 画轨迹 path.lineTo(point2_X, point2_Y); path.lineTo(point3_X, point3_Y); // 关闭轨迹 path.close(); // 画轨迹 canvas.drawPath(path, paint); } // 画矩形 } else { for (int i = 0; i < count; i++) { if (i == currentIndex) { paint.setColor(selectedColor); } else { paint.setColor(normalColor); } // 圆心的X轴坐标 float indexX = i * (2 * radius + index_padding) + firstIndexX; // 第一个点的坐标 float point1_X = indexX - (float) (Math.sqrt(2) / 2 * radius); float point1_Y = firstIndexY + (float) (Math.sqrt(2) / 2 * radius); // 第二个点的坐标 float point2_X = indexX - (float) (Math.sqrt(2) / 2 * radius); float point2_Y = firstIndexY - (float) (Math.sqrt(2) / 2 * radius); // 第三个点的坐标 float point3_X = indexX + (float) (Math.sqrt(2) / 2 * radius); float point3_Y = firstIndexY - (float) (Math.sqrt(2) / 2 * radius); // 第四个点的坐标 float point4_X = indexX + (float) (Math.sqrt(2) / 2 * radius); float point4_Y = firstIndexY + (float) (Math.sqrt(2) / 2 * radius); // 创建一个轨迹对象 Path path = new Path(); // 移动到第一点 path.moveTo(point1_X, point1_Y); // 画轨迹 path.lineTo(point2_X, point2_Y); path.lineTo(point3_X, point3_Y); path.lineTo(point4_X, point4_Y); // 关闭轨迹 path.close(); // 画轨迹 canvas.drawPath(path, paint); } } } /** * 改变索引,重绘视图 * * @param i 要改变的索引 */ public void setCurrentIndex(int i) { currentIndex = i; // 视图重绘 invalidate(); } /** * 设置索引的总数 * @param count */ public void setCount(int count){ this.count = count; } /** * 设置索引的形状 * @param shape */ public void setShape(Shape shape){ this.shape = shape; } /** * 设置索引未被选中时的颜色 * @param normalColor */ public void setNormalColor(int normalColor){ this.normalColor = normalColor; } /** * 设置索引被选中时的颜色 * @param selectedColor */ public void setSelectedColor(int selectedColor){ this.selectedColor = selectedColor; } /** * 设置索引之间的间距 * @param index_padding */ public void setIndex_padding(float index_padding){ this.index_padding = index_padding; } /** * 设置索引的半径 * @param radius */ public void setRadius(float radius){ this.radius = radius; } /** * 初始化画笔工具 */ private void init() { paint = new Paint(); paint.setColor(normalColor); // 抗锯齿 paint.setAntiAlias(true); } public enum Shape { /** * 圆形 */ Circle, /** * 三角形 */ Triangle, /** * 矩形 */ Rectangle } }