[Android] Android自定义View修炼之路(2)

xiaoxiao2021-02-28  83

前言

上一篇文章中介绍了自定义View的基本流程,今天我们仍然跟随洋神脚步学习自定义View,本篇文章参考自洋神的 Android 自定义View (三) 圆环交替 等待效果一文,有兴趣的可以去洋神的博客看看哈!

举例

自定义View流程回顾

上一篇文章中介绍了下自定义View的流程,在本篇文章中我们仍然将这4个步骤列出来加深印象:

自定义View的属性在View的构造方法中获得自定义的属性重写onMeasure重写onDraw

下面我们按照这4个步骤一步步完成我们的自定义View。

自定义View的属性

在工程目录下的res/values子目录下建立一个attrs.xml文件,在里面定义我们需要的属性:

<?xml version="1.0" encoding="utf-8"?> <resources> <attr name="firstColor" format="color"/> <attr name="secondColor" format="color"/> <attr name="circleWidth" format="dimension"/> <attr name="speed" format="integer"/> <declare-styleable name="CustomView"> <attr name="firstColor"/> <attr name="secondColor"/> <attr name="circleWidth"/> <attr name="speed"/> </declare-styleable> </resources>

如上面这段代码,我们定义了4个属性,分别是第一个圆环的颜色、第二个圆环的颜色、圆环的宽度以及圆环更新的速度,然后我们就可以在layout布局文件中这样使用我们的自定义View及自定义属性:

<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.glemontree.customview04.MainActivity"> <com.glemontree.customview04.CustomView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true"/> </RelativeLayout>

这里我没有添加自定义属性,全都使用的默认属性,如果你有兴趣,可以在layout布局文件中的CustomView子结点下添加app:xxx="xxx"来使用自定义属性。

在View的构造方法中获取自定义属性

紧接着我们可以在自定义View的构造方法中获取自定义的属性,如下:

public CustomView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CustomView, defStyleAttr, 0); mFirstColor = a.getColor(R.styleable.CustomView_firstColor, Color.GREEN); mSecondColor = a.getColor(R.styleable.CustomView_secondColor, Color.RED); mCircleWidth = a.getDimensionPixelOffset(R.styleable.CustomView_circleWidth, (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 20, getResources().getDisplayMetrics())); mSpeed = a.getInt(R.styleable.CustomView_speed, 20); a.recycle(); mPaint = new Paint(); // 开启线程更新进度并刷新界面 new Thread() { public void run() { while (true) { mProgress++; if (mProgress == 360) { mProgress = 0; if (!mIsNext) { mIsNext = true; } else { mIsNext = false; } } // 刷新界面 postInvalidate(); // Thread.sleep()函数需要使用try-catch语句进行包围 try { Thread.sleep(mSpeed); } catch (InterruptedException e) { e.printStackTrace(); } } } }.start(); }

在View的构造方法中我们分别获取了我们自定义的4个属性,并且设置了默认值,这样即使在layout布局文件中不设置这4个自定义属性,仍然可以保证有值。

在构造方法中还开启了一个线程,这个线程主要的目的就是更新mProgress并且刷新界面,mProgress每增加1,就刷新界面一次,刷新界面是通过postInvalidate()方法来实现的。

因为这里并不需要onMeasure()操作,因此省去onMeasure()的实现,我们直接看onDraw()函数。

重写onDraw

onDraw()函数的内容如下:

@Override protected void onDraw(Canvas canvas) { // 获得中心点 int centre = getWidth() / 2; // 获得半径 int radius = centre - mCircleWidth / 2; // 设置空心线宽 mPaint.setStrokeWidth(mCircleWidth); // 抗锯齿 mPaint.setAntiAlias(true); // 只绘制图形轮廓(描边) mPaint.setStyle(Paint.Style.STROKE); // 指定圆弧的外轮廓矩形区域 RectF oval = new RectF(centre - radius, centre - radius, centre + radius, centre + radius); if (!mIsNext) { // 设置圆环的颜色 mPaint.setColor(mFirstColor); // 画出圆环 canvas.drawCircle(centre, centre, radius, mPaint); // 设置圆弧的颜色 mPaint.setColor(mSecondColor); // 根据进度画圆弧 canvas.drawArc(oval, -90, mProgress, false, mPaint); } else { // 设置圆环的颜色 mPaint.setColor(mSecondColor); // 画出圆环 canvas.drawCircle(centre, centre, radius, mPaint); // 设置圆弧的颜色 mPaint.setColor(mFirstColor); // 根据进度画圆弧 canvas.drawArc(oval, -90, mProgress, false, mPaint); } // canvas.drawRect(oval, mPaint); }

其实也没啥特别要说的,就是绘制圆环和圆弧,下面我想介绍下drawArc()函数。

`drawArc()函数的原型如下:

public void drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter, Paint paint)

其各个参数的含义如下:

oval:指定圆弧的外轮廓矩形区域startAngle:圆弧起始角度,单位为度sweepAngle:圆弧扫过的角度,顺时针方向,单位为度useCenter:当为true时,在绘制圆弧时将圆心包括在内,通常用来绘制扇形paint:绘制圆弧的画笔

第一个参数oval我纠结了蛮久,一直没搞懂是什么意思,其实呢,就是圆弧的外切圆,比如在我们的程序中:

RectF oval = new RectF(centre - radius, centre - radius, centre + radius, centre + radius);

绘制的矩形正好是圆弧的外切矩形,在上面这段程序中你可以取消最后一行的注释,查看绘制的矩形到底是什么样的。

总结

其实我是想上一张动图的,但是尼玛使用GifCam录制动图得到的动图总是颜色凌乱,还没搞懂,等我搞懂了搞张图上来。

转载请注明原文地址: https://www.6miu.com/read-31029.html

最新回复(0)