推荐个音乐下载app【佳语音乐下载】
https://gitlab.com/gaopinqiang/checkversion/raw/master/Music_Download.apk
开发有时会用到仪表盘(例如测速,类似汽车仪表盘),这里我们自定义个View来实现这个功能,还支持指针动画,避免过于生硬。
先给个效果图:
下面是具体的实现代码(在真机上测试通过):
DashboardView.java
package com.example.dashboardView;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.SweepGradient;
import android.os.Build;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.View;
import com.example.testgesturedetector.R;
/**
* 自定义测速仪表盘
* 直接继承View需要处理wrap_content 时onMeasure方法的宽高
*/
public class DashboardView extends View {
/** 定义一些缺省值 */
private int mRadius; // 扇形半径
private int mStartAngle = 150; // 起始角度,180-30度(左边平行夹角30度)
private int mSweepAngle = 240; // 绘制角度,360+30度 = 150+240度
private int mMin = 0; // 最小值
private int mMax = 100; // 最大值
private int mSection = 8; // 值域(mMax-mMin)等分份数
private int mPortion = 5; // 一个mSection等分份数
private String mHeaderText = ""; // 表头 Mbps
private int mVelocity = mMin; // 实时速度
private int mStrokeWidth; // 画笔宽度
private int mLength1; // 长刻度的相对圆弧的长度
private int mLength2; // 刻度读数顶部的相对圆弧的长度
private int mPLRadius; // 指针长半径
private int mPSRadius; // 指针短半径
private int mPadding;
private float mCenterX, mCenterY; // 圆心坐标
private Paint mPaint;
private RectF mRectFArc;
private Path mPath;
private RectF mRectFInnerArc;
private Rect mRectText;
private String[] mTexts;
private int[] mColors;
private Context mContext;
public DashboardView(Context context) {
this(context, null);
mContext = context;
}
public DashboardView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
mContext = context;
}
public DashboardView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mContext = context;
init();
}
@TargetApi(Build.VERSION_CODES.M)
private void init() {
mStrokeWidth = dp2px(3);
mLength1 = dp2px(8) + mStrokeWidth;
mLength2 = mLength1 + dp2px(4);
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mRectFArc = new RectF();
mPath = new Path();
mRectFInnerArc = new RectF();
mRectText = new Rect();
mTexts = new String[mSection + 1]; // 需要显示mSection + 1个刻度读数
for (int i = 0; i < mTexts.length; i++) {
int n = (mMax - mMin) / mSection;
mTexts[i] = String.valueOf(mMin + i * n);
}
// TODO: 2020/4/20 重置刻度盘
mTexts[0] = "0M";
mTexts[1] = "1M";
mTexts[2] = "2M";
mTexts[3] = "5M";
mTexts[4] = "10M";
mTexts[5] = "20M";
mTexts[6] = "50M";
mTexts[7] = "80M";
mTexts[8] = "100M";
mColors = new int[]{
mContext.getColor(R.color.color_green),
mContext.getColor(R.color.color_yellow),
mContext.getColor(R.color.color_red)
};
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
mPadding = Math.max(
Math.max(getPaddingLeft(), getPaddingTop()),
Math.max(getPaddingRight(), getPaddingBottom())
);
setPadding(mPadding, mPadding, mPadding, mPadding);
int width = resolveSize(dp2px(260), widthMeasureSpec);
mRadius = (width - mPadding * 2 - mStrokeWidth * 2) / 2;
// 由起始角度确定的高度
float[] point1 = getCoordinatePoint(mRadius, mStartAngle);
// 由结束角度确定的高度
float[] point2 = getCoordinatePoint(mRadius, mStartAngle + mSweepAngle);
int height = (int) Math.max(point1[1] + mRadius + mStrokeWidth * 2,
point2[1] + mRadius + mStrokeWidth * 2);
// TODO: 2020/4/20 需要处理高度
// setMeasuredDimension(width, height + getPaddingTop() + getPaddingBottom());
setMeasuredDimension(width, width);
mCenterX = mCenterY = getMeasuredWidth() / 2f;
mRectFArc.set(
getPaddingLeft() + mStrokeWidth,
getPaddingTop() + mStrokeWidth,
getMeasuredWidth() - getPaddingRight() - mStrokeWidth,
getMeasuredWidth() - getPaddingBottom() - mStrokeWidth
);
mPaint.setTextSize(sp2px(16));
mPaint.getTextBounds("0"