Android自定義View——繪製基礎

本篇接着上一篇的基礎知識來說,今天要學點能看的見的東西了————繪製基礎。

一、繪製的簡要說明

自定義繪製最主要的點就是重寫繪製方法,當我們定義一個類去繼承自View這個類時,會讓你必須重寫幾個構造方法和onDraw(Canvas canvas)方法,那我們最常用的繪製方法就是這個onDraw方法,參數需要一個Canvas對象,我們繪製的關鍵就是通過Canvas提供的各個api去進行繪製、裁剪以及幾何變換,這些我會慢慢的進行整理。本篇既然是基礎,那麼這裏就只講關於繪製的方法,即是drawXXX()方法。先把必須的東西都一下說完,在詳細介紹,所以在這裏還需要用到一個畫筆類:Paint,這個類提供的一些api可以讓我們設置畫筆的顏色、形狀、陰影等等,通過Canvas和Paint的搭配使用之後,我們就可以繪製出各種豐富多彩的圖形了。

二、常用api的說明

1、顏色填充

 

@Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //給View上色爲粉紅色
        canvas.drawColor(getResources().getColor(R.color.pageColor));
    }

 

這裏直接調用drawColor()方法,參數填充顏色即可,效果如下:

2、繪製圓形及環形

先看個簡單的,繪製一個實心圓,這裏我們需要藉助Paint對象了哦,首先實例化一個Paint對象,然後調用canvas.drawCircle(圓心橫座標,圓心縱座標,半徑,畫筆對象)方法,各個參數的含義已經很明確了,其中Paint.Style.FILL是實心模式,Paint.Style.STROKE是線條即空心模式。對了,需要說明的一點是,這裏的座標系和我們平時在數學中學的兩維座標系不同,android中每個View自己有一個座標系,原點是View左上角的那個點,水平方向爲X軸,向右爲正向左爲負,豎直方向爲Y軸,向下爲正向上爲負,盜了大神一張圖,上圖:

除了畫實心圓,我們還可以畫空心圓,畫帶有顏色的實心圓,畫圓環等等,因爲使用也比較簡單我就不詳細說明了,具體來看一下代碼,已經給出了註釋:

 

@Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); //開啓抗鋸齒
        //實心圓
        canvas.drawCircle(100, 300, 50, paint);
        //空心圓
        paint.setStyle(Paint.Style.STROKE); //設置空心圓
        canvas.drawCircle(250, 300, 50, paint);
        //粉紅色實心圓
        paint.setStyle(Paint.Style.FILL);
        paint.setColor(Color.parseColor("#FF4081"));
        canvas.drawCircle(400, 300, 50, paint);
        //線寬爲10的空心圓
        paint.setStyle(Paint.Style.STROKE);
        paint.setStrokeWidth(10); //設置線的寬度
        canvas.drawCircle(550, 300, 50, paint);
    }

這裏需要說明的有一點Paint.ANTI_ALIAS_FLAG這個屬性是給畫筆添加抗鋸齒效果,以保證圖形邊緣平滑,具體的實現效果爲:

 

3、繪製矩形

我們可以使用canvas.drawRect(float left,float top,float right,float bottom,Paint paint)方法來繪製矩形,還有兩個重載的方法,可以直接傳Rect和RectF對象,具體代碼如下:

@Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        Paint paint = new Paint();
        //畫矩形
        paint.setColor(Color.parseColor("#3F51B5"));
        canvas.drawRect(100,100,600,300,paint);
//        Rect rect = new Rect(100,100,600,300);
//        canvas.drawRect(rect,paint);
//        RectF rectF = new RectF(100,100,600,300);
//        canvas.drawRect(rectF,paint);
    }

具體效果如下圖所示:

 


4、繪製點

我們使用drawPoint(float x, float y, Paint paint)方法來畫點,參數爲點的座標和畫筆對象,點的形狀可以通過paint.setStrokeCap(cap)方法來進行設置,ROUND爲原點,SQUARE爲方點,它們等同於繪製實現圓和實心矩形。另外drawPoints(float[] pts, Paint paint) 這個方法是畫一組點,具體使用方法如下:

 

@Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //手動關閉硬件加速,因爲Canvas和Paint有一些方法不支持硬件加速
        //在這裏不加這句話Paint.Cap.Round不起效果,會是方形的
        this.setLayerType(LAYER_TYPE_SOFTWARE,null);
        Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        //畫圓點
        paint.setStrokeWidth(20); //設置點的大小
        paint.setStrokeCap(Paint.Cap.ROUND); //設置點的形狀爲原型
        paint.setColor(Color.parseColor("#FF4081"));
        canvas.drawPoint(100, 100, paint);
        //畫方點
        paint.setStrokeWidth(30);
        paint.setStrokeCap(Paint.Cap.SQUARE); //設置點的形狀爲方形
        canvas.drawPoint(200, 100, paint);
        //畫一組點
        float[] points = {50,200,100,200,50,280,100,280};
        canvas.drawPoints(points,paint);
    }

它的效果如圖所示:

 


5、繪製橢圓

我們可以使用drawOval(float left, float top, float right, float bottom, Paint paint)方法來畫橢圓,它還有一個重載的方法drawOval(RectF rect, Paint paint),參數很好理解了,邊界座標和畫筆對象,具體在代碼中來看它是如何使用的:

 

@Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        //畫實心橢圓
        paint.setStyle(Paint.Style.FILL);
        //這個api必須在版本大於21是才能使用,否則程序會crash
