Android自定義View之體重秤

一.先上圖

image.png

二.功能拆分

1.背景圓
2.進(jìn)度圓(進(jìn)度開頭是弧形的)
3.中間的文字(圓圈內(nèi)的水平&豎直居中)

三.細(xì)節(jié)

1.背景圓沒什么難度,進(jìn)度圓的開頭和結(jié)尾都是圓的,用到了paint的api為: progressCirclePaint.setStrokeCap(Paint.Cap.ROUND);
2.文字的繪制,主要就是居中效果,水平居中設(shè)置 textPaint.setTextAlign(Paint.Align.CENTER)即可,豎直方向上可以有2種思路,一個是根據(jù)TextBounds的top&bottom 來計算豎直的偏移量,第二個是使用FontMetrics的ascent&descent來計算偏移量(具體可參考rengwuxian關(guān)于文字的繪制),兩者效果區(qū)別不大,自由選擇,倒是顯示效果需要根據(jù)文字是靜態(tài)的還是動態(tài)的來稍微調(diào)整偏移量的計算,因?yàn)閯討B(tài)文字可能會出現(xiàn)跳動

四.欠缺

進(jìn)度條沒有動畫

五.關(guān)于文字的左邊距

如果文字字體過大,文字的左邊距也可能過大,如下圖


image.png

如需要取消這個邊距,同樣也可用TextBounds調(diào)整,調(diào)整后:


image.png

六.talk is cheap

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PathDashPathEffect;
import android.graphics.PathMeasure;
import android.graphics.Rect;
import android.graphics.RectF;
import android.support.annotation.Nullable;
import android.text.TextPaint;
import android.util.AttributeSet;
import android.util.Log;
import android.util.TypedValue;
import android.view.View;

/**
 * 體重表
 * 圓環(huán)&中間的信息
 * 重點(diǎn)是中間的信息string居中
 * TODO 需要將設(shè)置進(jìn)度以及設(shè)置中間文字信息的api暴露出來
 * TODO 提供兩種文字豎直方向居中的算法
 */
public class WeightBoard extends View {
    private static final float RADIUS_CIRCLE = Utils.dp2px(150);
    private static final int START_ANGLE = -90;
    Paint bgCirclePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    Paint progressCirclePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
    TextPaint textPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
    private float width, height;
    private RectF rectF;
    private String text = "60Kg";
    final Rect textBounds = new Rect();
    private Paint.FontMetrics fontMetrics;

    public WeightBoard(Context context) {
        this(context, null);
    }

    public WeightBoard(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public WeightBoard(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        float circleStrokeWidth = Utils.dp2px(15);
        bgCirclePaint.setColor(Color.GRAY);
        bgCirclePaint.setStyle(Paint.Style.STROKE);
        bgCirclePaint.setStrokeWidth(circleStrokeWidth);
        progressCirclePaint.setStrokeCap(Paint.Cap.ROUND);
        progressCirclePaint.setColor(Color.parseColor("#CC9966"));
        progressCirclePaint.setStyle(Paint.Style.STROKE);
        progressCirclePaint.setStrokeWidth(circleStrokeWidth);
        textPaint.setColor(Color.parseColor("#0094ff"));
        textPaint.setTextSize(Utils.dp2px(40));
        textPaint.setFakeBoldText(true);
        textPaint.setStyle(Paint.Style.FILL);
        textPaint.setTextAlign(Paint.Align.CENTER);
        rectF = new RectF();
        fontMetrics = textPaint.getFontMetrics();
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        width = getWidth();
        height = getHeight();
        rectF.set(((float) (width / 2)) - RADIUS_CIRCLE, ((float) (height / 2)) - RADIUS_CIRCLE, ((float) (width / 2)) + RADIUS_CIRCLE, ((float) (height / 2)) + RADIUS_CIRCLE);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //1先畫兩個重疊的圓環(huán)
        //1.1先畫背景圓
        canvas.drawCircle(width / 2, height / 2, RADIUS_CIRCLE, bgCirclePaint);
        //1.2畫進(jìn)度圓弧,注意圓弧的開頭是圓潤的
        canvas.drawArc(rectF, START_ANGLE, 120, false, progressCirclePaint);
        //2.畫中間的信息文字
        //2.1根據(jù)FontMetrics來調(diào)整豎直偏移
        float verticalOffset = (fontMetrics.ascent + fontMetrics.descent) / 2;
        //2.2使用TextBounds來計算偏移
//        textPaint.getTextBounds(text, 0, text.length(), textBounds);
//        verticalOffset = (textBounds.bottom + textBounds.top)/ 2;
        canvas.drawText(text, width / 2, height / 2 - verticalOffset, textPaint);
        bgCirclePaint.setStrokeWidth(Utils.dp2px(1));
        canvas.drawLine(width / 2, height / 2, width / 2 + 100, height / 2, bgCirclePaint);
        testClipLeftSpace(canvas);
    }

    private void testClipLeftSpace(Canvas canvas) {
        textPaint.setTextAlign(Paint.Align.LEFT);
        textPaint.setTextSize(Utils.dp2px(200));
        textPaint.getTextBounds("a",0,"a".length(),textBounds);
        canvas.drawText("a", -textBounds.left, 500, textPaint);
        textPaint.setTextSize(Utils.dp2px(20));
        canvas.drawText("a", 0, 500 + textPaint.getFontSpacing(), textPaint);
    }
}

引用:
HenCoder Android 開發(fā)進(jìn)階:自定義 View 1-3 drawText() 文字的繪制

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容