Android 繪圖基礎

正兒八經小青年就是我發表於2018-12-25

基本圖形繪製

說到畫圖,在Android中有兩個非常重要的東西,PaintCanvasPaint就是畫筆,Canvas就是畫布。

那怎麼繪製一個自定義View呢?我就明人不說暗話了,看程式碼吧~

package com.example.chengyingying.androiddemo;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.View;

public class DemoView extends View {


    private Paint myPaint;


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

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

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

    private void init() {

        myPaint = new Paint();
        myPaint.setColor(Color.RED);//設定畫筆顏色
        myPaint.setStyle(Paint.Style.STROKE);//設定畫筆填充樣式
        myPaint.setStrokeWidth(50);//設定畫筆寬度
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawCircle(100,100,100,myPaint);

    }
}

複製程式碼

程式碼很簡單,首先建立一個類,然後讓這個類去繼承View。就表示當前這個類是一個自定義View。如果我們想寫個像LinearLayout,RelativeLayout這樣的容器,那我們應該繼承ViewGroup,如果我們想要在系統自帶控制元件的基礎上再自己定義或者新增點兒東西的話,那就繼承系統原有的控制元件即可。比如我想弄的圓形的ImageView,那我們就繼承ImageView。如果我想做一個花型的按鈕,那我就繼承Button就行。其次我們就是重寫onDraw(canvas),在這個函式裡面有個引數,canvas,這個就是當前的畫布,我們要畫東西就在這上面畫。在這裡我給畫筆設定了幾個屬性:

        myPaint = new Paint();
        myPaint.setColor(Color.RED);//設定畫筆顏色
        myPaint.setStyle(Paint.Style.STROKE);//設定畫筆填充樣式
        myPaint.setStrokeWidth(50);//設定畫筆寬度
        
複製程式碼

然後呼叫了canvas.drawCircle(100,100,100,myPaint);畫了一個圓。 然後我們直接在佈局檔案裡以全名的方式引入他即可,例如:

<com.example.chengyingying.androiddemo.DemoView
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
複製程式碼

記住,必須是全名。當然我們也可以通過程式碼使用。直接建立自定義控制元件的例項即可。記住,如果要在xml中使用自定義控制元件,這個構造方法一定要新增。

public DemoView(Context context, @Nullable AttributeSet attrs) {
        this(context,attrs,0);
    }
複製程式碼

然後我們看下效果:

小結

要想建立一個自定義控制元件,就三步即可:

  • 新建自定義類繼承View
  • 建立畫筆,並初始化
  • 重寫onDraw(canvas)方法

畫筆的基本設定

現在看下我們剛才用到的畫筆的幾個屬性

  1. setColor()

    該函式用於設定畫筆顏色,不說那些顏色相關的東西了,就說下,可以有那幾只方式設定顏色,簡單粗暴。

  • setColor(0xFFFFFF)
  • setColor(Color.Red)
  • setColor(Color.rgb(255,255,255))
  • setColor(Color.parseColor("#FF0000"))
  • setColor(getResources().getColor(R.color.white))
  1. setStyle() 該函式用於設定填充樣式,對於文字和幾何圖形有效。style有三種取值方式.
  • Paint.Style.FILL 僅填充內部
  • Paint.Style.FILL_AND_STROKE 填充內部和描邊
  • Paint.Style.STROKE 僅描邊
  1. setStrokeWidth()

    用於設定描邊寬度值,單位是px。僅當畫筆的Style樣式是Style.FILL_AND_STROKE時有效。

Cavans使用基礎

