实现自定义控件小圆环效果;
First:我们定义一个attrs.xml 在values包里
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="MyProgressRound">
<attr name="progressColor" format="color"/>
<attr name="textSize" format="dimension"/>
<attr name="ringSize" format="dimension"/>
<attr name="radiuSize" format="dimension"/>
</declare-styleable>
</resources>
Second:建立实类MyProgressRound继承view:
package com.example.weekone;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
/**
* Created by dd
* 在xml里面可以设置 进度圆环的属性
* 1、颜色
* 2、文本大小
* 3、粗细
* 4、圆环半径
*
* ***** values文件夹里面 创建一个attrs.xml
* ***** 命名控件 namesp ?
* <>
* <attr name="layout_width" format=""><attr/>
* </>
*/
public class MyProgressRound extends View{
Paint paint;
private int mProgress = 0;
private int mCountProgress = 0;
private float mRadiuSize = 0;
private float mRingSize = 0;
private float mTextSize = 0;
private int mProgressColor = 0;
public MyProgressRound(Context context) {
super(context);
init();
}
/**
* 所有在xml布局文件中 标签里面声明的属性 都可以在AttributeSet类的对象中获取出来
* @param context
* @param attrs
*/
public MyProgressRound(Context context, @Nullable AttributeSet attrs) {
//在该构造方法中可以获取到 所有参数
//把参数传出去 在onDraw方法中可以操作 onMeasure中也可以操作
super(context, attrs);
getCustomAttr(context, attrs);
init();
}
private void getCustomAttr(Context context, AttributeSet attrs) {
TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.MyProgressRound);
mRadiuSize = array.getDimension(R.styleable.MyProgressRound_radiuSize, 100);
mRingSize = array.getDimension(R.styleable.MyProgressRound_ringSize, 10);
mTextSize = array.getDimension(R.styleable.MyProgressRound_textSize, 10);
mProgressColor = array.getColor(R.styleable.MyProgressRound_progressColor, Color.BLACK);
}
public MyProgressRound(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
public void init(){
paint = new Paint();
paint.setAntiAlias(true);
}
//widthMeasureSpec/heightMeasureSpec 是一个32为的int类型
//01000000 00000000 00000000 00000000
//高两位 代表类型
//warpcontent类型 MeasureSpec.AT_MOST
//matchparent类型 MeasureSpec.EXACTLY 或者具体的长度 100dp 200dp
// 其他类型
//
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
int width = 0;
int height = 0;
if(widthMode == MeasureSpec.AT_MOST){
width = (int) (mRadiuSize * 2);
}else{
width = Math.max(widthSize, (int) (mRadiuSize * 2));
}
if(heightMode == MeasureSpec.AT_MOST){
height = (int) (mRadiuSize * 2);
}else{
height = Math.max(heightSize, (int) (mRadiuSize * 2));
}
setMeasuredDimension(width, height);
// switch (widthMode){
// case MeasureSpec.AT_MOST:
// //如果宽度使用的是warp_content那么 我们需要手动设置控件的宽值, 标准是宽是半径的2倍
// Log.i("=============widthMode", "onMeasure: " + "AT_MOST---> warp_content");
// //确定了宽高后,修改控件的宽高
// setMeasuredDimension((int)(mRadiuSize * 2), (int)(mRadiuSize * 2));
// break;
// case MeasureSpec.EXACTLY:
// Log.i("=============widthMode", "onMeasure: " + "Exactly---> match_parent");
// break;
// }
//
// switch (heightMode){
// case MeasureSpec.AT_MOST:
// Log.i("=============heightMode", "onMeasure: " + "AT_MOST---> warp_content");
// break;
// case MeasureSpec.EXACTLY:
// Log.i("=============heightMode", "onMeasure: " + "Exactly---> match_parent");
// break;
// }
}
@Override
protected void onDraw(Canvas canvas) {
//在布局文件中设置的圆环半径大小就可以不用写死
paint.setStrokeWidth(0);
paint.setColor(Color.BLACK);
paint.setStyle(Paint.Style.STROKE);
canvas.drawCircle(getMeasuredWidth()/2, getMeasuredHeight()/2, mRadiuSize, paint);
canvas.drawCircle(getMeasuredWidth()/2, getMeasuredHeight()/2, mRadiuSize - mRingSize, paint);
paint.setTextSize(mTextSize);
String text = mCountProgress + "%";
float textWidth = paint.measureText(text);
canvas.drawText(text, getMeasuredWidth()/2-textWidth/2 , getMeasuredWidth()/2 + mTextSize/2, paint);
RectF rectF = new RectF(getMeasuredWidth()/2 - mRadiuSize + mRingSize/2,getMeasuredHeight()/2 - mRadiuSize + mRingSize/2,getMeasuredWidth()/2 + mRadiuSize - mRingSize/2,getMeasuredHeight()/2 + mRadiuSize - mRingSize/2);
paint.setStrokeWidth(mRingSize);
paint.setColor(mProgressColor);
canvas.drawArc(rectF, 0, mProgress, false, paint);
}
public void setProgress(int progress){
mProgress = progress;
mCountProgress = progress * 100 / 360;
invalidate();
}
}
Threed: 在布局文件里初始化控件:
<?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.example.weekone.MainActivity">
<com.example.weekone.MyProgressRound
android:id="@+id/mpr"
android:layout_width="100dp"
android:layout_height="100dp"
android:background="#f00"
app:ringSize="10dp"
app:progressColor="#883399"
app:radiuSize="100dp"
app:textSize="20sp"
android:layout_centerInParent="true"
/>
</RelativeLayout>
Last:我们在MainActivity里面实现具体的操作:
package com.example.weekone;
import android.os.AsyncTask;
import android.os.SystemClock;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.ImageView;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
MyProgressRound mpr;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mpr = (MyProgressRound) findViewById(R.id.mpr);
new AsyncTask<String, Integer, String>(){
@Override
protected String doInBackground(String... params) {
for (int i = 0; i <= 360; i++) {
SystemClock.sleep(10);
publishProgress(i);
}
return null;
}
//该方法的调用条件是 publishProgress
@Override
protected void onProgressUpdate(Integer... values) {
mpr.setProgress(values[0]);
}
}.execute();
}
}
网友评论