Android 之 Shader 用法詳細介紹

概述

Shader 是Android中非常重要的一個類 一般稱之為著色器,其作用是用來給圖像著色,我們一般在自定義View的時候通過paint.setShader(Shader shader)使用比較多 Shader有五個子類 下面將對每個API的使用做詳細介紹

BitmapShader(圖像渲染)

構造方法

public BitmapShader(@NonNull Bitmap bitmap, TileMode tileX, TileMode tileY)

該API是針對Bitmap進行繪制的 其參數含義

bitmap : 要進行繪制的bitmap
tileX : 在X軸處理的效果,Shader.TileMode里有三種模式:CLAMP、MIRROR和REPETA
tileY : 在Y軸處理的效果,Shader.TileMode里有三種模式:CLAMP、MIRROR和REPETA

這里對先對Shader.TileMode里有三種(拉伸)模式進行詳解 后面的內容可以以此為參考(區分X軸和Y軸)

1.Shader.TileMode.CLAMP:

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    Bitmap bitmap = ((BitmapDrawable)getResources().getDrawable(R.mipmap.mifeng)).getBitmap();
    BitmapShader bitmapShader=new BitmapShader(bitmap, Shader.TileMode.CLAMP,Shader.TileMode.CLAMP);
    paint.setShader(bitmapShader);
    //畫矩形圖
    canvas.drawRect(new RectF(0,0,1000,1200),paint);

Shader.TileMode.CLAMP會將邊緣的像素進行拉伸、擴展到整個View的寬度或高度

2.Shader.TileMode.MIRROR(鏡像)

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    Bitmap bitmap = ((BitmapDrawable)getResources().getDrawable(R.mipmap.mifeng)).getBitmap();
    BitmapShader bitmapShader=new BitmapShader(bitmap, Shader.TileMode.MIRROR,Shader.TileMode.MIRROR);
    paint.setShader(bitmapShader);
    //畫矩形圖
    canvas.drawRect(new RectF(0,0,1000,1200),paint);

Shader.TileMode.MIRROR在繪制的矩形區域內,X軸方向和Y軸方向上出現了鏡面翻轉 直到占滿整個View的寬高

3.Shader.TileMode.REPEAT(平鋪):

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    Bitmap bitmap = ((BitmapDrawable)getResources().getDrawable(R.mipmap.mifeng)).getBitmap();
    BitmapShader bitmapShader=new BitmapShader(bitmap, Shader.TileMode.REPEAT,Shader.TileMode.REPEAT);
    paint.setShader(bitmapShader);
    //畫矩形圖
    canvas.drawRect(new RectF(0,0,1000,1200),paint);

Shader.TileMode.REPEAT 將圖像進行復制平鋪 跟電腦桌面壁紙一樣 占不滿一屏會進行平鋪

另外通過BitmapShader自定義圓形或圓角矩形非常的簡單

//構造函數一
@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
      BitmapShader bitmapShader=new BitmapShader(bitmap, Shader.TileMode.REPEAT,Shader.TileMode.REPEAT);
        paint.setShader(bitmapShader);
        //將圖片通過矩陣拉伸為正方形
        int max = Math.max(bitmapWidth, bitmapHeight);
        int scale = max/ Math.min(bitmapWidth, bitmapHeight);
        Matrix matrix=new Matrix();
        matrix.setScale(scale,scale);
        bitmapShader.setLocalMatrix(matrix);
        //畫圓形圖
        //canvas.drawCircle(max/2,max/2,max/2,paint);
        //畫橢圓形圖
        canvas.drawOval(new RectF(0,0,bitmapWidth,bitmapHeight),paint);
   }
LinearGradient(線性渲染)

構造函數:

LinearGradient(float x0, float y0, float x1, float y1, int color0, int color1,TileMode tile)

x0,y0:表示漸變的起點坐標
x1,y1:表示漸變的終點坐標
color0,color1:表示起點的顏色和終點的顏色。
TileMode:和上面講的完全一致,不贅述了。

LinearGradient(float x0, float y0, float x1, float y1, int colors[], float positions[],TileMode tile)

x0,y0:表示漸變的起點坐標
x1,y1:表示漸變的終點坐標
colors[]:傳入多個顏色,產生更加豐富的漸變效果。
float[]:可以設置在不同的渲染階段渲染不同的顏色
TileMode:和上面講的完全一致,不贅述了。
//構造函數一
@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
      LinearGradient linearGradient=new LinearGradient(0,0,1000,50,Color.RED,Color.BLUE,Shader.TileMode.REPEAT);
      paint.setShader(linearGradient);
      paint.setStyle(Paint.Style.FILL);
      paint.setStrokeWidth(10);
      canvas.drawRect(new RectF(10,10,1000,50),paint);
   }
//構造函數二
@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
      int[] mColors = {Color.RED,Color.GREEN,Color.BLUE,Color.YELLOW};
      float[] loaction=new float[] {0.25F, 0.5F, 0.75F, 1.0F };
      LinearGradient linearGradient=new LinearGradient(0,0,1000,50,mColors,loaction,Shader.TileMode.REPEAT);
      paint.setShader(linearGradient);
      paint.setStyle(Paint.Style.FILL);
      paint.setStrokeWidth(10);
      canvas.drawRect(new RectF(10,10,1000,50),paint);
   }


提示:

  • 通過效果圖看到在使用第二種方式創建對象的時候float[] loaction=new float[] {0.25F, 0.5F, 0.75F, 1.0F }的作用就是規劃View每個繪制階段繪制的顏色 比如在繪制0-25%的時候是紅色 25%-50%是綠色 并以此類推
  • 另外需要注意的是float[] loaction的長度要與color[]的長度保持一致 且color[]的長度不得低于2 不然會報錯 看源碼就知道:
if (colors.length < 2) {
 throw new IllegalArgumentException("needs >= 2 number of colors");
}
if (positions != null && colors.length != positions.length){
 throw new IllegalArgumentException("color and position arrays must be of equal length");
}
RadialGradient(環形渲染,圓形中心向四周漸變的效果)

RadialGradient常用于水波紋效果
構造方法:

RadialGradient(float centerX, float centerY, float radius,
@NonNull int colors[], @Nullable float stops[], @NonNull TileMode tileMode)

這里的構造方法注意點與LinearGradient一致 這里不再贅述

centerX,centerY:表示漸變的起點坐標(中心點)
radius:表示漸變半徑長度
colors[]:傳入多個顏色,產生更加豐富的漸變效果。
float[]:可以設置在不同的渲染階段渲染不同的顏色
TileMode:和上面講的完全一致,不贅述了。

RadialGradient(float centerX, float centerY, float radius,
int centerColor, int edgeColor, @NonNull TileMode tileMode)

centerX,centerY:表示漸變的起點坐標(中心點)
radius:表示漸變半徑長度
color0,color1:表示起點的顏色和終點的顏色。
TileMode:和上面講的完全一致,不贅述了。
@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    int[] mColors = {Color.RED,Color.GREEN,Color.BLUE,Color.YELLOW};
    float[] loaction=new float[] {0.25F, 0.5F, 0.75F, 1.0F };
    RadialGradient radialGradient=new RadialGradient(300,300,300,mColors,loaction,Shader.TileMode.CLAMP);
    paint.setShader(radialGradient);
    paint.setStyle(Paint.Style.FILL);
    canvas.drawCircle(300,300,300,paint);
   }
SweepGradient(梯度渲染)

SweepGradient類似于雷達掃描的效果

構造函數:

SweepGradient(float cx, float cy,int colors[], float positions[])

cx,cx:表示漸變的起點坐標(中心點)
colors[]:傳入多個顏色,產生更加豐富的漸變效果。
float[]:與LinearGradient的positions[]效果一致 可以為null

SweepGradient(float cx, float cy, int color0, int color1)

cx,cx:表示漸變的起點坐標(中心點)
color0,color1:開始顏色,結束顏色。
@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
   int[] mColors = {Color.RED,Color.GREEN,Color.BLUE,Color.YELLOW};
   SweepGradient sweepGradient=new SweepGradient(300,300,mColors,null);
   paint.setShader(sweepGradient);
   canvas.drawCircle(300,300,300,paint);
}

雷達效果(gif表現不怎么好 將就看下):


ComposeShader(組合模式)

構造函數:

ComposeShader (Shader shaderA, Shader shaderB, Xfermode mode)
ComposeShader (Shader shaderA, Shader shaderB, PorterDuff.Mode mode)

兩個構造函數都差不多 將2個Shader進行混合渲染 只是最后一個參數指定了混合模式
關于混合模式可以參考:Android靈魂畫家的18種混合模式

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    Bitmap bitmap1 = ((BitmapDrawable)getResources().getDrawable(R.mipmap.heart)).getBitmap();
        BitmapShader bitmapShader1=new BitmapShader(bitmap1, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
        LinearGradient linearGradient1=new LinearGradient(0,0,bitmap1.getWidth(),bitmap1.getHeight(), Color.GREEN,Color.BLUE, Shader.TileMode.CLAMP);
        //取兩圖層交集部分疊加后顏色
        ComposeShader composeShader1=new ComposeShader(bitmapShader1,linearGradient1,PorterDuff.Mode.MULTIPLY);
        paint.setShader(composeShader1);
        canvas.drawRect(0,0,bitmap1.getWidth(),bitmap1.getHeight(),paint);

        canvas.translate(0,200);
        linearGradient1=new LinearGradient(0,0,bitmap1.getWidth(),bitmap1.getHeight(), Color.RED,Color.RED, Shader.TileMode.CLAMP);
        //取兩圖層交集部分疊加后顏色
        composeShader1=new ComposeShader(bitmapShader1,linearGradient1,PorterDuff.Mode.MULTIPLY);
        paint.setShader(composeShader1);
        canvas.drawRect(0,0,bitmap1.getWidth(),bitmap1.getHeight(),paint);
}


關于Shader的相關基本使用方法就介紹到這里 另外Shader還支持各種矩陣操作 通過setLocalMatrix(matrix)調用 哎 感覺一篇下來都在拼圖 好累!

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • Android繪圖之Shader Shader是繪圖過程中的著色器,它有五個子類: BitmapShader Co...
    lavor閱讀 15,358評論 3 62
  • 在上篇說道BitmapShader的使用關于Shader.TileMode這個參數在說明一下Shader.Tile...
    大大大寒閱讀 1,575評論 3 1
  • LinearGradient 線性漸變渲染器 LinearGradient中文翻譯過來就是線性漸變的意思。線性漸變...
    53a92716edbe閱讀 423評論 1 2
  • 他站在窗戶前,目光所及之處是一座座高樓,廣場大媽跳舞的節奏曲子時不時傳入耳邊。天空一片湛藍,可憐到沒...
    軒殤公子閱讀 278評論 0 0
  • 是真的,我不服輸地嘗試了很多職業和愛好,總算找到我可以安安靜靜做一輩子的一個手藝。哪怕再小,我希望一生都可以慢慢做...
    攝影師柳丁閱讀 146評論 0 1