Android 自定義View系列之必備api

目錄表

寫本篇博客的意圖是想總結一下在實際的自定義view開發中,常被我們所用到的api方法,之所以有了這個想法,是因爲自定義view寫的多了,總感覺掌握的知識點越來越雜,毫無章法。所以也就有了這麼一個想串串知識點的念頭。本文不從概念起筆,也不教你如何實現一個view,把它簡單看作一個私人的api文檔就好。

在這裏插入圖片描述

線段

這裏貼下畫線的api代碼:

        drawLine(float startX, float startY, float stopX, float stopY, Paint paint)

這裏貼下簡單的代碼片段:

        /**
         * @params startX 線段起點的x座標
         * @params startY 線段起點的Y座標
         * @params stopX 線段終點的x座標
         * @params stopY 線段終點y的座標
         */
        canvas.drawLine(0,0
                , CommentUtils.dip2px(mContext, 150)// px
                , CommentUtils.dip2px(mContext, 150)// px
                , linePaint);

這是xml中的佈局片段:

    <com.mjzuo.views.view.GeometricFigureView
        android:layout_width="150dp"
        android:layout_height="150dp"
        android:background="#787878"
        android:layout_marginLeft="50dp"
        android:layout_marginTop="50dp"
        />

效果圖如下
繪製線段

矩形

這裏貼下矩形的api方法:

        public RectF (float left, 
                float top, 
                float right, 
                float bottom)
        public void drawRect (RectF rect,  Paint paint)

這裏貼下使用的代碼片段:

        /**
         * RectF:
         *  left 矩形左側的x座標
         *  top 矩形頂部的y座標
         *  right 矩形右側的x座標
         *  bottom 矩形底部的y座標
         */
        if(rectF == null)
            rectF = new RectF(0, 0
                    , CommentUtils.dip2px(mContext, 150)// 單位都是px
                    , CommentUtils.dip2px(mContext, 75));
        canvas.drawRect(rectF, rectPaint);

這是xml中的佈局片段:

    <com.mjzuo.views.view.GeometricFigureView
        android:layout_width="150dp"
        android:layout_height="150dp"
        android:background="#f0f0f0"
        android:layout_marginLeft="50dp"
        android:layout_marginTop="50dp"
        />

效果圖如下:
繪製矩形

圓形

這裏貼下圓形的api方法:

        public void drawCircle (float cx, float cy, float radius, Paint paint)

這裏貼下使用的代碼片段:

        /**
         *  float cx 中心點的x座標
         *  float cy 中心點的y座標
         *  float radius 半徑
         */
        canvas.drawCircle(CommentUtils.dip2px(mContext, 75)
                , CommentUtils.dip2px(mContext, 75)
                , CommentUtils.dip2px(mContext, 75)
                , circlePaint);

這是xml中的佈局片段:

    <com.mjzuo.views.view.GeometricFigureView
        android:id="@+id/view_circle"
        android:layout_width="150dp"
        android:layout_height="150dp"
        android:background="#787878"
        android:layout_marginLeft="50dp"
        android:layout_marginTop="50dp"
        />

效果圖如下:
繪製圓

默認畫出的圓是實心圓,可以通過設置畫筆屬性來畫空心圓,代碼如下:

        circlePaint = new Paint();
        circlePaint.setColor(0xFFCCFFFF);
        // 充滿
//        circlePaint.setStyle(Paint.Style.FILL);
        // 鑲邊
        circlePaint.setStyle(Paint.Style.STROKE);
橢圓

這是畫橢圓的api:

        // added in api level 21
        // public void drawOval (float left, float top, float right, float bottom, Paint paint)
        public void drawOval (RectF oval, Paint paint)

方法中RectF即是橢圓的外切矩形。這裏貼下橢圓的api方法:

        if(mOvalRectF == null)
            mOvalRectF = new RectF(0, 0
                    , CommentUtils.dip2px(mContext, 75)// 單位都是px
                    , CommentUtils.dip2px(mContext, 37.5f));
        canvas.drawOval(mOvalRectF, mOvalPaint);

這是xml中的佈局片段:

    <com.mjzuo.views.view.GeometricFigureView
        android:layout_width="150dp"
        android:layout_height="150dp"
        android:background="#787878"
        android:layout_marginLeft="50dp"
        android:layout_marginTop="50dp"
        custom:draw_type="3"
        />

效果圖如下:
繪製橢圓

圓角矩形

這裏貼下圓角矩形的api方法:

        // added in api level 21
        //public void drawRoundRect (float left, float top, float right, float bottom, float rx, float ry, Paint paint)
        public void drawRoundRect (RectF rect, float rx, float ry, Paint paint)

這裏貼下圓角矩形的方法:

        /**
         * RectF:矩形區域
         * rx:在x軸的半徑,焦點在x軸的橢圓長半軸
         * ry:在y軸的半徑,焦點在x軸的橢圓短半軸
         *  可以理解成,在rectF矩形左上角的一個長軸短軸分別爲2rx、2ry的標準內切橢圓
         */
        if(mRoundRectF == null)
            mRoundRectF = new RectF(0, 0
                    , CommentUtils.dip2px(mContext, 150)// 單位都是px
                    , CommentUtils.dip2px(mContext, 75));
        canvas.drawRoundRect(mRoundRectF
                , CommentUtils.dip2px(mContext, 36.5f)
                , CommentUtils.dip2px(mContext, 18.25f)
                , mRoundRectFPaint);

這是xml中的佈局片段:

    <com.mjzuo.views.view.GeometricFigureView
        android:layout_width="150dp"
        android:layout_height="150dp"
        android:background="#787878"
        android:layout_marginLeft="50dp"
        android:layout_marginTop="50dp"
        custom:draw_type="4"
        />

效果圖如下:
繪製圓角矩形

這裏貼下弧的api方法:

        public void drawArc (RectF oval, float startAngle,  float sweepAngle, boolean useCenter, Paint paint)

這裏貼下使用弧的方法:

        /**
         * RectF:矩形邊界
         * startAngle:開始弧的角度,手錶3點鐘的方向爲0
         * sweepAngle:順時針的掃過的總角度
         * useCenter:橢圓的中心是否包含在弧裏
         */
        if(mArcRectF == null)
            mArcRectF = new RectF(0, 0
                    , CommentUtils.dip2px(mContext, 150)// 單位都是px
                    , CommentUtils.dip2px(mContext, 75));
        canvas.drawArc(mArcRectF
                , 0
                , 90
                , true
                , mArcPaint);

這是xml中的佈局片段:

    <com.mjzuo.views.view.GeometricFigureView
        android:layout_width="150dp"
        android:layout_height="150dp"
        android:background="#787878"
        android:layout_marginLeft="50dp"
        android:layout_marginTop="50dp"
        custom:draw_type="5"
        />

效果圖如下:
繪製弧

多邊形

我們主要通過path方法來繪製多邊形,當然如果配合畫布的旋轉、平移等會更加方便,在本demo中是以三角形爲例,來演示path的用法,代碼片段如下:

    /**
     *  繪製多邊形,這裏以三角形爲例
     */
    private void drawMoreFigure(Canvas canvas) {
        // 三角形的起點
        if(mMoreFIgurePath == null)
            mMoreFIgurePath = new Path();
        // 三角形的起點
        mMoreFIgurePath.moveTo(CommentUtils.dip2px(mContext, 75), 0);
        // (75,0)->(0,75)畫線
        mMoreFIgurePath.lineTo(0, CommentUtils.dip2px(mContext, 75));
        // (0,75)->(150,75)畫線
        mMoreFIgurePath.lineTo(CommentUtils.dip2px(mContext, 150)
                , CommentUtils.dip2px(mContext, 75));
        // (150,75)->(75,0)畫線,常用close替代
//        mMoreFIgurePath.lineTo(CommentUtils.dip2px(mContext, 75), 0);
        // 閉合路徑
        mMoreFIgurePath.close();
        canvas.drawPath(mMoreFIgurePath, mMoreFigurePaint);
    }

