android 自定义view实现仿QQ运动步数进度效果
最近公司在策划一个新的项目,原型还没出来,再说这公司人都要走没了,估计又要找工作了,所以必须要学习,争取每个写个关于自定义view方面的,这样几个月积累下来,也能学习到东西,今天就带来简单的效果,就是仿QQ运动步数的进度条效果.在这就不分析了,直接贴代码,
自定义属性:
<?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="QQMovementView"> <attr name="defaultCircleColor" format="color|reference"></attr> <attr name="ProgressColor" format="color|reference"></attr> <attr name="CustomTextColor" format="color|reference"></attr> <attr name="CustomTextSize" format="dimension|reference"></attr> <attr name="BorderWidth" format="integer|reference"></attr> <attr name="ProgressMax" format="integer|reference"></attr> <attr name="currentProgress" format="integer|reference"></attr> <attr name="CustomStartAngle" format="integer|reference"></attr> <attr name="CustomSweepAngle" format="integer|reference"></attr> </declare-styleable> </resources>
自定义View
package com.day01; 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 zhouguizhijxhz on 2018/5/24. */ public class QQMovementView extends View { private static final String TAG = "QQMovementView"; private Paint progressPaint; private Paint textPaint; private Paint circlePaint; private int defaultCircleColor = Color.parseColor("#FF82AB"); private int defaultTextColor = Color.parseColor("#ff3f3f"); private int defaultTextSize = 24; private int borderWidth = 12; private int progressColor = Color.parseColor("#FFA07A"); private int max = 100; private int currentProgress = 10; private int startAngle = 135; private int sweepAngle = 270; public QQMovementView(Context context) { this(context, null); } public QQMovementView(Context context, @Nullable AttributeSet attrs) { this(context, attrs, 0); } public QQMovementView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); initAttrs(context, attrs); initTextPaint(context); initCirclePaint(); initProgressPaint(); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int width = measureWidth(widthMeasureSpec); int height = measureHeight(heightMeasureSpec); setMeasuredDimension(Math.min(width, height), Math.min(width, height)); } private int measureHeight(int heightMeasureSpec) { int mode = MeasureSpec.getMode(heightMeasureSpec); int height = MeasureSpec.getSize(heightMeasureSpec); if (mode == MeasureSpec.AT_MOST) { height = 360; } return height; } private int measureWidth(int widthMeasureSpec) { int mode = MeasureSpec.getMode(widthMeasureSpec); int width = MeasureSpec.getSize(widthMeasureSpec); if (mode == MeasureSpec.AT_MOST) { width = 360; } return width; } private void initProgressPaint() { progressPaint = new Paint(); progressPaint.setColor(progressColor); progressPaint.setStrokeWidth(borderWidth); progressPaint.setStyle(Paint.Style.STROKE); progressPaint.setStrokeCap(Paint.Cap.ROUND); progressPaint.setAntiAlias(true); } private void initCirclePaint() { circlePaint = new Paint(); circlePaint.setColor(defaultCircleColor); circlePaint.setStrokeWidth(borderWidth); circlePaint.setStyle(Paint.Style.STROKE); circlePaint.setStrokeCap(Paint.Cap.ROUND); circlePaint.setAntiAlias(true); } private void initTextPaint(Context context) { textPaint = new Paint(); textPaint.setColor(defaultTextColor); textPaint.setTextSize(sp2px(context,defaultTextSize)); } private void initAttrs(Context context, AttributeSet attrs) { if (null == context || null == attrs) { return; } TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.QQMovementView); defaultCircleColor = typedArray.getColor(R.styleable.QQMovementView_defaultCircleColor, defaultCircleColor); defaultTextColor = typedArray.getColor(R.styleable.QQMovementView_CustomTextColor, defaultTextColor); defaultTextSize = typedArray.getDimensionPixelSize(R.styleable.QQMovementView_CustomTextSize, defaultTextSize); progressColor = typedArray.getColor(R.styleable.QQMovementView_ProgressColor, progressColor); borderWidth = typedArray.getInteger(R.styleable.QQMovementView_BorderWidth, borderWidth); max = typedArray.getInteger(R.styleable.QQMovementView_ProgressMax,max); currentProgress = typedArray.getInteger(R.styleable.QQMovementView_currentProgress,currentProgress); startAngle = typedArray.getInteger(R.styleable.QQMovementView_CustomStartAngle,startAngle); sweepAngle = typedArray.getInteger(R.styleable.QQMovementView_CustomSweepAngle,sweepAngle); Log.e(TAG,"max--->"+max); Log.e(TAG,"currentProgress--->"+currentProgress); typedArray.recycle(); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); drawArc(canvas); drawProgressArc(canvas); drawProgressText(canvas); } private void drawProgressText(Canvas canvas) { if (null == canvas) { return; } String strPercent = String.valueOf(currentProgress); Paint.FontMetricsInt fm = textPaint.getFontMetricsInt(); canvas.drawText(strPercent, getWidth() / 2 - textPaint.measureText(strPercent) / 2, getHeight() / 2 - (fm.bottom + fm.top) / 2, textPaint); } private void drawProgressArc(Canvas canvas) { if (null == canvas) { return; } if (max == 0) { return; } if (currentProgress == 0) { return; } RectF rectF = new RectF(borderWidth / 2, borderWidth / 2, getMeasuredWidth() - borderWidth / 2, getMeasuredHeight() - borderWidth / 2); float percent = (float) currentProgress / max; Log.e(TAG,"percent------->"+percent); canvas.drawArc(rectF, startAngle, sweepAngle * percent, false, progressPaint); } private void drawArc(Canvas canvas) { if (null == canvas) { return; } RectF rectF = new RectF(borderWidth / 2, borderWidth / 2, getMeasuredWidth() - borderWidth / 2, getMeasuredHeight() - borderWidth / 2); canvas.drawArc(rectF, startAngle, sweepAngle, false, circlePaint); } public static int sp2px(Context context, float spValue) { final float fontScale = context.getResources().getDisplayMetrics().scaledDensity; return (int) (spValue * fontScale + 0.5f); } public void setMax(int max) { this.max = max; } public void setCurrentProgress(int currentProgress) { this.currentProgress = currentProgress; } }
布局:
<?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" android:layout_width="match_parent" android:layout_height="match_parent" > <com.day01.QQMovementView android:layout_width="240dp" android:layout_height="240dp" android:layout_centerHorizontal="true" android:layout_marginRight="60dp" android:layout_marginTop="60dp" app:currentProgress="30" app:ProgressMax="200" /> </RelativeLayout>
效果: