paint畫筆

概念:

畫筆,保存了繪製幾何圖形,文本和位圖的樣式和顏色信息。

常用API:

常用API主要如顏色效果和文本相關等。

當我們調用常用API的時候直接調用native方法。

初始化

 mPaint = new Paint(); //初始化
 mPaint.setAntiAlias(true); // 抗鋸齒

描邊效果

mPaint.setStyle(Paint.Style.FILL); //描邊效果

setStyle裏面有三種屬性


    public enum Style {
      
        FILL            (0),
        
        STROKE          (1),
       
        FILL_AND_STROKE (2);

       ...
    }
FILL屬性:

在這裏插入圖片描述

STROKE屬性:

在這裏插入圖片描述

FILL_AND_STROKE

兩種同時作用


描邊寬度


 mPaint.setStrokeWidth(4);//描邊寬度

上圖中圓環的寬度

圓角效果

   mPaint.setStrokeCap(Paint.Cap.ROUND); //圓角效果

Paint.Cap.ROUND裏面有三種屬性

    public enum Cap {
       
        BUTT    (0),
     
        ROUND   (1),
       
        SQUARE  (2);

        private Cap(int nativeInt) {
            this.nativeInt = nativeInt;
        }
        final int nativeInt;
    }

如果是畫直線

        mPaint = new Paint(); //初始化

        mPaint.setStrokeWidth(44);//描邊寬度
        mPaint.setStrokeCap(Paint.Cap.ROUND); //圓角效果
            @Override
            
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            canvas.drawLine(400,400,600,400,mPaint);
        }

拐角風格

setStrokeJoin(Paint.Join join)

設置線段連接處樣式,取值有:Join.MITER(結合處爲銳角)、Join.Round(結合處爲圓弧)、Join.BEVEL(結合處爲直線)
在這裏插入圖片描述

設置環形渲染器

mPaint.setShader(new SweepGradient(200, 200, Color.BLUE, Color.RED)); //設置環形渲染器

設置圖層混合模式

 mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DARKEN)); //設置圖層混合模式

設置顏色過濾器

mPaint.setColorFilter(new LightingColorFilter(0x00ffff, 0x000000)); //設置顏色過濾器 光照效果

設置雙線性過濾

mPaint.setFilterBitmap(true); //設置雙線性過濾 將圖片過度平滑

在這裏插入圖片描述

設置畫筆遮罩濾鏡 ,傳入度數和樣式

mPaint.setMaskFilter(new BlurMaskFilter(10, BlurMaskFilter.Blur.NORMAL));//設置畫筆遮罩濾鏡 ,傳入度數和樣式

設置文本縮放倍數

mPaint.setTextScaleX(2);// 設置文本縮放倍數

設置字體大小

//        mPaint.setTextSize(38);// 設置字體大小


對其方式

//        mPaint.setTextAlign(Paint.Align.LEFT);//對其方式

設置下劃線

//        mPaint.setUnderlineText(true);// 設置下劃線

文本大小寬度字體度量

//        String str = "Android";
//        Rect rect = new Rect();
//        mPaint.getTextBounds(str, 0, str.length(), rect); //測量文本大小,將文本大小信息存放在rect中
//        mPaint.measureText(str); //獲取文本的寬
//        mPaint.getFontMetrics(); //獲取字體度量對象

對於指定字號的某種字體,再度量方面的各種屬性。參數包括:

  • baseline:字符基線
  • ascent:字符最高點到baseline的推薦距離
  • top:字符最高點到baseline的最大距離
  • descent:字符最低點到baseline的推薦距離
  • bottom:字符最低點到baseline的最大距離
  • leading:行間距,即前一行的descent與下一行的ascent之間的距離
    在這裏插入圖片描述
    右鍵圖片另存爲,查看大圖

Paint顏色相關

  1. setcolor( int color)參數具體的顏色值,16 進制數值,0XFFF000
  2. . setARGB(inta,intr,intg,intb)參數分別透明度,紅,綠,藍。0-255 數值
  3. shader( Shadershader)參數着色器對象,一般使用 shader 的幾個子類
  • Lineargradient:線性渲染
  • RadialGradient:環形渲染
  • SweepGradient:掃描渲染
  • BitmapShader:位圖渲染
  • ComposeShader:組合渲染,例如 LinearGradient+ Bitmap shader
  1. setColorFilter( Colorfilter colorfilter)設置顏色過濾。一般使用

Colorfilter 三個子類:

  • Lighting ColorFilter:光照效果
  • PorterDuffcolorfilter:指定一個顏色和一種 PorterDuff Mode 與繪製對象進行合成
  • ColorMatrixcolorfilter:使用一個 ColorMatrix 來對顏色進行處理
LinearGradients線性渲染
public LinearGradient (float x0, 
                float y0, 
                float x1, 
                float y1, 
                long[] colors, 
                float[] positions, 
                Shader.TileMode tile)
參數
x0 yo x1 y1 漸變的兩個端點的位置
color0 color1 是端點的顏色
tile 端點範圍之外的着色規則,類型是 TileMode
使用:
    /**
     * 線性渲染,LinearGradient(float x0, float y0, float x1, float y1, @NonNull @ColorInt int colors[], @Nullable float positions[], @NonNull TileMode tile)
     * (x0,y0):漸變起始點座標
     * (x1,y1):漸變結束點座標
     * color0:漸變開始點顏色,16進制的顏色表示,必須要帶有透明度
     * color1:漸變結束顏色
     * colors:漸變數組
     * positions:位置數組,position的取值範圍[0,1],作用是指定某個位置的顏色值,如果傳null,漸變就線性變化。
     * tile:用於指定控件區域大於指定的漸變區域時,空白區域的顏色填充方法
     */
    mShader = new LinearGradient(0, 0, 500, 500, new int[]{Color.RED, Color.BLUE, Color.GREEN}, new float[]{0.f,0.7f,1}, Shader.TileMode.REPEAT);
    mPaint.setShader(mShader);
 	canvas.drawCircle(250, 250, 250, mPaint);
效果

在這裏插入圖片描述

注意:

紅到藍漸變

new int[]{Color.RED, Color.BLUE, Color.GREEN}, new float[]{0.f,0.7f,1}
個數是相對應的
color.red和0.f對應
Color.BLUE和0.7f對應
Color.GREEN和1對應
RadialGradient環形渲染
public RadialGradient (float centerX, float centerY, float radius, int centerColor, int edgeColor, Shader.TileMode tileMode)
參數
centerX centerY 輻射中心的座標
radius 輻射半徑
centerColor 輻射中心的顏色
tileMode 輻射範圍之外的着色規則,類型是 TileMode
使用:
    /**
     * 環形渲染,RadialGradient(float centerX, float centerY, float radius, @ColorInt int colors[], @Nullable float stops[], TileMode tileMode)
     * centerX ,centerY:shader的中心座標,開始漸變的座標
     * radius:漸變的半徑
     * centerColor,edgeColor:中心點漸變顏色,邊界的漸變顏色
     * colors:漸變顏色數組
     * stoops:漸變位置數組,類似掃描漸變的positions數組,取值[0,1],中心點爲0,半徑到達位置爲1.0f
     * tileMode:shader未覆蓋以外的填充模式。
     */
    mShader = new RadialGradient(250, 250, 250, new int[]{Color.GREEN, Color.YELLOW, Color.RED}, null, Shader.TileMode.CLAMP);
    mPaint.setShader(mShader);
    canvas.drawCircle(250, 250, 250, mPaint);
效果

在這裏插入圖片描述

SweepGradient 掃描渲染
public SweepGradient (float cx, float cy, int color0, int color1)
參數
cx cy 掃描的中心
color0 掃描的起始顏色
color1 掃描的終止顏色
使用:
     /**
     * 掃描渲染,SweepGradient(float cx, float cy, @ColorInt int color0,int color1)
     * cx,cy 漸變中心座標
     * color0,color1:漸變開始結束顏色
     * colors,positions:類似LinearGradient,用於多顏色漸變,positions爲null時,根據顏色線性漸變
     */
    mShader = new SweepGradient(250, 250, Color.RED, Color.GREEN);
    mPaint.setShader(mShader);
    canvas.drawCircle(250, 250, 250, mPaint);
效果

在這裏插入圖片描述

位圖渲染
public BitmapShader (Bitmap bitmap, Shader.TileMode tileX, Shader.TileMode tileY)
參數
bitmap 用來做模板的 Bitmap對象
tileX 橫向的着色規則 ,類型是TileMode
tileY 縱向的着色規則 ,類型是TileMode
使用:
     /**
     * 位圖渲染,BitmapShader(@NonNull Bitmap bitmap, @NonNull TileMode tileX, @NonNull TileMode tileY)
     * Bitmap:構造shader使用的bitmap
     * tileX:X軸方向的TileMode
     * tileY:Y軸方向的TileMode
     * REPEAT, 繪製區域超過渲染區域的部分,重複排版
     *   CLAMP, 繪製區域超過渲染區域的部分,會以最後一個像素拉伸排版
     *  MIRROR, 繪製區域超過渲染區域的部分,鏡像翻轉排版
     */
    mShader = new BitmapShader(mBitmap, Shader.TileMode.REPEAT, Shader.TileMode.MIRROR);
    mPaint.setShader(mShader);
    canvas.drawRect(0,0,500, 500, mPaint);

在這裏插入圖片描述鏡像是因爲MIRROR
重複是因爲REPEAT
還有一個CLAMP,將圖片最後一個拉伸