在xml中的代碼片段如下:

    <com.mjzuo.views.view.GeometricFigureView
        android:layout_width="150dp"
        android:layout_height="150dp"
        android:background="#787878"
        android:layout_marginLeft="50dp"
        android:layout_marginTop="50dp"
        custom:draw_type="6"
        />

效果圖如下:

在這裏插入圖片描述
我們也可以通過畫筆Paint來設置是否填充:

        mMoreFigurePaint = new Paint();
        mMoreFigurePaint.setColor(0xFFCCFFFF);
        mMoreFigurePaint.setStyle(Paint.Style.STROKE);// 鑲邊

填充顏色

這裏填下填充顏色的api:

        // int:16進制。29以下默認模式:PorterDuff.Mode.SRC_OVER,即源像素直接繪製在目標像素上
        public void drawColor (int color)
        // long:將RGB轉換成10進制的值
        public void drawColor (long color)
        // 兩個參數的重載方法,具體model請查看源碼或官網文檔
        public void drawColor (int color, PorterDuff.Mode mode)
        // api 29新增方法,相較PorterDuff.Mode新增了一些方法,相當於一個包裝類
        public void drawColor (int color, BlendMode mode)

填充顏色的方法代碼:

        canvas.drawColor(0xFFCCFFFF, PorterDuff.Mode.SRC_OVER);

這是xml中的佈局片段:

    <com.mjzuo.views.view.GeometricFigureView
        android:layout_width="150dp"
        android:layout_height="150dp"
        android:layout_marginLeft="50dp"
        android:layout_marginTop="50dp"
        custom:draw_type="7"
        />

效果圖如下:
填充顏色

文本

這裏是繪製文本的api:

        public void drawText (String text, 
                float x, 
                float y, 
                Paint paint)

這是繪製文字的代碼:

        /**
         *  text:繪製文本
         *  textX:繪製文本的原點x座標
         *  textY:繪製文本基線的y座標
         */
        canvas.drawText("我和我的祖國"
                , CommentUtils.dip2px(mContext, 75)
                , CommentUtils.dip2px(mContext, 75)
                , textPaint);

這是xml中的佈局片段:

    <com.mjzuo.views.view.GeometricFigureView
        android:layout_width="150dp"
        android:layout_height="150dp"
        android:layout_marginLeft="50dp"
        android:layout_marginTop="50dp"
        custom:draw_type="8"
        />

效果圖如下:
繪製文本

bitmap

繪製圖片位圖的api:

        public void drawBitmap (Bitmap bitmap, 
                float left, 
                float top, 
                Paint paint)

繪製位圖的代碼片段:

        /**
         * bitmap
         *  left:繪製的位圖的左側位置
         *  top:繪製位圖的上方位置
         */
        if(mBitmap == null){
            // 將資源圖片轉換成bitmap,R.mipmap.android:資源圖片
            mBitmap = BitmapFactory.decodeResource(mContext.getResources(), R.mipmap.icon_android);
            // 將mBitmap縮放成固定大小
            mBitmap = BitmapUtils.conversionBitmap(mBitmap
                    , CommentUtils.dip2px(mContext, 42)
                    , CommentUtils.dip2px(mContext, 42));
        }
        canvas.drawBitmap(mBitmap
                , 0
                , 0
                , mBitmapPaint);

這是xml中的佈局片段:

    <com.mjzuo.views.view.GeometricFigureView
        android:layout_width="150dp"
        android:layout_height="150dp"
        android:background="#787878"
        android:layout_marginLeft="50dp"
        android:layout_marginTop="50dp"
        custom:draw_type="9"
        />

效果圖如下:
繪製bitmap

畫布裁剪

