android羣英傳筆記——重寫View來實現全新的控件(弧線展示圖)

弧線展示圖

如下圖所示就是這次的弧線展示圖:

弧線展示圖

根據書中的代碼增加了可自定義弧形的大小,並且可以在佈局中自定義各部分的顏色和大小設置。

接下來開始介紹如何創建一個這樣的自定義View。

很明顯,這個自定義View其實分爲三個部分,分別是中間的圓形、中間顯示的文字和外圈的弧線。有了這樣的思路,只要在onDraw()方法中一個個去繪製就可以了。

首先,在初始化的時候,設置好繪製三種圖形的參數。圓的代碼如下所示:

// 中心圓的圓心座標
mCircleXY = length/2;
// 中心圓的半徑
mRadius = (float) (length*0.5/2);

繪製弧線,需要指定其橢圓的外接矩形,代碼如下所示:

        // 繪製弧形的外接矩形屬性
        mArcRectF = new RectF(
                (float) (length * 0.1),
                (float) (length * 0.1),
                (float) (length * 0.9),
                (float) (length * 0.9)
        );

繪製文字,只要設置好文字的起始繪製位置就可以了。

接下來,我們就可以在onDraw()方法中進行繪製了,代碼如下所示:

        // 繪製中心圓
        canvas.drawCircle(mCircleXY, mCircleXY, mRadius, mCirclePaint);
        // 繪製弧形
        canvas.drawArc(mArcRectF, 270, mSweepValue, false, mArcPaint);
        // 繪製文字
        // 測量字體寬度,根據字體的寬度設置在圓環中間
        float textWidth = mTextPaint.measureText(mShowText);
        // 通過文字的大小和長度將文字繪製在圓的正中心
        canvas.drawText(mShowText, 0,mShowText.length(), mCircleXY-(textWidth/2), mCircleXY+(mShowTextSize/4), mTextPaint);

當然,如果想在佈局時給這個簡單的View自定義屬性的話,可以通過attrs.xml文件給這個控件添加可以自定義的屬性,attrs.xml中設置的屬性可以根據需要添加,在java中的調用方法如下所示:

        // 將所有的attrs中的所有樣式都存儲到TypeArray中
        TypedArray ta = context.obtainStyledAttributes(attrs,R.styleable.ArcDisplay);

        // 給中心圓設置屬性
        mCirclePaint = new Paint();
        mCirclePaint.setColor(ta.getColor(R.styleable.ArcDisplay_centerCircleColor,
                ContextCompat.getColor(context,R.color.defCircleColor)));

        // 給弧形設置屬性
        mArcPaint = new Paint();
        mArcPaint.setColor(ta.getColor(R.styleable.ArcDisplay_arcColor,
                ContextCompat.getColor(context,R.color.defArcColor)));
        mArcPaint.setStrokeWidth(ta.getInteger(R.styleable.ArcDisplay_arcWidth, 60));
        mArcPaint.setStyle(Paint.Style.STROKE);
        setProgress(ta.getFloat(R.styleable.ArcDisplay_arcAngle, 10));

        // 給中間文字設置屬性
        mTextPaint = new Paint();
        mTextPaint.setColor(ta.getColor(R.styleable.ArcDisplay_centerTextColor,
                ContextCompat.getColor(context,R.color.defTextColor)));
        mShowTextSize = ta.getInteger(R.styleable.ArcDisplay_centerFontSize, 10);
        mTextPaint.setTextSize(mShowTextSize);

        ta.recycle();

當調用者不具體指定屬性時,可以給它們都設置一個默認值。

設置完自定義屬性後,開始設置如何通過百分比的形式讓弧形顯示準確的比例長度,代碼如下所示:

    /**
     * 給弧形設置一個角度(百分比的形式)
     * @param mSweepValue 角度比例
     */
    public void setProgress(float mSweepValue){
        if (mSweepValue != 0) {
            this.mSweepValue = (float) (360.0 * (mSweepValue / 100.0));
            mShowText = mSweepValue + "%";
        } else {
            this.mSweepValue = 25;
            mShowText = 25 + "%";
        }

        invalidate();
    }

通過以上方法就可以實現輸入具體的百分比讓弧形長度準確顯示。

以上就是弧形展示圖的實現步驟,有沒有很簡單。

代碼

以下是完整代碼:

package com.example.customarc;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
import android.support.v4.content.ContextCompat;
import android.util.AttributeSet;
import android.view.View;

import com.example.arcdisplay.R;

/**
 * 自定義弧線展示圖
 * Created by shize on 2016/8/30.
 */
