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里有三種(拉伸)模式進行詳解 后面的內容可以以此為參考(區(qū)分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在繪制的矩形區(qū)域內犹赖,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);
   }


提示:

  • 通過效果圖看到在使用第二種方式創(chuàng)建對象的時候float[] loaction=new float[] {0.25F, 0.5F, 0.75F, 1.0F }的作用就是規(guī)劃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(環(huán)形渲染,圓形中心向四周漸變的效果)

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)調用 哎 感覺一篇下來都在拼圖 好累静陈!

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市诞丽,隨后出現的幾起案子鲸拥,更是在濱河造成了極大的恐慌,老刑警劉巖僧免,帶你破解...
    沈念sama閱讀 211,290評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件刑赶,死亡現場離奇詭異,居然都是意外死亡懂衩,警方通過查閱死者的電腦和手機撞叨,發(fā)現死者居然都...
    沈念sama閱讀 90,107評論 2 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來浊洞,“玉大人牵敷,你說我怎么就攤上這事∨嫔辏” “怎么了劣领?”我有些...
    開封第一講書人閱讀 156,872評論 0 347
  • 文/不壞的土叔 我叫張陵,是天一觀的道長铁材。 經常有香客問我尖淘,道長,這世上最難降的妖魔是什么著觉? 我笑而不...
    開封第一講書人閱讀 56,415評論 1 283
  • 正文 為了忘掉前任村生,我火速辦了婚禮,結果婚禮上饼丘,老公的妹妹穿的比我還像新娘趁桃。我一直安慰自己,他們只是感情好肄鸽,可當我...
    茶點故事閱讀 65,453評論 6 385
  • 文/花漫 我一把揭開白布卫病。 她就那樣靜靜地躺著,像睡著了一般典徘。 火紅的嫁衣襯著肌膚如雪蟀苛。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,784評論 1 290
  • 那天逮诲,我揣著相機與錄音帜平,去河邊找鬼。 笑死梅鹦,一個胖子當著我的面吹牛裆甩,可吹牛的內容都是我干的。 我是一名探鬼主播齐唆,決...
    沈念sama閱讀 38,927評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼嗤栓,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了箍邮?” 一聲冷哼從身側響起抛腕,我...
    開封第一講書人閱讀 37,691評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎媒殉,沒想到半個月后担敌,有當地人在樹林里發(fā)現了一具尸體,經...
    沈念sama閱讀 44,137評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡廷蓉,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,472評論 2 326
  • 正文 我和宋清朗相戀三年全封,在試婚紗的時候發(fā)現自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片桃犬。...
    茶點故事閱讀 38,622評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡刹悴,死狀恐怖,靈堂內的尸體忽然破棺而出攒暇,到底是詐尸還是另有隱情土匀,我是刑警寧澤,帶...
    沈念sama閱讀 34,289評論 4 329
  • 正文 年R本政府宣布形用,位于F島的核電站就轧,受9級特大地震影響证杭,放射性物質發(fā)生泄漏。R本人自食惡果不足惜妒御,卻給世界環(huán)境...
    茶點故事閱讀 39,887評論 3 312
  • 文/蒙蒙 一解愤、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧乎莉,春花似錦送讲、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至边灭,卻和暖如春异希,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背存筏。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工宠互, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人椭坚。 一個月前我還...
    沈念sama閱讀 46,316評論 2 360
  • 正文 我出身青樓予跌,卻偏偏與公主長得像,于是被迫代替她去往敵國和親善茎。 傳聞我的和親對象是個殘疾皇子券册,可洞房花燭夜當晚...
    茶點故事閱讀 43,490評論 2 348

推薦閱讀更多精彩內容

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