cavans就是塊布,你想幹啥,就拿畫筆在這上面畫。現在看下他咋用?

  1. 畫布背景設定

    有三種方法可以實現畫布背景設定:

  • void drawColor(int color)
  • void drawARGB(int a,int r,int g,int b)
  • void drawRGB(int r,int g,int b)
  1. 畫直線
  • void drawLine(float startX,float startY,float stopX,float stopY,Paint paint) startX: 起始點X座標

    startY: 起始點Y座標

    stopX: 終點X座標

    stopY: 終點Y座標

    注:

    直線的粗細於Paint.setStrokeWidth有直接關係。所以,paint.setStrokeWidth在Style起作用是,用於設定描邊寬度;在Style不起作用時,用於設定畫筆寬度。

  1. 畫點

    void drawPonit(float x,float y,Paint paint)

  • floatx:點的X座標

  • floaty:點的Y座標

    點的大小隻與paint.setStrokeWidth(width)有關,而與paint.setStyle無關。

  1. 矩形工具類RectF Rect概述

    這兩個類都是矩形工具類,根據4個點構造出一個矩形結構。RectF與Rect中的方法,成員變數完全一樣,唯一不同的是:RectF是用來儲存float型別數值的矩形結構的,而Rect是用來儲存int型別數值的矩形結構的。

    RectF:

    建構函式有下面四個:

    RectF(),

    RectF(float left,float top,float right,float bottom),

    RectF(RectF r)

    RectF(Rect r)

    Rect

    建構函式如下:

    Rect()

    Rect(int left,int top,int right,int bottom)

    Rect(Rect r)

  2. 矩形

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

    void drawRect(RectF recf ,Paint paint)

    void drawRect(Rect r,Paint paint)

    引數:

    第一個的寫法是直接傳入,,四個點,畫出矩形

    第二,第三個建構函式是根據傳入RectF或者Rect矩形變數來指定所畫的矩形。

  3. Canvans變換

    平移(translate)

    canvas中有一個函式translate()用來實現畫布平移的,畫布的原狀是以左上角為原點,向左是X軸正方向,向下是Y軸正方向。

    translate函式其實實現的想當於平移座標系,即平移座標系的圓點位置。translate()函式的原型如下:

    void translate(float dx,float dy)

    引數說明:

    float dx:水平方向平移的距離,正數指向正方向(向右)平移的量,負數為向(向左)平移的量

    float dy: 垂直方向平移的距離,正數指向正方向(向下)平移的量,負數為向負方向(向上)平移的量

    旋轉(Rotate)

    畫布的旋轉是預設圍繞座標原點來旋轉的,這裡容易產生錯覺,看起來覺得是圖片旋轉了,其實我們旋轉的是畫布,以後在此畫布上畫的東西顯示出來的時候全部看起來都是旋轉的。Rotate函式有兩個建構函式:

    void rotate(float degress) void rotate(float degress,float px,float py)

    第一個建構函式直接輸入旋轉的度數,正數是順時針旋轉,負數指逆時針旋轉,它的旋轉中心點是原點(0,0)

    第二個建構函式除了度數以外,還可以指定旋轉的中心點座標(px,py)

    縮放(scale)

    public void scale(float sx,float sy)

    引數:

    float sx:水平方向伸縮的比例,sx為小數為縮小,sx為整數為放大 float sy:垂直方向伸縮比例,sy為小數為縮小,整數為放大。

  4. 螢幕顯示與Canvas的關係

  • 每次呼叫canvas.drawXXXX系列函式來繪圖時,都會產生一個全新的Canvas畫布。
  • 如果再DrawXXX前,呼叫平移,旋轉等函式來對Canvas進行操作,那這個操作是不可逆的!每次產生的畫布的最新位置都是這些操作後的位置
  • 在Canvas與螢幕合成時,超出螢幕範圍的影象是不會顯示出來的。
  1. 畫布裁剪

    裁剪畫布是利用Clip系列函式,通過與Rect、Path、Region取交、並、差等集合運算來獲得最新的畫布形狀。除了呼叫Save、Restore函式以外,這個操作是不可逆的,一但Canvas畫布被裁剪,就不能再被恢復!

    boolean clipPath(Path path)

    boolean clipPath(Path path, Region.Op op)

    boolean clipRect(Rect rect, Region.Op op)

    boolean clipRect(RectF rect, Region.Op op)

    boolean clipRect(int left, int top, int right, int bottom)

    boolean clipRect(float left, float top, float right, float bottom)

    boolean clipRect(RectF rect)

    boolean clipRect(float left, float top, float right, float bottom, Region.Op op)

    boolean clipRect(Rect rect)

    boolean clipRegion(Region region)

    boolean clipRegion(Region region, Region.Op op)

  2. 畫布的儲存於恢復

    Save():每次呼叫Save()函式,都會把當前的畫布的狀態進行儲存,然後放入特定的棧中;

    restore():每當呼叫Restore()函式,就會把棧中最頂層的畫布狀態取出來,並按照這個狀態恢復當前的畫布,並在這個畫布上做畫。

先宣告:這篇文章是自己買了本啟艦大神的書,然後邊看出,邊看他部落格,摘下來一些東西。自己寫這個東西,一是加深自己的理解,二是為了方便自己在坐地鐵的時候,學習看,方便。

出處:https://blog.csdn.net/harvic880925/article/details/39080931

最後強烈建議大家買一本啟艦大神的《Android自定義控制元件入門與實戰》這本書,寫的很好,通俗易懂。
複製程式碼

相關文章