讲了这么多期了,大家多少应该明白自定义控件的套路了,如果还不明白,请把我的前五讲仔细复习一下,里面每一步讲的比较仔细,废话不多说,直接上码
第一步:创建自定义控件类 (继承于View)
第二步: 创建自定义属性
在这里,我们就不分析需要哪些自定义属性了,直接给大家上自定义属性文件,大家现在应该具备理解能力了
第三步:在布局文件中应用
第四步:获取自定义属性值 并 编写相应方法
package com.wustyq.senseone.selfView;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.View;
import androidx.annotation.Nullable;
import com.wustyq.senseone.R;
public class myProgress extends View {
private int mBgColor;
private int mOneColor;
private int mTwoColor;
private int mThreeColor;
private int mFourColor;
private int mBorderWidth;
private String mProgressText;
private int mProgressTextSize;
private int mProgressTextColor;
private int mRadius;
private Paint mBgPaint;
private Paint mOnePaint;
private Paint mTwoPaint;
private Paint mThreePaint;
private Paint mFourPaint;
private Paint mProgressPaint;
private Paint mTextPaint;
//当前进度
private float mCurrentProgress = 0.0f;
public myProgress(Context context) {
this(context,null);
}
public myProgress(Context context, @Nullable AttributeSet attrs) {
this(context, attrs,0);
}
public myProgress(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.myProgress);
mBgColor = typedArray.getColor(R.styleable.myProgress_bgColor,mBgColor);
mOneColor = typedArray.getColor(R.styleable.myProgress_oneColor,mOneColor);
mTwoColor = typedArray.getColor(R.styleable.myProgress_twoColor,mTwoColor);
mThreeColor = typedArray.getColor(R.styleable.myProgress_threeColor,mThreeColor);
mFourColor = typedArray.getColor(R.styleable.myProgress_fourColor,mFourColor);
mBorderWidth = (int) typedArray.getDimension(R.styleable.myProgress_borderWidth,dip2px(mBorderWidth));
mRadius = (int) typedArray.getDimension(R.styleable.myProgress_radius,mRadius);
mProgressText = typedArray.getString(R.styleable.myProgress_progressText);
mProgressTextSize = typedArray.getDimensionPixelSize(R.styleable.myProgress_progressTextSize,sp2px(mProgressTextSize));
mProgressTextColor = typedArray.getColor(R.styleable.myProgress_progressTextColor,mProgressTextColor);
//根据颜色获取画笔
mBgPaint = initPaint(mBgColor);
mOnePaint = initPaint(mOneColor);
mTwoPaint = initPaint(mTwoColor);
mThreePaint = initPaint(mThreeColor);
mFourPaint = initPaint(mFourColor);
mProgressPaint = initTextPaint(mProgressTextColor,mProgressTextSize);
mTextPaint = initTextPaint(Color.parseColor("#000000"),14);
typedArray.recycle();
}
private int sp2px(int sp) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,sp,getResources().getDisplayMetrics());
}
private float dip2px(int dip) {
return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,dip,getResources().getDisplayMetrics());
}
private Paint initTextPaint(int TextColor,int textSize) {
Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setDither(true);
paint.setTextSize(textSize);
paint.setColor(TextColor);
return paint;
}
private Paint initPaint(int Color) {
Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setDither(true);
paint.setStrokeWidth(mBorderWidth);
paint.setColor(Color);
return paint;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//保证是正方形
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = MeasureSpec.getSize(heightMeasureSpec);
setMeasuredDimension(width>height?height:width,width>height?height:width);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//绘制底部文字
mTextPaint.setTextSize(mProgressTextSize);
canvas.drawText(mProgressText,getWidth()/2-getTextWidth(mProgressText)/2, (float) (getHeight()/2+getTextHeight(mProgressText)),mTextPaint);
//绘制基圆
drawBgCircle(canvas);
//获取进度文字
String currentProgressString =(int) (mCurrentProgress*100) + "%";
if (mCurrentProgress >= 0.0f && mCurrentProgress <= 0.25f){
canvas.drawText(currentProgressString,getWidth()/2-getTextWidth(currentProgressString)/2,
(float) (getHeight()/2-getTextHeight(currentProgressString)*0.5),mProgressPaint);
drawArc(canvas,mOnePaint,0,360*mCurrentProgress);
}else if (mCurrentProgress > 0.25f && mCurrentProgress <= 0.5f){
canvas.drawText(currentProgressString,getWidth()/2-getTextWidth(currentProgressString)/2,
(float) (getHeight()/2-getTextHeight(currentProgressString)*0.5),mProgressPaint);
drawArc(canvas,mOnePaint,0,90);
drawArc(canvas,mTwoPaint,90, (float) (360*(mCurrentProgress - 0.25)));
}else if (mCurrentProgress > 0.5f && mCurrentProgress <= 0.75f){
canvas.drawText(currentProgressString,getWidth()/2-getTextWidth(currentProgressString)/2,
(float) (getHeight()/2-getTextHeight(currentProgressString)*0.5),mProgressPaint);
drawArc(canvas,mOnePaint,0,90);
drawArc(canvas,mTwoPaint,90, 90);
drawArc(canvas,mThreePaint,180,(float) (360*(mCurrentProgress - 0.5)));
}else if (mCurrentProgress > 0.75f && mCurrentProgress <= 1.0f){
canvas.drawText(currentProgressString,getWidth()/2-getTextWidth(currentProgressString)/2,
(float) (getHeight()/2-getTextHeight(currentProgressString)*0.5),mProgressPaint);
drawArc(canvas,mOnePaint,0,90);
drawArc(canvas,mTwoPaint,90, 90);
drawArc(canvas,mThreePaint,180,90);
drawArc(canvas,mFourPaint,270,(float) (360*(mCurrentProgress - 0.75)));
}
}
private void drawArc(Canvas canvas,Paint paint,float start,float end) {
paint.setStyle(Paint.Style.STROKE);
float left = getWidth()/2 - mRadius;
float top = getHeight()/2 -mRadius;
float right = getWidth()/2 + mRadius;
float bottom = getHeight()/2 + mRadius;
RectF rectf = new RectF(left,top,right,bottom);
canvas.drawArc(rectf,start,end,false,paint);
canvas.save();
}
private void drawBgCircle(Canvas canvas) {
mBgPaint.setStyle(Paint.Style.STROKE);
canvas.drawCircle(getWidth()/2,getHeight()/2,mRadius,mBgPaint);
}
//获取文字 width、height
private float getTextWidth(String str){
Rect bounds = new Rect();
mTextPaint.getTextBounds(str,0,str.length(),bounds);
return bounds.width();
}
private float getTextHeight(String str){
Rect bounds = new Rect();
mTextPaint.getTextBounds(str,0,str.length(),bounds);
return bounds.height();
}
//提供外界设置当前进度
public synchronized void setCurrentProgress(float progress) {
this.mCurrentProgress = progress;
invalidate();
}
}
在这里,比较费脑子的就是 如何让 圆弧 和 圆 重叠在一起,代码里面有公式,配合下面这张图理解
第五步:在外面使用
package com.wustyq.senseone.app;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.app.Activity;
import android.os.Bundle;
import android.view.Gravity;
import android.view.View;
import android.view.animation.BounceInterpolator;
import android.view.animation.DecelerateInterpolator;
import android.widget.Button;
import android.widget.Toast;
import com.wustyq.senseone.R;
import com.wustyq.senseone.selfView.myProgress;
public class MainActivity extends Activity implements View.OnClickListener {
private myProgress mp_myProgress;
private Button bt_test_one;
private int clickNum = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initWelcome();
initView();
initData();
}
private void initView() {
mp_myProgress = findViewById(R.id.mp_myProgress);
bt_test_one = findViewById(R.id.bt_test_one);
}
private void initData() {
bt_test_one.setOnClickListener(this);
}
private void initWelcome() {
Toast toast = Toast.makeText(this, null, Toast.LENGTH_SHORT);
toast.setText("欢迎来到第一感知,很高兴为您服务");
toast.setGravity(Gravity.CENTER,0,0);
toast.show();
}
@Override
public void onClick(View v) {
switch(v.getId()){
case R.id.bt_test_one:
{
System.out.println(clickNum + "clickNum");
if (clickNum == 0){
setValueObject(mp_myProgress,0.0f,0.25f);
clickNum++;
}else if (clickNum == 1){
setValueObject(mp_myProgress,0.25f,0.5f);
clickNum++;
}else if (clickNum == 2){
setValueObject(mp_myProgress,0.5f,0.75f);
clickNum++;
}else if (clickNum == 3){
setValueObject(mp_myProgress,0.75f,1.0f);
clickNum = 0;
}
}
break;
}
}
private void setValueObject(final myProgress view, float start, float end) {
ValueAnimator valueAnimator = ObjectAnimator.ofFloat(start, end);
valueAnimator.setDuration(2000);
valueAnimator.setInterpolator(new DecelerateInterpolator());
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float animatedValue = (float) animation.getAnimatedValue();
view.setCurrentProgress(animatedValue);
}
});
valueAnimator.start();
}
}
我计划多写几个组件,放在一起,然后把源码一起上传供大家参考!!!