編輯:關於Android編程
效果圖


直接在xml文件中添加即可,在代碼中調用setProgress(int) 即可。代碼注釋寫的很清楚,有興趣的隨便改改。
package com.xk.testdemo.view;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Rect;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import com.xk.testdemo.config.ConfigColor;
import static android.R.attr.angle;
import static android.R.attr.baseline;
import static android.R.attr.dial;
import static android.R.attr.end;
import static android.R.attr.path;
import static android.R.attr.radius;
import static android.R.attr.width;
import static android.R.attr.x;
import static android.R.attr.y;
/**
* Created by xuekai on 2016/10/26.
*/
public class InstrumentView extends View {
private String color_outcircle = "#DEDEDE";
private String color_bg_outcircle = "#2690F8";
private String color_bg_incircle = "#58ADE4";
private String color_progress = "#87CEEB";
private String color_smart_circle = "#C2B9B0";
private String color_indicator_left = "#E1DCD6";
private String color_indicator_right = "#F4EFE9";
/**
* 當前進度
*/
private int progress = 50;
/**
* 要畫的內容的實際寬度
*/
private int contentWidth;
/**
* view的實際寬度
*/
private int viewWidth;
/**
* view的實際高度
*/
private int viewHeight;
/**
* 外環線的寬度
*/
private int outCircleWidth = 1;
/**
* 外環的半徑
*/
private int outCircleRadius = 0;
/**
* 內環的半徑
*/
private int inCircleRedius = 0;
/**
* 內環與外環的距離
*/
private int outAndInDistance = 0;
/**
* 內環的寬度
*/
private int inCircleWidth = 0;
/**
* 刻度盤距離它外面的圓的距離
*/
private int dialOutCircleDistance = 0;
/**
* 內容中心的坐標
*/
private int[] centerPoint = new int[2];
/**
* 刻度線的數量
*/
private int dialCount = 0;
/**
* 每隔幾次出現一個長線
*/
private int dialPer = 0;
/**
* 長線的長度
*/
private int dialLongLength = 0;
/**
* 短線的長度
*/
private int dialShortLength = 0;
/**
* 刻度線距離圓心最遠的距離
*/
private int dialRadius = 0;
/**
* 圓弧開始的角度
*/
private int startAngle = 0;
/**
* 圓弧劃過的角度
*/
private int allAngle = 0;
private Paint mPaint;
/**
* 刻度盤上數字的數量
*/
private int figureCount = 6;
public InstrumentView(Context context) {
this(context, null);
}
public InstrumentView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public InstrumentView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
mPaint = new Paint();
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setAntiAlias(true);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
initValues();
}
/**
* 初始化尺寸
*/
private void initValues() {
viewWidth = getMeasuredWidth();
viewHeight = getMeasuredHeight();
contentWidth = viewWidth > viewHeight ? viewHeight : viewWidth;
outCircleRadius = contentWidth / 2 - outCircleWidth;
outAndInDistance = (int) (contentWidth / 26.5);
inCircleWidth = (int) (contentWidth / 18.7);
centerPoint[0] = viewWidth / 2;
centerPoint[1] = viewHeight / 2;
inCircleRedius = outCircleRadius - outAndInDistance - inCircleWidth / 2;
startAngle = 150;
allAngle = 240;
dialOutCircleDistance = inCircleWidth;
dialCount = 50;
dialPer = 5;
dialLongLength = (int) (dialOutCircleDistance / 1.2);
dialShortLength = (int) (dialLongLength / 1.8);
dialRadius = inCircleRedius - dialOutCircleDistance;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
drawStatic(canvas);
drawDynamic(canvas);
}
/**
* 繪制靜態的部分
*
* @param canvas
*/
private void drawStatic(Canvas canvas) {
drawOutCircle(canvas);
drawCircleWithRound(startAngle, allAngle, inCircleWidth, inCircleRedius, color_outcircle, canvas);
drawDial(startAngle, allAngle, dialCount, dialPer, dialLongLength, dialShortLength, dialRadius, canvas);
drawBackGround(canvas);
drawFigure(canvas, figureCount);
}
private void drawFigure(Canvas canvas, int count) {
int figure = 0;
int angle;
for (int i = 0; i < count; i++) {
figure = (int) (100 / (1f * count-1) * i);
angle = (int) ((allAngle) / ((count-1) * 1f) * i) + startAngle;
int[] pointFromAngleAndRadius = getPointFromAngleAndRadius(angle, dialRadius - dialLongLength * 2 );
mPaint.setTextSize(15);
mPaint.setTextAlign(Paint.Align.CENTER);
canvas.save();
canvas.rotate(angle+90,pointFromAngleAndRadius[0],pointFromAngleAndRadius[1]);
canvas.drawText(figure+"%",pointFromAngleAndRadius[0],pointFromAngleAndRadius[1],mPaint);
canvas.restore();
}
}
/**
* 畫內層背景
*
* @param canvas
*/
private void drawBackGround(Canvas canvas) {
mPaint.setColor(Color.parseColor(color_bg_outcircle));
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(outCircleRadius / 3 / 2);
canvas.drawCircle(centerPoint[0], centerPoint[1], outCircleRadius / 3, mPaint);
mPaint.setColor(Color.parseColor(color_bg_incircle));
mPaint.setStyle(Paint.Style.FILL);
canvas.drawCircle(centerPoint[0], centerPoint[1], (outCircleRadius / 3f / 2), mPaint);
}
/**
* 畫刻度盤
*
* @param startAngle 開始畫的角度
* @param allAngle 總共劃過的角度
* @param dialCount 總共的線的數量
* @param per 每隔幾個出現一次長線
* @param longLength 長仙女的長度
* @param shortLength 短線的長度
* @param radius 距離圓心最遠的地方的半徑
*/
private void drawDial(int startAngle, int allAngle, int dialCount, int per, int longLength, int shortLength, int radius, Canvas canvas) {
int length;
int angle;
for (int i = 0; i <= dialCount; i++) {
angle = (int) ((allAngle) / (dialCount * 1f) * i) + startAngle;
if (i % 5 == 0) {
length = longLength;
} else {
length = shortLength;
}
drawSingleDial(angle, length, radius, canvas);
}
}
/**
* 畫刻度中的一條線
*
* @param angle 所處的角度
* @param length 線的長度
* @param radius 距離圓心最遠的地方的半徑
*/
private void drawSingleDial(int angle, int length, int radius, Canvas canvas) {
int[] startP = getPointFromAngleAndRadius(angle, radius);
int[] endP = getPointFromAngleAndRadius(angle, radius - length);
canvas.drawLine(startP[0], startP[1], endP[0], endP[1], mPaint);
}
/**
* 畫最外層的圓
*
* @param canvas
*/
private void drawOutCircle(Canvas canvas) {
mPaint.setStrokeWidth(outCircleWidth);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setColor(Color.parseColor(color_outcircle));
canvas.drawCircle(centerPoint[0], centerPoint[1], outCircleRadius, mPaint);
}
/**
* 繪制動態的部分
*
* @param canvas
*/
private void drawDynamic(Canvas canvas) {
drawProgress(progress, canvas);
drawIndicator(progress, canvas);
drawCurrentProgressTv(progress, canvas);
}
/**
* 繪制當前進度是文字
*
* @param progress
* @param canvas
*/
private void drawCurrentProgressTv(int progress, Canvas canvas) {
// canvas.drawText("當前進度:"+progress+"%",);
mPaint.setTextSize(25);
mPaint.setTextAlign(Paint.Align.CENTER);
Paint.FontMetrics fontMetrics = mPaint.getFontMetrics();
float baseLine1 = centerPoint[1] + (outCircleRadius / 20f * 11 - fontMetrics.top - fontMetrics.bottom);
canvas.drawText("當前進度", centerPoint[0], baseLine1, mPaint);
float baseLine2 = outCircleRadius / 20f * 11 - 3 * (fontMetrics.bottom + fontMetrics.top) + centerPoint[1];
canvas.drawText(progress + "%", centerPoint[0], baseLine2, mPaint);
}
/**
* 畫指針以及他的背景
*
* @param progress
* @param canvas
*/
private void drawIndicator(int progress, Canvas canvas) {
drawPointer(canvas);
drawIndicatorBg(canvas);
}
/**
* 指針的最遠處的半徑和刻度線的一樣
*/
private void drawPointer(Canvas canvas) {
RectF rectF = new RectF(centerPoint[0] - (int) (outCircleRadius / 3f / 2 / 2),
centerPoint[1] - (int) (outCircleRadius / 3f / 2 / 2), centerPoint[0] + (int) (outCircleRadius / 3f / 2 / 2), centerPoint[1] + (int) (outCircleRadius / 3f / 2 / 2));
int angle = (int) ((allAngle) / (100 * 1f) * progress) + startAngle;
//指針的定點坐標
int[] peakPoint = getPointFromAngleAndRadius(angle, dialRadius);
//頂點朝上,左側的底部點的坐標
int[] bottomLeft = getPointFromAngleAndRadius(angle - 90, (int) (outCircleRadius / 3f / 2 / 2));
//頂點朝上,右側的底部點的坐標
int[] bottomRight = getPointFromAngleAndRadius(angle + 90, (int) (outCircleRadius / 3f / 2 / 2));
Path path = new Path();
mPaint.setColor(Color.parseColor(color_indicator_left));
path.moveTo(centerPoint[0], centerPoint[1]);
path.lineTo(peakPoint[0], peakPoint[1]);
path.lineTo(bottomLeft[0], bottomLeft[1]);
path.close();
canvas.drawPath(path, mPaint);
canvas.drawArc(rectF, angle - 180, 100, true, mPaint);
Log.e("InstrumentView", "drawPointer" + angle);
mPaint.setColor(Color.parseColor(color_indicator_right));
path.reset();
path.moveTo(centerPoint[0], centerPoint[1]);
path.lineTo(peakPoint[0], peakPoint[1]);
path.lineTo(bottomRight[0], bottomRight[1]);
path.close();
canvas.drawPath(path, mPaint);
canvas.drawArc(rectF, angle + 80, 100, true, mPaint);
}
private void drawIndicatorBg(Canvas canvas) {
mPaint.setColor(Color.parseColor(color_smart_circle));
mPaint.setStyle(Paint.Style.FILL);
canvas.drawCircle(centerPoint[0], centerPoint[1], (outCircleRadius / 3f / 2 / 4), mPaint);
}
/**
* 根據進度畫進度條
*
* @param progress 最大進度為100.最小為0
*/
private void drawProgress(int progress, Canvas canvas) {
float ratio = progress / 100f;
int angle = (int) (allAngle * ratio);
drawCircleWithRound(startAngle, angle, inCircleWidth, inCircleRedius, color_progress, canvas);
}
public int getProgress() {
return progress;
}
public void setProgress(int progress) {
this.progress = progress;
invalidate();
}
/**
* 畫一個兩端為圓弧的圓形曲線
*
* @param startAngle 曲線開始的角度
* @param allAngle 曲線走過的角度
* @param radius 曲線的半徑
* @param width 曲線的厚度
*/
private void drawCircleWithRound(int startAngle, int allAngle, int width, int radius, String color, Canvas canvas) {
mPaint.setStrokeWidth(width);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setColor(Color.parseColor(color));
RectF rectF = new RectF(centerPoint[0] - radius, centerPoint[1] - radius, centerPoint[0] + radius, centerPoint[1] + radius);
canvas.drawArc(rectF, startAngle, allAngle, false, mPaint);
drawArcRoune(radius, startAngle, width, canvas);
drawArcRoune(radius, startAngle + allAngle, width, canvas);
}
/**
* 繪制圓弧兩端的圓
*
* @param radius 圓弧的半徑
* @param angle 所處於圓弧的多少度的位置
* @param width 圓弧的寬度
*/
private void drawArcRoune(int radius, int angle, int width, Canvas canvas) {
int[] point = getPointFromAngleAndRadius(angle, radius);
mPaint.setStrokeWidth(0);
mPaint.setStyle(Paint.Style.FILL);
mPaint.setStyle(Paint.Style.FILL);
canvas.drawCircle(point[0], point[1], width / 2, mPaint);
}
/**
* 根據角度和半徑,求一個點的坐標
*
* @param angle
* @param radius
* @return
*/
private int[] getPointFromAngleAndRadius(int angle, int radius) {
double x = radius * Math.cos(angle * Math.PI / 180) + centerPoint[0];
double y = radius * Math.sin(angle * Math.PI / 180) + centerPoint[1];
return new int[]{(int) x, (int) y};
}
}
package com.xk.testdemo;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.SeekBar;
import com.xk.testdemo.view.IndicatorContainer;
import com.xk.testdemo.view.InstrumentView;
public class MainActivity extends AppCompatActivity {
private IndicatorContainer myView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final InstrumentView viewById = (InstrumentView) findViewById(R.id.instrumentView);
SeekBar viewById1 = (SeekBar) findViewById(R.id.sb);
viewById1.setMax(100);
viewById1.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
viewById.setProgress(progress);
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
}
}
Android基於IIS的APK下載(一)自定義更新控件
Android越來越普及,那已經安裝的應用要如何更新呢?在應用市場中常會有顯示某某應用已經更新之類的信息,那我們是否也可以實現類似的功能呢?如果要實現又要做
Android系統升級的完整過程
下面是HTC官方的一個圖片,展示了Android系統從發布最終到用戶手中的一個完整的過程: Awesome Infographic: HTC Shows Us “Th
android編程實現局部界面動態切換的方法
本文實例講述了android編程實現局部界面動態切換的方法。分享給大家供大家參考,具體如下:局部界面固定,局部界面可以動態切換。效果如下:這個效果由3個layout構成m
Android 高清加載巨圖方案 拒絕壓縮圖片
一、概述距離上一篇博客有段時間沒更新了,主要是最近有些私事導致的,那麼就先來一篇簡單一點的博客脈動回來。對於加載圖片,大家都不陌生,一般為了盡可能避免OOM都