//        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
//            canvas.drawOval(100,100,400,300,paint);
//        }
        RectF rectF = new RectF(100,100,400,300);
        canvas.drawOval(rectF,paint);
        //畫空心橢圓
        paint.setStyle(Paint.Style.STROKE);
//        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
//            canvas.drawOval(100,400,400,600,paint);
//        }
        RectF r = new RectF(100,400,400,600);
        canvas.drawOval(r,paint);
    }

效果如下圖所示:

 


6、繪製直線

繪製直線就比較簡單了,使用drawLine(float startX, float startY, float stopX, float stopY, Paint paint)方法畫線,參數就是起始點的座標和畫筆對象。另外我們還可以繪製一組直線,組合出漢字或者其他圖形,使用drawLines(float[] pts, Paint paint) 方法批量操作,下面同樣通過代碼來看它的使用:

 

@Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        paint.setStrokeWidth(20);
        //畫直線
        canvas.drawLine(100,100,600,200,paint);
        //批量畫線
        float[] points = {200,300,600,300,400,300,400,700,200,700,600,700};
        canvas.drawLines(points,paint);
    }

效果如下圖所示:

 


7、繪製圓角矩形

使用drawRoundRect(float left, float top, float right, float bottom, float rx, float ry, Paint paint)方法來畫圓角矩形,參數分別爲外輪廓的座標,圓角的橫向半徑,縱向半徑,畫筆對象,使用起來也是很簡單,直接上代碼:

 

@Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        //畫實心圓角矩形
        RectF r1 = new RectF(100,50,400,200);
        canvas.drawRoundRect(r1,30,30,paint);
        //畫空心圓角矩形
        paint.setStyle(Paint.Style.STROKE);
        RectF r2 = new RectF(100,250,400,400);
        canvas.drawRoundRect(r2,30,30,paint);
    }

效果圖如下所示:

 


8、繪製弧形或者扇形

這裏使用drawArc(float left, float top, float right, float bottom, float startAngle, float sweepAngle, boolean useCenter, Paint paint)方法來繪製弧形或扇形,通過查看源碼我們可以發現,它底層是通過一個橢圓來描述弧形的,其中參數left、top、right、bottom是所在的橢圓的邊界座標,startAngle是弧形的起始角度,X軸的正向爲0度的位置,順時針爲正逆時針爲負,sweepAngle是弧形範圍角度,useCenter表示是否連接到圓心,爲true表示連接,就是扇形,爲false表示不連接,就是弧形。具體使用方式見代碼:

 

@Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        paint.setStyle(Paint.Style.FILL); // 填充模式
        RectF rectF = new RectF(200, 100, 600, 500);
        // 繪製扇形
        canvas.drawArc(rectF, -110, 100, true, paint);
        // 繪製弧形
        canvas.drawArc(rectF, 20, 140, false, paint);
        paint.setStyle(Paint.Style.STROKE);
        // 繪製不封口的弧形,即弧線
        canvas.drawArc(rectF, 180, 60, false, paint);
    }

效果圖如下所示:

 


9、繪製自定義圖形

說到畫自定義圖形,我們就會用到drawPath(Path path,Paint paint)這個方法了,它是通過描述路徑的方式來繪製圖形的,參數就是描述圖形路徑的對象和畫筆對象。描述路徑的方法又可分爲兩類:添加子圖形和畫線,即addXxx()和xxxTo()兩類,我這裏結合一個繪製心形的案例來介紹其中的一些方法,首先來看lineTo(float x, float y) / rLineTo(float x, float y) 方法,從當前位置向目標位置一條畫線,x,y是目標點的座標,當前位置就是最後一次調用Path方法的位置,初始值爲(0,0),不同的是前者的參數是絕對座標,後者的參數是相對座標;moveTo(float x, float y) / rMoveTo(float x, float y) 這個方法是移動到目標位置,可以用來指定起始點的座標;arcTo(float left, float top, float right, float bottom, float startAngle, float sweepAngle, boolean forceMoveTo)這個方法用來畫弧形,前面的參數和之前的意思一樣,這裏介紹一下forceMoveTo這個參數的意思,它是表示繪製時是否留下移動的軌跡;addArc(float left, float top, float right, float bottom, float startAngle, float sweepAngle)這個方法也是用來畫弧形的,它和arcTo()的區別就是它直接將forceMoveTo置爲true了;drawText(String text, float x, float y, Paint paint)這個方法是用來繪製文字的,參數是文本,位置座標和畫筆對象。具體的實現代碼如下:

 

@Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        paint.setColor(Color.parseColor("#FF4081"));
        Path path = new Path(); //初始化Path對象
        RectF rectF = new RectF(100,200,300,400);
        path.addArc(rectF,-225,225);
        RectF r = new RectF(300,200,500,400);
        path.arcTo(r,-180,225,false);
        path.lineTo(300,542);
        canvas.drawPath(path,paint);
    }

效果圖如下所示:

 

 

 

關於繪製基礎部分的知識點就介紹這麼多,最後通過兩個小案例直方圖和餅圖進行知識點的鞏固,我已經將完整的代碼上傳到GitHub上面了,歡迎大家批評指正。

直方圖和餅圖的效果圖如下:

項目地址:https://github.com/JArchie/CustomViewDemo

我的這篇文章是基於在扔物線大神的系列課程的學習總結,這裏也推薦給大家:https://juejin.im/user/552f20a7e4b060d72a89d87f,實際上這個小項目就是對這個課後作業的解答,我建議大家如果想學習的都去看看大神的這個系列的文章,寫的真的很詳細,值得一看!

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