如果改成橫軸改成 CLAMP

        mShader = new BitmapShader(mBitmap, Shader.TileMode.CLAMP, Shader.TileMode.MIRROR);
        mPaint.setShader(mShader);
        canvas.drawRect(0,0,500, 500, mPaint);

在這裏插入圖片描述

組合渲染
public ComposeShader (Shader shaderA, Shader shaderB, PorterDuff.Mode mode)
參數
shaderA shaderB 兩個相繼使用的 Shader
mode 兩個Sharder的疊加模式,ShaderA 和 shaderB應該怎樣共同繪製。它的類型是PorterDuff.Mode
        /**
         * 組合渲染,
         * ComposeShader(@NonNull Shader shaderA, @NonNull Shader shaderB, Xfermode mode)
         * ComposeShader(@NonNull Shader shaderA, @NonNull Shader shaderB, PorterDuff.Mode mode)
         * shaderA,shaderB:要混合的兩種shader
         * Xfermode mode: 組合兩種shader顏色的模式
         * PorterDuff.Mode mode: 組合兩種shader顏色的模式
         */
        BitmapShader bitmapShader = new BitmapShader(mBitmap, Shader.TileMode.REPEAT, Shader.TileMode.REPEAT);
        LinearGradient linearGradient = new LinearGradient(0, 0, 1000, 1600, new int[]{Color.RED, Color.GREEN, Color.BLUE}, null, Shader.TileMode.CLAMP);
        mShader = new ComposeShader(bitmapShader, linearGradient, PorterDuff.Mode.MULTIPLY);
        mPaint.setShader(mShader);
        canvas.drawCircle(250, 250, 250, mPaint);

在這裏插入圖片描述

Shader.TileMode着色模式

ShaderTileMode着色模式
Shader.TileMode.CLAMP 超出的部分以最後一個像素來排版
Shader.TileMode.MIRROR 超出的部分以鏡像翻轉來排版
Shader.TileMode.REPEAT 超出的部分重複排版
使用:

        mShader = new BitmapShader(mBitmap, Shader.TileMode.REPEAT, Shader.TileMode.MIRROR);
        mPaint.setShader(mShader);
        canvas.drawRect(0,0,500, 500, mPaint);
PorterDuff.Mode圖層混合模式

它將所繪製圖形的像素與Canvas中對應位置的像素按照一定規則進行混合,形成新的像素值,從而更新 Canvas中最終的像素顏色值

18種模式

public class PorterDuff {
    public PorterDuff() {
        throw new RuntimeException("Stub!");
    }

    public static enum Mode {
        ADD,
        CLEAR,
        DARKEN,
        DST,
        DST_ATOP,
        DST_IN,
        DST_OUT,
        DST_OVER,
        LIGHTEN,
        MULTIPLY,
        OVERLAY,
        SCREEN,
        SRC,
        SRC_ATOP,
        SRC_IN,
        SRC_OUT,
        SRC_OVER,
        XOR;

        private Mode() {
        }
    }
}

三個使用的地方

        //1.ComposeShader
        //2.畫筆Paint.setXfermode()
        //3.PorterDuffColorFilter

首先禁止硬件加速

 //禁止硬件加速
 setLayerType(View.LAYER_TYPE_SOFTWARE, null);

谷歌提供APIDemos教我們如何使用

https://github.com/THEONE10211024/ApiDemos

找到
XfermodesActivity

離屏繪製

通過使用離屏緩衝,把要繪製的內容單獨繪製在緩衝層,保證 Xfermode的使用不會出現錯誤的結果。

使用離屏緩衝有兩種方式

第一種

Canvas saveLayer()可以做短時的離屏緩衝,在繪製之前保存,繪製之後恢復

第二種

View.setLayerType()直接把整個View都繪製在離屏緩衝中。
setLayerType(LAYER_TYPE_ HARDWARE)使用GPU來緩衝,
setLayerType(LAYER_TYPE_SOFTWARE)使用一個 Bitmap來緩衝

先看第一種:

public class XfermodeView extends View {

    private Paint mPaint;
    private int mWidth, mHeight;

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

