問(wèn)題
- 如何線性顏色變化?
Shader mShader = new LinearGradient(pointX - raduis, pointY, pointX + raduis, pointY,
new int[]{0xFF445EED, 0xFF072AE9, 0xFF0625CE}, null, Shader.TileMode.CLAMP);
完整的自定義View
public class SpeedControlView extends View implements Runnable {
//畫(huà)筆
private Paint mPaint, textPaint, speedAreaPaint;
private Context mContext;
//屏幕寬高
private int screenWidth, screenHeight;
//儀表盤(pán)圓的半徑
private float raduis, sRaduis;
//圓心
private int pointX, pointY;
//文字的偏移量
private float textScale;
//速度指針變化的位置
private float linePointerX, linePointerY;
//速度
private int speed;
//速度范圍的2個(gè)扇形外切矩形
private RectF speedRectF, speedRectFInner;
//速度控制模式 1 加速 2 減速 3 手剎
private int type;
// 速度文字 繪制的XY坐標(biāo)
private int baseX, baseY;
//屏幕密度
private float mDensityDpi;
//設(shè)置速度控制模式
public void setType(int type) {
this.type = type;
}
//開(kāi)始重繪
private boolean start = true;
public void setStart(boolean start) {
this.start = start;
}
// 設(shè)置速度 并重繪視圖
public void setSpeed(int speed) {
this.speed = speed;
if (speed > 0) {
postInvalidate();
}
}
public SpeedControlView(Context context) {
this(context, null);
}
public SpeedControlView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public SpeedControlView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mContext = context;
//獲取屏幕寬高
// screenWidth = ((Activity) context).getWindowManager().getDefaultDisplay().getWidth();
// screenHeight = ((Activity) context).getWindowManager().getDefaultDisplay().getHeight();
//獲取屏幕寬高 和 屏幕密度dpi
DisplayMetrics displayMetrics = getResources().getDisplayMetrics();
screenWidth = displayMetrics.widthPixels;
screenHeight = displayMetrics.heightPixels;
mDensityDpi = displayMetrics.densityDpi / 320; //320為我的測(cè)試機(jī)dpi密度油猫,以次繪制視圖
//關(guān)閉硬件加速
setLayerType(LAYER_TYPE_SOFTWARE, null);
//設(shè)置抗鋸齒
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setAntiAlias(true);
//設(shè)置畫(huà)筆樣式
mPaint.setStyle(Paint.Style.FILL);
mPaint.setStrokeWidth(5 * mDensityDpi);
//初始化 圓心左邊 和 半徑
raduis = screenWidth / 3;
pointX = pointY = screenWidth / 2;
// pointY = screenHeight / 4;
//設(shè)置抗鋸齒
textPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
textPaint.setAntiAlias(true);
//設(shè)置畫(huà)筆顏色
textPaint.setColor(Color.WHITE);
// 獲取字體并設(shè)置畫(huà)筆字體
Typeface typeface = Typeface.createFromAsset(mContext.getAssets(), "kt.ttf");
textPaint.setTypeface(typeface);
//設(shè)置抗鋸齒
speedAreaPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
speedAreaPaint.setAntiAlias(true);
//設(shè)置畫(huà)筆樣式
speedAreaPaint.setStyle(Paint.Style.FILL);
// 設(shè)置速度范圍扇形的漸變顏色
Shader mShader = new LinearGradient(pointX - raduis, pointY, pointX + raduis, pointY,
new int[]{0xFF445EED, 0xFF072AE9, 0xFF0625CE}, null, Shader.TileMode.CLAMP);
speedAreaPaint.setShader(mShader);
// 初始化速度范圍的2個(gè)扇形外切矩形
speedRectF = new RectF(pointX - raduis + 10 * mDensityDpi, pointY - raduis + 10 * mDensityDpi,
pointX + raduis - 10 * mDensityDpi, pointY + raduis - 10 * mDensityDpi);
speedRectFInner = new RectF(pointX - raduis / 2, pointY - raduis / 2,
pointX + raduis / 2, pointY + raduis / 2);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawColor(Color.YELLOW);
//繪制外層圓奔滑,兩個(gè)外圈祟牲,兩個(gè)內(nèi)圈
drawCicle(canvas);
//繪制速度范圍扇形區(qū)域
speedAreaPaint.setColor(0x7E3F51B5);
drawSpeedArea(canvas);
//變換畫(huà)筆顏色 繪制刻度
mPaint.setColor(0xBF3F6AB5);
drawScale(canvas);
//變換畫(huà)筆顏色 繪制速度標(biāo)識(shí)文字
textPaint.setTextSize(25 * mDensityDpi);
mPaint.setColor(Color.WHITE);
sRaduis = raduis - 50 * mDensityDpi;
textScale = Math.abs(textPaint.descent() + textPaint.ascent()) / 2;
Log.e("textScale", textScale + "");
drawText(canvas);
//繪制中間文字內(nèi)容
drawCenter(canvas);
}
/**
* 繪制外層圓
*/
private void drawCicle(Canvas canvas) {
mPaint.setStyle(Paint.Style.FILL);
mPaint.setColor(0xFF343434);
canvas.drawCircle(pointX, pointY, raduis, mPaint);
//外圈2個(gè)圓
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setColor(0xBF3F6AB5);
mPaint.setStrokeWidth(4 * mDensityDpi);
canvas.drawCircle(pointX, pointY, raduis, mPaint);
mPaint.setStrokeWidth(3 * mDensityDpi);
canvas.drawCircle(pointX, pointY, raduis - 10 * mDensityDpi, mPaint);
//內(nèi)圈2個(gè)圓
mPaint.setStrokeWidth(5 * mDensityDpi);
mPaint.setColor(0xE73F51B5);
canvas.drawCircle(pointX, pointY, raduis / 2, mPaint);
mPaint.setColor(0x7E3F51B5);
canvas.drawCircle(pointX, pointY, raduis / 2 + 5 * mDensityDpi, mPaint);
mPaint.setStrokeWidth(3 * mDensityDpi);
}
/**
* 繪制速度區(qū)域扇形
*/
private void drawSpeedArea(Canvas canvas) {
int degree;
if (speed < 210) {
degree = speed * 36 / 30;
} else {
degree = 210 * 36 / 30;
}
canvas.drawArc(speedRectF, 144, degree, true, speedAreaPaint);
// TODO: 2016/5/12
//不顯示中間的內(nèi)圈的扇形區(qū)域
mPaint.setColor(0xFF343434);
mPaint.setStyle(Paint.Style.FILL);
canvas.drawArc(speedRectFInner, 144, degree, true, mPaint);
mPaint.setStyle(Paint.Style.STROKE);
}
/**
* 繪制刻度
*/
private void drawScale(Canvas canvas) {
for (int i = 0; i < 60; i++) {
if (i % 6 == 0) {
canvas.drawLine(pointX - raduis + 10 * mDensityDpi, pointY, pointX - raduis + 50 * mDensityDpi, pointY, mPaint);
} else {
canvas.drawLine(pointX - raduis + 10 * mDensityDpi, pointY, pointX - raduis + 30 * mDensityDpi, pointY, mPaint);
}
canvas.rotate(6, pointX, pointY);
}
}
/**
* 繪制速度標(biāo)識(shí)文字
*/
private void drawText(Canvas canvas) {
// canvas.save();
// canvas.rotate(-36, pointX, pointY);
for (int i = 0; i < 8; i++) {
int value = 30 * i;
String TEXT = String.valueOf(value);
switch (value) {
case 0:
// 計(jì)算Baseline繪制的起點(diǎn)X軸坐標(biāo)
baseX = (int) (pointX - sRaduis * Math.cos(Math.PI / 5) + textPaint.measureText(TEXT) / 2 + textScale / 2);
// 計(jì)算Baseline繪制的Y坐標(biāo)
baseY = (int) (pointY + sRaduis * Math.sin(Math.PI / 5) + textScale / 2);
break;
case 30:
baseX = (int) (pointX - raduis + 50 * mDensityDpi + textPaint.measureText(TEXT) / 2);
baseY = (int) (pointY + textScale);
break;
case 60:
baseX = (int) (pointX - sRaduis * Math.cos(Math.PI / 5) + textScale);
baseY = (int) (pointY - sRaduis * Math.sin(Math.PI / 5) + textScale * 2);
break;
case 90:
baseX = (int) (pointX - sRaduis * Math.cos(2 * Math.PI / 5) - textScale / 2);
baseY = (int) (pointY - sRaduis * Math.sin(2 * Math.PI / 5) + 2 * textScale);
break;
case 120:
baseX = (int) (pointX + sRaduis * Math.sin(Math.PI / 10) - textPaint.measureText(TEXT) / 2);
baseY = (int) (pointY - sRaduis * Math.cos(Math.PI / 10) + 2 * textScale);
break;
case 150:
baseX = (int) (pointX + sRaduis * Math.cos(Math.PI / 5) - textPaint.measureText(TEXT) - textScale / 2);
baseY = (int) (pointY - sRaduis * Math.sin(Math.PI / 5) + textScale * 2);
break;
case 180:
baseX = (int) (pointX + sRaduis - textPaint.measureText(TEXT) - textScale / 2);
baseY = (int) (pointY + textScale);
break;
case 210:
baseX = (int) (pointX + sRaduis * Math.cos(Math.PI / 5) - textPaint.measureText(TEXT) - textScale / 2);
baseY = (int) (pointY + sRaduis * Math.sin(Math.PI / 5) - textScale / 2);
break;
}
// baseX = (int) (pointX - raduis + 50 * mDensityDpi + textPaint.measureText(TEXT) / 2);
// baseY = (int) (pointY + textScale);
canvas.drawText(TEXT, baseX, baseY, textPaint);
// canvas.rotate(36, pointX, pointY);
}
// canvas.restore();
}
/**
* 繪制中間文字內(nèi)容
*/
private void drawCenter(Canvas canvas) {
//速度
textPaint.setTextSize(60 * mDensityDpi);
float tw = textPaint.measureText(String.valueOf(speed));
baseX = (int) (pointX - tw / 2);
baseY = (int) (pointY + Math.abs(textPaint.descent() + textPaint.ascent()) / 4);
canvas.drawText(String.valueOf(speed), baseX, baseY, textPaint);
//單位
textPaint.setTextSize(20 * mDensityDpi);
tw = textPaint.measureText("km/h");
baseX = (int) (pointX - tw / 2);
baseY = (int) (pointY + raduis / 4 + Math.abs(textPaint.descent() + textPaint.ascent()) / 4);
canvas.drawText("km/h", baseX, baseY, textPaint);
}
@Override
public void run() {
int speedChange;
while (start) {
switch (type) {
case 1://油門(mén)
speedChange = 3;
break;
case 2://剎車
speedChange = -5;
break;
case 3://手剎
speed = 0;
default:
speedChange = -1;
break;
}
speed += speedChange;
if (speed < 1) {
speed = 0;
}
try {
Thread.sleep(50);
setSpeed(speed);
} catch (InterruptedException e) {
e.printStackTrace();
break;
}
}
}
}
調(diào)用:
@Override
protected void onResume() {
super.onResume();
if (speedControlView != null) {
speedControlView.setSpeed(0);
speedControlView.setStart(true);
}
new Thread(speedControlView).start();
}
@Override
protected void onStop() {
super.onStop();
if (speedControlView != null) {
speedControlView.setSpeed(0);
speedControlView.setStart(false);
}
}