教你玩轉自定義View—手擼一個倒計時控件如此簡單

在一個APP啓動的時候呢,通常常常見到倒計時3秒或幾秒的場景,在這個場景中,也常常看到一個有動畫加載的view,效果圖以下:git

倒計時效果圖
倒計時效果圖

分析

正所謂知己知彼百戰百勝,因此咱們每去作一件事情以前都要去花費必定的時間去了解一些相關的東西。那麼這樣的一個效果呢其實不難,咱們只需兩個東西便可實現。——canvas和屬性動畫。github

1.自定義咱們須要的屬性:

那麼爲了考慮擴展性,那麼有些屬性呢咱們不能寫死,自定義屬性是最好的選擇!首先在values文件夾下新建文件attrs.xmlcanvas

<declare-styleable name="CountDownView">
        <!--view半徑-->
        <attr name="cd_circle_radius" format="dimension" />
        <!--畫筆寬度-->
        <attr name="cd_arc_width" format="dimension" />
        <!--畫筆顏色-->
        <attr name="cd_arc_color" format="color" />
        <!--背景顏色-->
        <attr name="cd_bg_color" format="color" />
        <!--字體顏色-->
        <attr name="cd_text_color" format="color" />
        <!--字體尺寸-->
        <attr name="cd_text_size" format="dimension" />
        <!--動畫執行時長-->
        <attr name="cd_animator_time" format="integer" />
        <!--時間單位-->
        <attr name="cd_animator_time_unit" format="string" />
        <!--動畫進退方式-->
        <attr name="cd_retreat_type" format="enum">
            <!--外層的圓弧逐漸變長-->
            <enum name="forward" value="1" />
            <!--外層的圓弧逐漸減短-->
            <enum name="back" value="2" />
        </attr>
        <!--加載進度的開始位置-->
        <attr name="cd_location" format="enum">
            <enum name="left" value="1" />
            <enum name="top" value="2" />
            <enum name="right" value="3" />
            <enum name="bottom" value="4" />
        </attr>
    </declare-styleable>複製代碼

而後在自定義View中獲取並設置這些屬性:
首先,來聲明和獲取定義好的屬性:bash

private Paint mPaintBackGround;//背景畫筆
    private Paint mPaintArc;//圓弧畫筆
    private Paint mPaintText;//文字畫筆
    private int mRetreatType;//圓弧繪製方式(增長和減小)
    private float mPaintArcWidth;//最外層圓弧的寬度
    private int mCircleRadius;//圓圈的半徑
    private int mPaintArcColor = Color.parseColor("#3C3F41");//初始值
    private int mPaintBackGroundColor = Color.parseColor("#55B2E5");//初始值
......複製代碼

獲取這些屬性值:微信

TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.CountDownView);
mRetreatType = array.getInt(R.styleable.CountDownView_cd_retreat_type, 1);
location = array.getInt(R.styleable.CountDownView_cd_location, 1);複製代碼

初始化畫筆等操做:ide

2.畫出須要的效果:畫圓弧,畫字體,畫背景

這裏咱們使用cancas的drawArc()方法,不瞭解這個方法是什麼意思的請跳至此處查看詳細解釋~drawArc()方法詳細介紹字體

環形進度
環形進度

3.改變屬性值,從新繪製

4.接口回調。

這一步就很簡單了,只要監聽動畫執行結束就是完成了加載,因此咱們先來寫一個接口。動畫

private OnLoadingFinishListener loadingFinishListener;

    public void setOnLoadingFinishListener(OnLoadingFinishListener listener) {
        this.loadingFinishListener = listener;
    }

    public interface OnLoadingFinishListener {
        void finish();
    }複製代碼

在對應的Activity中回調接口就能夠了。ui

OK,到這裏就算所有結束了,下面是部分源碼:this

@Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        //由於必須是圓形的view,因此在這裏從新賦值
        setMeasuredDimension(mCircleRadius * 2, mCircleRadius * 2);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //畫北景園
        canvas.drawCircle(mWidth / 2, mHeight / 2, mWidth / 2 - mPaintArcWidth, mPaintBackGround);
        //畫圓弧
        RectF rectF = new RectF(0 + mPaintArcWidth / 2, 0 + mPaintArcWidth / 2
                , mWidth - mPaintArcWidth / 2, mHeight - mPaintArcWidth / 2);
        canvas.drawArc(rectF, startAngle, mSweepAngle, false, mPaintArc);
        //畫文字
        float mTetxWidth = mPaintText.measureText(mText, 0, mText.length());
        float dx = mWidth / 2 - mTetxWidth / 2;
        Paint.FontMetricsInt fontMetricsInt = mPaintText.getFontMetricsInt();
        float dy = (fontMetricsInt.bottom - fontMetricsInt.top) / 2 - fontMetricsInt.bottom;
        float baseLine = mHeight / 2 + dy;
        canvas.drawText(mText, dx, baseLine, mPaintText);

    }複製代碼

博客地址:

www.jianshu.com/p/2b5ef5e18…

項目地址:

github.com/SuperKotlin…

相信本身,沒有作不到的,只有想不到的

若是你以爲此文對您有所幫助,歡迎入羣 QQ交流羣 :232203809
微信公衆號:終端研發部

技術+職場
技術+職場
相關文章
相關標籤/搜索