目前有很多APP都具有進度展示功能,而進度展示的效果多種多樣,0.0就要看你們UI坑不坑了,有簡單的,也有復雜的,首先分析一下UI圖,
UI.png
本來想著用多個view組合完成的,但想想自定義view逼格高對性能也好,所以就用自定義view吧。先上波demo圖:
XIAN.gif
思路
根據分類的個數n ,開始畫圓和上部分標題,線的個數 =分類的個數-1,主要的還是先計算出每個圓心的坐標,先畫線然后畫圓,這樣就可以讓圓把線蓋住一部分實現效果,而不用在計算兩個圓之間的距離再畫線了, 而圓心的坐標我們根據輸入的width把分成 width/n 分就好,width/n / 2 就為第一個圓的x坐標,然后類推,下方內容矩形,是先畫一個矩形,然后在上方畫一個三角形,然后在矩形中間開始畫text,具體實現請看代碼。
代碼
public class MyScheduleView extends View {
private Context mcontext;
//進度個數
private int ScheduleCount = 3;
// 圓的顏色
private int circleColor;
// 線的顏色
private int lineColor = Color.BLACK;
// 當前進度
private int progress = 1;
/* 測量文本寬高的矩形 */
private Rect mTextRect;
/* 測量title文本寬高的矩形 */
private Rect tTextRect;
//用來內容文本的矩形
private Rect cTextRect;
private String texttitle [] ={"天使投資人","至尊VIP","黑金VIP","聯合創始人"};
// 標簽text 畫筆
private Paint ttPaint;
/* 文本畫筆 */
private Paint mTextPaint;
// 三角形畫筆
private Paint tipPaint;
// 文本大小
private float textsize ;
// 標簽文本大小
private float ttextsize ;
// 矩形畫筆
private Paint RECpaint;
// 矩形
private RectF recRect= new RectF();
/**
* 畫三角形的path
*/
private Path path = new Path();
/**
* 三角形的高
*/
private int triangleHeight;
/*
* view的高度
*/
private int height;
private int width;
// 圓的半徑
private float circlewidth= 10;
//線的高度
private float linehight = 10;
/* 線畫筆 */
private Paint mLinePaint;
/* 圓畫筆 */
private Paint CirclePaint;
/**
* 第一個圓開始繪制的圓心坐標
*/
private float startX;
private float startY;
private String textcont[] ={"累計年化投資額達10萬,邀約3人以上,即晉級為天使投資人","累計年化投資額達30萬,邀約3人以上,即晉級為至尊VIP","累計年化投資額達60萬,邀約3人以上,即晉級為黑金VIP","累計年化投資額達90萬,邀約3人以上,即晉級為聯合創始人","通關。。。。。。。。。。。。。。。。。。"};
public MyScheduleView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
mcontext = context;
getAtt(attrs);
initPaint();
}
private void getAtt(AttributeSet attrs) {
TypedArray typedArray = mcontext.obtainStyledAttributes(attrs, R.styleable.MyScheduleView);
ScheduleCount = typedArray.getInt(R.styleable.MyScheduleView_ScheduleCount, ScheduleCount);
circleColor = typedArray.getColor(R.styleable.MyScheduleView_scircleColor, Color.parseColor("#df0781"));
lineColor =typedArray.getColor(R.styleable.MyScheduleView_lineColor, lineColor);
circlewidth = typedArray.getDimension(R.styleable.MyScheduleView_circleWidth,dp2px(10));
linehight = typedArray.getDimension(R.styleable.MyScheduleView_linehight,linehight);
textsize = typedArray.getDimension(R.styleable.MyScheduleView_msvTextsize,textsize);
ttextsize = typedArray.getDimension(R.styleable.MyScheduleView_msvTTextsize,ttextsize);
typedArray.recycle();
mTextRect = new Rect();
tTextRect = new Rect();
cTextRect = new Rect();
}
/**
* 初始化畫筆
*/
private void initPaint() {
mLinePaint = new Paint();
mLinePaint.setStyle(Paint.Style.FILL);
mLinePaint.setColor(circleColor);
mLinePaint.setAntiAlias(true);
ttPaint = new Paint();
ttPaint.setStyle(Paint.Style.FILL);
ttPaint.setColor(Color.BLACK);
ttPaint.setTextSize(ttextsize);
ttPaint.setAntiAlias(true);
CirclePaint = new Paint();
CirclePaint.setStyle(Paint.Style.FILL);
CirclePaint.setColor(circleColor);
CirclePaint.setAntiAlias(true);
mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mTextPaint.setStyle(Paint.Style.FILL);
mTextPaint.setColor(Color.WHITE);
mTextPaint.setTextSize(textsize);
mTextPaint.setAntiAlias(true);
RECpaint = new Paint();
RECpaint.setStyle(Paint.Style.FILL);
RECpaint.setColor(Color.BLUE);
CirclePaint.setAntiAlias(true);
tipPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
tipPaint.setColor(Color.BLUE);
tipPaint.setAntiAlias(true);
tipPaint.setStrokeCap(Paint.Cap.ROUND);
tipPaint.setStyle(Paint.Style.FILL);
}
/**
* 設置畫筆
* @param style 畫筆風格
* @param color 畫筆顏色
* @return
*/
private Paint getPaint( Paint.Style style, int color) {
Paint paint = new Paint(ANTI_ALIAS_FLAG);
paint.setStyle(style);
paint.setColor(color);
paint.setAntiAlias(true);
return paint;
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
width = w;
height = h;
startX = w / ScheduleCount / 2;
startY = h / 2;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
drawLine(canvas);
drawCircle(canvas);
drawTriangle(canvas);
drawText(canvas);
drawTitle(canvas);
}
private void drawTitle(Canvas canvas) {
for (int i = 0; i < ScheduleCount; i++) {
if (i<=progress-1){
ttPaint.setColor(circleColor);
}else {
ttPaint.setColor(Color.BLACK);;
}
// canvas.drawCircle(startX + i * 2 * startX, startY, circlewidth, CirclePaint);
ttPaint.getTextBounds(texttitle[i], 0, texttitle[i].length(), tTextRect);
float TextWidth = tTextRect.width();
float TextHeight = tTextRect.height();
canvas.drawText(texttitle[i],startX + i * 2 * startX-TextWidth/2, (float) (getHeight()/ 2 - TextHeight), ttPaint);
}
}
/**
* 畫實心圓
*
* @param canvas
*/
private void drawCircle(Canvas canvas) {
for (int i = 0; i < ScheduleCount; i++) {
if (i<=progress-1){
CirclePaint.setColor(circleColor);
}else {
CirclePaint.setColor(Color.BLACK);;
}
canvas.drawCircle(startX + i * 2 * startX, startY, circlewidth, CirclePaint);
}
}
// 畫線
private void drawLine(Canvas canvas) {
for (int i = 0; i < ScheduleCount-1; i++) {
if (i<=progress-2){
mLinePaint.setColor(lineColor);
}else {
mLinePaint.setColor(Color.BLACK);;
}
canvas.drawLine(startX + i * 2 * startX,height/2,startX + (i+1) * 2 * startX,height/2,mLinePaint);
}
}
// 繪制內容文本
private void drawText(Canvas canvas) {
mTextPaint.getTextBounds(textcont[progress], 0, textcont[progress].length(), mTextRect);
float TextWidth = mTextRect.width();
float TextHeight = mTextRect.height();
cTextRect.set((int)(startX - (2 * circlewidth)),(int)((height / 2) + 2 * circlewidth),(int)(startX+TextWidth ), (int)((height / 2) + (5 * circlewidth)));
// 繪制矩形
canvas.drawRect(cTextRect, RECpaint);
Paint.FontMetricsInt fontMetrics = mTextPaint.getFontMetricsInt();
// 獲取baseLine
int baseline = cTextRect.top + (cTextRect.bottom - cTextRect.top - fontMetrics.bottom + fontMetrics.top) / 2 - fontMetrics.top;
mTextPaint.setTextAlign(Paint.Align.CENTER);
canvas.drawText(textcont[progress],cTextRect.centerX(),baseline, mTextPaint);
}
/**
* 繪制三角形
*
* @param canvas
*/
private void drawTriangle(Canvas canvas) {
for (int i = 0; i < ScheduleCount; i++) {
if (i == progress-1){
path.moveTo(startX + i * 2 * startX, (float) (height / 2+1.5*circlewidth));
path.lineTo((float) (startX + i * 2 * startX-0.5*circlewidth), height / 2+2*circlewidth);
path.lineTo((float) (startX + i * 2 * startX+0.5*circlewidth), height / 2+2*circlewidth);
canvas.drawPath(path, tipPaint);
path.reset();
}
}
}
public void setProgress(int mprogress) {
progress = mprogress;
invalidate();
}
/**
* dp 2 px
*
* @param dpVal
*/
protected int dp2px(int dpVal) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
dpVal, getResources().getDisplayMetrics());
}
}
attr 文件
<declare-styleable name="MyScheduleView">
<attr name="circleWidth" format="dimension" />
<attr name="ScheduleCount" format="integer" />
<attr name="lineWidth" format="dimension" />
<attr name="linehight" format="dimension" />
<attr name="scircleColor" format="color" />
<attr name="lineColor" format="color" />
<attr name="msvTextsize" format="dimension"></attr>
<attr name="msvTTextsize" format="dimension"></attr>
</declare-styleable>
注意
由于 畫下方矩形的起始位置是固定的,畫其寬度時,根據的是text文本的寬度,所以當字符串的長度太小而進度很高時,不適用,可以在畫矩形時,給矩形設置固定寬度就可以了。
項目地址:
csdn:http://download.csdn.net/download/qq_38367802/10172775
github:https://github.com/liuzhenhang/myview