這是根據path裁剪canvas的代碼片段:

    private void drawClipPathOnCanval(Canvas canvas) {
        if(mClipPath == null){
            mClipPath = new Path();
            // path爲圓形矩形。裁剪圓形,弧等都同理
            if(mClipRectF == null)
                mClipRectF = new RectF(0, 0
                        , CommentUtils.dip2px(mContext, 150)// 單位都是px
                        , CommentUtils.dip2px(mContext, 150));
            /**
             * RectF:矩形輪廓
             * rx:圓角矩形的圓角的x半徑
             * ry:圓角矩形的圓角的y半徑
             * direction:cw:順時針、CCW:逆時針
             */
            mClipPath.addRoundRect(mClipRectF
                    , CommentUtils.dip2px(mContext, 15)
                    , CommentUtils.dip2px(mContext, 15)
                    , Path.Direction.CW);
        }
        canvas.clipPath(mClipPath);
    }

在onDraw方法中進行繪製,本例中是在裁剪後的canvas上繪製了3個矩形,代碼片段如下:

                // 鎖定當前畫布
                canvas.save();
                // 裁剪畫布
                drawClipPathOnCanval(canvas);
                // 畫紅色矩形,矩形方法見上
                drawRedRect(canvas);
                // 畫黃色矩形
                drawYeRect(canvas);
                // 畫綠色矩形
                drawGrRect(canvas);
                // 恢復畫布
                canvas.restore();

在xml中的佈局片段:

    <com.mjzuo.views.view.GeometricFigureView
        android:layout_width="150dp"
        android:layout_height="150dp"
        android:background="#787878"
        android:layout_marginLeft="50dp"
        android:layout_marginTop="50dp"
        custom:draw_type="10"
        />

效果圖如下:
畫布裁剪

畫布旋轉

這是旋轉畫布的代碼片段:

    private void drawRotate(Canvas canvas) {
        // 畫10條線,畫線的方法同上
        for(int index = 0; index < 9; index ++){
            // 畫布旋轉的角度,每次+10
            canvas.rotate(10f);
            // 因爲畫布旋轉了,所以繪製出來的線段也就跟着旋轉了
            drawLine(canvas);
        }
    }

這是onDraw中的方法,需要在每次旋轉前保存下當前的canvas:

                // 鎖定當前畫布
                canvas.save();
                // 畫線
                drawRotate(canvas);
                // 恢復畫布
                canvas.restore();

這是畫線的方法,同上:

    private void drawLine(Canvas canvas) {
        /**
         * @params startX 線段起點的x座標
         * @params startY 線段起點的Y座標
         * @params stopX 線段終點的x座標
         * @params stopY 線段終點y的座標
         */
        canvas.drawLine(0,0
                , CommentUtils.dip2px(mContext, 75)
                , 0
                , linePaint);
    }

這是xml中的佈局的代碼片段:

    <com.mjzuo.views.view.GeometricFigureView
        android:layout_width="150dp"
        android:layout_height="150dp"
        android:background="#787878"
        android:layout_marginLeft="50dp"
        android:layout_marginTop="50dp"
        custom:draw_type="11"
        />

效果如圖:
畫布旋轉

畫布平移

在上面畫布旋轉代碼的基礎上,我們將畫布中的線段起點挪動到view的中心點位置,代碼片段如下:

    private void drawTranslate(Canvas canvas){
        /**
         * dx: 要在x中轉換的距離
         * dy: 要在y中轉換的距離
         */
        canvas.translate(CommentUtils.dip2px(mContext, 75)
                , CommentUtils.dip2px(mContext, 75));
    }

在onDraw中繪製線段,並平移旋轉畫布:

                // 鎖定當前畫布
                canvas.save();
                // 挪動畫布
                drawTranslate(canvas);
                // 畫線
                drawRotate(canvas);
                // 恢復畫布
                canvas.restore();

在xml中的代碼片段:

    <com.mjzuo.views.view.GeometricFigureView
        android:layout_width="150dp"
        android:layout_height="150dp"
        android:background="#787878"
        android:layout_marginLeft="50dp"
        android:layout_marginTop="50dp"
        custom:draw_type="12"
        />

效果圖如下:
畫布平移

gitHub - CustomViewCollection

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