public class ArcDisplay extends View {
    // 中心圓的xy軸座標
    private float mCircleXY;
    // 中心圓的半徑
    private float mRadius;
    // 中心圓的畫筆
    private Paint mCirclePaint;
    // 弧線橢圓的畫筆
    private Paint mArcPaint;
    // 弧線掃過的角度
    private float mSweepValue;
    // 中心圓的文字
    private String mShowText;
    // 文字的畫筆
    private Paint mTextPaint;
    // 畫布的寬
    private int length;
    // 文字大小尺寸
    private int mShowTextSize;

    public ArcDisplay(Context context) {
        super(context);
    }

    public ArcDisplay(Context context, AttributeSet attrs) {
        super(context, attrs);
        initView(context, attrs);
    }

    public ArcDisplay(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initView(context, attrs);
    }

    public void initView(Context context, AttributeSet attrs){
        // 將所有的attrs中的所有樣式都存儲到TypeArray中
        TypedArray ta = context.obtainStyledAttributes(attrs,R.styleable.ArcDisplay);

        // 給中心圓設置屬性
        mCirclePaint = new Paint();
        mCirclePaint.setColor(ta.getColor(R.styleable.ArcDisplay_centerCircleColor,
                ContextCompat.getColor(context,R.color.defCircleColor)));

        // 給弧形設置屬性
        mArcPaint = new Paint();
        mArcPaint.setColor(ta.getColor(R.styleable.ArcDisplay_arcColor,
                ContextCompat.getColor(context,R.color.defArcColor)));
        mArcPaint.setStrokeWidth(ta.getInteger(R.styleable.ArcDisplay_arcWidth, 60));
        mArcPaint.setStyle(Paint.Style.STROKE);
        setProgress(ta.getFloat(R.styleable.ArcDisplay_arcAngle, 10));

        // 給中間文字設置屬性
        mTextPaint = new Paint();
        mTextPaint.setColor(ta.getColor(R.styleable.ArcDisplay_centerTextColor,
                ContextCompat.getColor(context,R.color.defTextColor)));
        mShowTextSize = ta.getInteger(R.styleable.ArcDisplay_centerFontSize, 10);
        mTextPaint.setTextSize(mShowTextSize);

        ta.recycle();
    }

    @Override
    protected void onSizeChanged(int w,int h,int oldW,int oldH){
        super.onSizeChanged(w,h,oldW,oldH);
        length = w;
        mCircleXY = length/2;
        mRadius = (float) (length*0.5/2);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        // 弧線橢圓的外接矩形
        RectF mArcRectF;
        // 繪製弧形的外接矩形屬性
        mArcRectF = new RectF(
                (float) (length * 0.1),
                (float) (length * 0.1),
                (float) (length * 0.9),
                (float) (length * 0.9)
        );
        // 繪製中心圓
        canvas.drawCircle(mCircleXY, mCircleXY, mRadius, mCirclePaint);
        // 繪製弧形
        canvas.drawArc(mArcRectF, 270, mSweepValue, false, mArcPaint);
        // 繪製文字
        // 測量字體寬度,根據字體的寬度設置在圓環中間
        float textWidth = mTextPaint.measureText(mShowText);
        // 通過文字的大小和長度將文字繪製在圓的正中心
        canvas.drawText(mShowText, 0,mShowText.length(), mCircleXY-(textWidth/2), mCircleXY+(mShowTextSize/4), mTextPaint);
    }

    /**
     * 給弧形設置一個角度(百分比的形式)
     * @param mSweepValue 角度比例
     */
    public void setProgress(float mSweepValue){
        if (mSweepValue != 0) {
            this.mSweepValue = (float) (360.0 * (mSweepValue / 100.0));
            mShowText = mSweepValue + "%";
        } else {
            this.mSweepValue = 25;
            mShowText = 25 + "%";
        }

        invalidate();
    }
}

佈局文件調用代碼:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:custom="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.example.arcdisplay.MainActivity">

    <com.example.customarc.ArcDisplay
        android:id="@+id/arc"
        android:layout_width="match_parent"
        android:layout_height="400dp"
        custom:arcAngle="60"
        custom:arcColor="#00ff00"
        custom:arcWidth="60"
        custom:centerCircleColor="#00ff00"
        custom:centerFontSize="70"
        custom:centerTextColor="#f33" />

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@string/txt_angle"/>

        <EditText
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:id="@+id/angle"
            android:inputType="numberDecimal"/>

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/btnYes"
            android:text="@string/btn_txt_yes"/>
</LinearLayout>

以下是attrs.xml的代碼:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="ArcDisplay">
        <attr name="centerFontSize" format="integer" />
        <attr name="centerTextColor" format="color" />
        <attr name="centerCircleColor" format="color" />
        <attr name="arcColor" format="color" />
        <attr name="arcAngle" format="float" />
        <attr name="arcWidth" format="integer" />
    </declare-styleable>
</resources>

感謝閱讀,下次再見。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章