继续我们的自定义View之旅。 今天要实现的效果
首先我们看到这样的效果,如果是你,你会怎么去实现,我们来分析下,需要哪些属性。
- 2种颜色
- 速度
- 圆环的宽度
- 是否圆环交替显示
老规矩先自定义我们的属性:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="Myview">
<attr name="OneColor" format="color"/>
<attr name="TwoColr" format="color"/>
<attr name="CriWidth" format="dimension"/>
<attr name="speed" format="integer"/>
<attr name="ring" format="boolean"/>
</declare-styleable>
</resources>
接着我们在布局中使用我们自定义的属性:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:gravity="center_horizontal"
android:orientation="vertical">
<com.linchaokun.customview3.view.MyView
android:layout_width="300dp"
android:layout_height="0dp"
android:layout_weight="1"
app:OneColor="@color/colorAccent"
app:TwoColr="@color/colorPrimary"
app:CriWidth="30dp"
app:speed="10"/>
<com.linchaokun.customview3.view.MyView
android:layout_width="300dp"
android:layout_height="0dp"
android:layout_weight="1"
app:OneColor="@color/colorAccent"
app:TwoColr="@color/colorPrimary"
app:CriWidth="30dp"
app:speed="10"
app:ring="true"/>
</LinearLayout>
这里一个画饼图,一个画圆环交替效果(app:ring="true")。
接下来就是我们的重点自定义的View:
package com.linchaokun.customview3.view;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.util.Log;
import android.util.TypedValue;
import android.view.View;
import com.linchaokun.customview3.R;
/**
* 作者:linchaokun on 2016/7/31 20:46
* 邮箱:812086325@qq.com
*/
public class MyView extends View{
//第一个圆的颜色
private int mOneColor;
//第二个圆的颜色
private int mTwoColor;
//圆环的宽度
private int mCriWidth;
//速度
private int mSpeed;
//是否开始下一个
private boolean isNext = false;
//当前进度
private int mProgress;
//是否圆环交替
private boolean mRing;
//画笔
private Paint mPaint;
public MyView(Context context) {
this(context,null);
}
public MyView(Context context, AttributeSet attrs) {
this(context, attrs,0);
}
public MyView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
TypedArray array = context.getTheme().obtainStyledAttributes(attrs, R.styleable.Myview, defStyleAttr, 0);
//第一个圆颜色
mOneColor = array.getColor(R.styleable.Myview_OneColor, getResources().getColor(R.color.colorAccent));
//第二个圆的颜色
mTwoColor = array.getColor(R.styleable.Myview_TwoColr,getResources().getColor(R.color.colorPrimaryDark));
//圆环的宽度
mCriWidth = array.getDimensionPixelSize(R.styleable.Myview_CriWidth, (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,16,getResources().getDisplayMetrics()));
//圆环速率
mSpeed = array.getInteger(R.styleable.Myview_speed,0);
//是否圆环交替
mRing = array.getBoolean(R.styleable.Myview_ring,false);
array.recycle();
initPaint();
initThread();
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int centre = getWidth() / 2; // 获取圆心的x坐标
int radius = centre - mCriWidth / 2;// 半径
mPaint.setStrokeWidth(mCriWidth); // 设置圆环的宽度
mPaint.setAntiAlias(true); // 消除锯齿
if(mRing){
mPaint.setStyle(Paint.Style.STROKE); // 设置空心
}else{
mPaint.setStyle(Paint.Style.FILL); // 设置实心
}
RectF oval = new RectF(centre - radius, centre - radius, centre + radius, centre + radius); // 用于定义的圆弧的形状和大小的界限
if (!isNext)
{// 第一颜色的圈完整,第二颜色跑
mPaint.setColor(mOneColor); // 设置圆环的颜色
canvas.drawCircle(centre, centre, radius, mPaint); // 画出圆环
mPaint.setColor(mTwoColor); // 设置圆环的颜色
canvas.drawArc(oval, -90, mProgress, mRing?false:true, mPaint); // 根据进度画圆弧
} else
{
mPaint.setColor(mTwoColor); // 设置圆环的颜色
canvas.drawCircle(centre, centre, radius, mPaint); // 画出圆环
mPaint.setColor(mOneColor); // 设置圆环的颜色
canvas.drawArc(oval, -90, mProgress, mRing?false:true, mPaint); // 根据进度画圆弧
}
}
private void initThread() {
new Thread(new Runnable() {
@Override
public void run() {
while (true){
mProgress++;
if(mProgress==360){
mProgress=0;
if(!isNext){
isNext=true;
}else{
isNext=false;
}
}
postInvalidate();
try {
Thread.sleep(mSpeed);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
}
private void initPaint() {
mPaint = new Paint();
mPaint.setAntiAlias(true);
}
}
我们还是构造方法互调,在第三个构造方法写我们的代码。
构造方法我们获取到我们自定义的属性值,初始化我们的画笔,这里还初始化了一个线程。
相信看过前面文章的都很容易看懂本节课的内容,注释也写的听清楚了。