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