    public XfermodeView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public XfermodeView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }


    private void init() {
        //初始化畫筆
        mPaint = new Paint();
        mPaint.setColor(Color.RED);
        mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        mWidth = MeasureSpec.getSize(widthMeasureSpec);
        mHeight = MeasureSpec.getSize(heightMeasureSpec);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        //1.ComposeShader
        //2.畫筆Paint.setXfermode()
        //3.PorterDuffColorFilter

        //禁止硬件加速
        setLayerType(View.LAYER_TYPE_SOFTWARE, null);

        setBackgroundColor(Color.GRAY);

        //離屏繪製
        int layerId = canvas.saveLayer(0,0, getWidth(), getHeight(), mPaint, Canvas.ALL_SAVE_FLAG);

        //目標圖
        canvas.drawBitmap(createRectBitmap(mWidth, mHeight), 0, 0, mPaint);
        //設置混合模式
        mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
        //源圖,重疊區域右下角部分
        canvas.drawBitmap(createCircleBitmap(mWidth, mHeight), 0, 0, mPaint);
        //清除混合模式
        mPaint.setXfermode(null);

        canvas.restoreToCount(layerId);

    }

    //畫矩形Dst
    public Bitmap createRectBitmap(int width, int height) {
        Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);
        Paint dstPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        dstPaint.setColor(0xFF66AAFF);
        canvas.drawRect(new Rect(width / 20, height / 3, 2 * width / 3, 19 * height / 20), dstPaint);
        return bitmap;
    }

    //畫圓src
    public Bitmap createCircleBitmap(int width, int height) {
        Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);
        Paint scrPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        scrPaint.setColor(0xFFFFCC44);
        canvas.drawCircle(width * 2 / 3, height / 3, height / 4, scrPaint);
        return bitmap;
    }


}

效果

在這裏插入圖片描述如果去掉離屏繪製,將如下代碼註釋掉

 //離屏繪製
        int layerId = canvas.saveLayer(0,0, getWidth(), getHeight(), mPaint, Canvas.ALL_SAVE_FLAG);
  canvas.restoreToCount(layerId);

則效果
在這裏插入圖片描述

注意

添加離屏繪製,是先將矩形和圓合成一個圖形,然後繪製到canvas中,再添加背景 setBackgroundColor(Color.GRAY);

而不添加離屏繪製,是將背景和矩形以及圓都繪製到canvas中。導致合成的圖有灰色的背景。

也就是說離屏繪製是像圖層一樣,先後擺放繪製。

具體小案例

hongyang的博客 刮刮卡效果

pain效果相關 濾鏡

LightingColorFilter光照效果濾鏡
public LightingColorFilter (int mul, int add)

mul和add都是和顏色值格式相同的int值,其中mul用來和目標像素相乘,add用來和目標像素相加:
alpha通道將被忽略.

如果 mul 爲 0xffffff,add 爲 0x000000則爲原圖

R' = R * mul.R / 0xff + add.R
G' = G * mul.G / 0xff + add.G
B' = B * mul.B / 0xff + add.B

R G B目標
R' 得到後的結果

使用:

        /**
         * R' = R * mul.R / 0xff + add.R 00
         * G' = G * mul.G / 0xff + add.G ff
         * B' = B * mul.B / 0xff + add.B ff
         */
        //紅色去除掉
        LightingColorFilter lighting = new   LightingColorFilter(0x00ffff,0x000000);
        mPaint.setColorFilter(lighting);
        canvas.drawBitmap(mBitmap, 0,0, mPaint);

在這裏插入圖片描述

PorterDuffColorFilter濾鏡

使用一個指定的顏色和一種指定的 PorterDuff.Mode 來與繪製對象進行合成.

public PorterDuffColorFilter (int color, PorterDuff.Mode mode)
參數
color 具體的顏色值
mode 指定PorterDuff.Mode混合模式
        PorterDuffColorFilter porterDuffColorFilter = new PorterDuffColorFilter(Color.RED, PorterDuff.Mode.DARKEN);
        mPaint.setColorFilter(porterDuffColorFilter);
        canvas.drawBitmap(mBitmap, 100, 0, mPaint);
ColorMatrixColorFilter
public ColorMatrixColorFilter (float[] array)
參數
array 4*5列矩陣數組
使用
        float[] colorMatrix = {
                1,0,0,0,0,   //red
                0,1,0,0,0,   //green
                0,0,1,0,0,   //blue
                0,0,0,1,0    //alpha
        };
        mColorMatrixColorFilter = new ColorMatrixColorFilter(colorMatrix);
        mPaint.setColorFilter(mColorMatrixColorFilter);
        canvas.drawBitmap(mBitmap, 100, 0, mPaint);
        ColorMatrix cm = new ColorMatrix();
        //亮度調節,調節初始矩陣進行重新賦值
        cm.setScale(1,2,1,1);
//
        //飽和度調節0-無色彩, 1- 默認效果, >1飽和度加強
//        cm.setSaturation(2);
//
//        //色調調節
//        cm.setRotate(0, 45);
//
        mColorMatrixColorFilter = new ColorMatrixColorFilter(cm);
        mPaint.setColorFilter(mColorMatrixColorFilter);
        canvas.drawBitmap(mBitmap, 100, 0, mPaint);

參考:
https://hencoder.com/ui-1-2/

部分內容參考於網絡,無法找到原創標記。如果是你原創,請聯繫我添加。

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