Android繪圖之LinearGradient線性漸變(9)

Android 繪圖學(xué)習(xí)

1 linearGradient簡(jiǎn)介

linearGradient線性漸變献酗,會(huì)用到Paint的setShader蚜厉,Shader 被稱為著色器,在opengl中這個(gè)概念經(jīng)常被用到,android中的shader主要用來(lái)給圖像著色惋耙,Shader在繪制過(guò)程中會(huì)返回橫向重要的顏色組乱陡,Paint設(shè)置shader后浇揩,繪制時(shí)會(huì)從shader中獲取顏色,也就是需要shader告訴畫筆某處的顏色值憨颠。

Shader 具體實(shí)現(xiàn)類包括:
BitmapShader,ComposeShader,LinearGradient,RadialGradient,SweepGradient

https://blog.csdn.net/u010126792/article/details/83787779 我在 這篇文章中寫過(guò)android漸變的實(shí)現(xiàn)胳徽,此處就從LinearGradient開(kāi)始學(xué)習(xí)。
LinearGradient兩種構(gòu)造函數(shù):

/**
 * Create a shader that draws a linear gradient along a line.
 *
 * @param x0       The x-coordinate for the start of the gradient line
 * @param y0       The y-coordinate for the start of the gradient line
 * @param x1       The x-coordinate for the end of the gradient line
 * @param y1       The y-coordinate for the end of the gradient line
 * @param color0   The color at the start of the gradient line.
 * @param color1   The color at the end of the gradient line.
 * @param tile     The Shader tiling mode
*/
public LinearGradient(float x0, float y0, float x1, float y1,
    @ColorInt int color0, @ColorInt int color1, @NonNull TileMode tile) 爽彤;


/**
 * Create a shader that draws a linear gradient along a line.
 *
 * @param x0           The x-coordinate for the start of the gradient line
 * @param y0           The y-coordinate for the start of the gradient line
 * @param x1           The x-coordinate for the end of the gradient line
 * @param y1           The y-coordinate for the end of the gradient line
 * @param colors       The colors to be distributed along the gradient line
 * @param positions    May be null. The relative positions [0..1] of
 *                     each corresponding color in the colors array. If this is null,
 *                     the the colors are distributed evenly along the gradient line.
 * @param tile         The Shader tiling mode
*/
public LinearGradient(float x0, float y0, float x1, float y1, @NonNull @ColorInt int colors[], @Nullable float positions[], @NonNull TileMode tile) 养盗;

參數(shù)說(shuō)明:
(x0,y0):漸變起始點(diǎn)坐標(biāo)
(x1,y1):漸變結(jié)束點(diǎn)坐標(biāo)
color0:漸變開(kāi)始點(diǎn)顏色,16進(jìn)制的顏色表示,必須要帶有透明度
color1:漸變結(jié)束顏色
colors:漸變數(shù)組
positions:位置數(shù)組适篙,position的取值范圍[0,1],作用是指定某個(gè)位置的顏色值往核,如果傳null,漸變就線性變化嚷节。
tile:用于指定控件區(qū)域大于指定的漸變區(qū)域時(shí)聂儒,空白區(qū)域的顏色填充方法虎锚。

  • CLAMP邊緣拉伸,為被shader覆蓋區(qū)域衩婚,使用shader邊界顏色進(jìn)行填充
    -REPEAT 在水平和垂直兩個(gè)方向上重復(fù)窜护,相鄰圖像沒(méi)有間隙
    -MIRROR以鏡像的方式在水平和垂直兩個(gè)方向上重復(fù),相鄰圖像有間隙

第一個(gè)構(gòu)造函數(shù)可以指定兩個(gè)顏色之間的漸變非春,第二個(gè)構(gòu)造函數(shù)可以指定多個(gè)顏色之間的漸變柄慰,線性漸變不但可以代碼實(shí)現(xiàn)還可以xml文件實(shí)現(xiàn),這里只講解代碼實(shí)現(xiàn)方式税娜。

2 兩種顏色的線性漸變

只需要設(shè)置開(kāi)始結(jié)束點(diǎn)坐標(biāo)坐搔,開(kāi)始顏色,結(jié)束顏色敬矩。
實(shí)例代碼:

mPaint = new Paint();
mPaint.setColor(Color.BLUE);
mPaint.setAntiAlias(true);
mPaint.setStrokeWidth(3);
mPaint.setStyle(Paint.Style.FILL);
mPaint.setTextSize(20);

LinearGradient linearGradient = new LinearGradient(getWidth(),400,0,0,Color.RED,Color.GREEN, Shader.TileMode.CLAMP);
mPaint.setShader(linearGradient);
canvas.drawRect(0,0,getWidth(),400,mPaint);

xml中設(shè)置漸變可以通過(guò)設(shè)置angle角度來(lái)改變漸變的開(kāi)始結(jié)束概行,可以設(shè)置從上到下,從下到上弧岳,從左到右凳忙,從右到左,代碼中如何設(shè)置呢禽炬?

3 如何通過(guò)坐標(biāo)設(shè)置漸變方向:

通過(guò)坐標(biāo)可以輕松實(shí)現(xiàn)涧卵,漸變方向的控制:
(0,0)->(0,400)從上到下
(0,400)->(0,0) 從下到上

0,0)->(getMeasuredWidth(),0) 表示從左到右
(getMeasuredWidth(),0)->(0,0) 表示從右到左

0,0)-> (getMeasuredWidth(),getMeasuredHeight()) 斜角,從左上角到右下角

從左到右:

從右到左:


** 漸變填充顏色總結(jié)**

  • 要實(shí)現(xiàn)從上到下需要設(shè)置shader開(kāi)始結(jié)束點(diǎn)坐標(biāo)為左上角到左下角或右上角到右下角坐標(biāo)腹尖。

  • 要實(shí)現(xiàn)從下到上需要設(shè)置shader開(kāi)始結(jié)束點(diǎn)坐標(biāo)為左下角到左上角或右下角到右上角柳恐。

  • 要實(shí)現(xiàn)從左到右需要設(shè)置shader開(kāi)始結(jié)束點(diǎn)坐標(biāo)為左上角到右上角或者左下角到右下角。

  • 要實(shí)現(xiàn)從右到左需要設(shè)置shader開(kāi)始結(jié)束坐標(biāo)為右上角到左上角或者右下角到左下角热幔。

  • 要實(shí)現(xiàn)對(duì)角shader乐设,需要設(shè)置開(kāi)始結(jié)束點(diǎn)坐標(biāo)左上角到右下角。

4 多顏色填充 colors绎巨,positions數(shù)組參數(shù)講解

LinearGradient(float x0, float y0, float x1, float y1, @NonNull @ColorInt int colors[], @Nullable float positions[], @NonNull TileMode tile) 近尚;

positions為null時(shí),線性填充场勤,和沒(méi)有positions數(shù)組的構(gòu)造函數(shù)效果一樣戈锻。

Positions數(shù)組中值為0-1,0表示開(kāi)始繪制點(diǎn),1表示結(jié)束點(diǎn)和媳,0.5對(duì)應(yīng)中間點(diǎn)等等格遭。數(shù)組中位置信息對(duì)應(yīng)顏色數(shù)組中的顏色。
//例如
int [] colors = {Color.RED,Color.GREEN, Color.BLUE};
float[] position = {0f, 0.3f, 1.0f};
上面position[0]對(duì)應(yīng)數(shù)組中的第一個(gè)RED窗价,0.3f的位置對(duì)應(yīng)顏色中的GREEN如庭,1.0f的位置對(duì)應(yīng)顏色中的BLUE,所以從0-0.3的位置是從RED到GREEN的漸變,從0.3到1.0的位置的顏色漸變是GREEN到BLUE坪它。

int [] colors = {Color.RED,Color.GREEN, Color.BLUE};
float[] position = {0f, 0.3f, 1.0f};
LinearGradient linearGradient = new LinearGradient(0,0,getMeasuredWidth(),0,colors,position, Shader.TileMode.CLAMP);

mPaint.setShader(linearGradient);
canvas.drawRect(0,0,getMeasuredWidth(),getMeasuredHeight(),mPaint);

如果把0.3改成0.7骤竹,


5 利用LinearGradient實(shí)現(xiàn)變色字體

利用設(shè)置了變色shader的畫筆,就可以畫出變色字體:

 int [] colors = {Color.RED,Color.GREEN, Color.BLUE};
 float[] position = {0f, 0.7f, 1.0f};
 LinearGradient linearGradient = new LinearGradient(0,0,getMeasuredWidth(),0,colors,position, Shader.TileMode.CLAMP);

 mPaint.setShader(linearGradient);
// canvas.drawRect(0,0,getMeasuredWidth(),getMeasuredHeight(),mPaint);
 canvas.drawText("Android繪圖小糊涂",0,getMeasuredHeight()/2,mPaint);

如何讓字體顏色不停地變動(dòng):
Shader 可以設(shè)置matrix變換往毡,利用translate不停地移動(dòng)shader,實(shí)現(xiàn)漸變效果蒙揣,下面的實(shí)例不能用于生產(chǎn)環(huán)境,我只是寫個(gè)例子开瞭,后面會(huì)開(kāi)文章講解可用于生產(chǎn)的漸變懒震。

int [] colors = {Color.BLACK,Color.RED, Color.BLUE,Color.BLACK};
Rect rect = new Rect();
mPaint.getTextBounds(str,0,str.length(), rect);
int fontWidth = rect.width();
linearGradient = new LinearGradient(0,0,-fontWidth+10,0,colors,null, Shader.TileMode.CLAMP);
Matrix matrix = new Matrix();
matrix.setTranslate(tran,0);
linearGradient.setLocalMatrix(matrix);
tran = (tran + advance) ;
if (tran >= fontWidth*2){
   tran = 0;
}
mPaint.setShader(linearGradient);
canvas.drawText(str,0,getMeasuredHeight()/2,mPaint);
invalidate();

TileMode 邊緣填充模式

如果shader的大小小于view的大小時(shí)如何繪制其他沒(méi)有被shader覆蓋的區(qū)域?
跟最后一個(gè)參數(shù)有關(guān)嗤详,
-CLAMP
邊緣拉伸个扰,利用邊緣的顏色,填充剩余部分
-REPEAT
在水平和垂直兩個(gè)方向上重復(fù)葱色,相鄰圖像沒(méi)有間隙递宅,重復(fù)shader
-MIRROR
以鏡像的方式在水平和垂直兩個(gè)方向上重復(fù),相鄰圖像有間隙苍狰,鏡面shader

LinearGradient linearGradient = new LinearGradient(0,0,getMeasuredWidth()/2,getMeasuredHeight()/2,Color.RED,Color.GREEN, Shader.TileMode.CLAMP);
mPaint.setShader(linearGradient);
canvas.drawRect(0,0,getMeasuredWidth(),getMeasuredHeight(),mPaint);

CLAMP:

REPEAT:

MIRROR:

如果想要從對(duì)角線設(shè)置shader办龄,圖形最好是正方形這樣比較好看設(shè)置:

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

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    LinearGradient linearGradient = new LinearGradient(0,0,getMeasuredWidth()/2,getMeasuredHeight()/2,Color.RED,Color.GREEN, Shader.TileMode.MIRROR);
    mPaint.setShader(linearGradient);
    canvas.drawRect(0,0,getMeasuredWidth(),getMeasuredHeight(),mPaint);
}

android繪圖之Paint(1)
android繪圖之Canvas基礎(chǔ)(2)
Android繪圖之Path(3)
Android繪圖之drawText繪制文本相關(guān)(4)
Android繪圖之Canvas概念理解(5)
Android繪圖之Canvas變換(6)
Android繪圖之Canvas狀態(tài)保存和恢復(fù)(7)
Android繪圖之PathEffect (8)
Android繪圖之LinearGradient線性漸變(9)
Android繪圖之SweepGradient(10)
Android繪圖之RadialGradient 放射漸變(11)
Android繪制之BitmapShader(12)
Android繪圖之ComposeShader,PorterDuff.mode及Xfermode(13)
Android繪圖之drawText,getTextBounds,measureText,FontMetrics,基線(14)
Android繪圖之貝塞爾曲線簡(jiǎn)介(15)
Android繪圖之PathMeasure(16)
Android 動(dòng)態(tài)修改漸變 GradientDrawable

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末淋昭,一起剝皮案震驚了整個(gè)濱河市俐填,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌翔忽,老刑警劉巖英融,帶你破解...
    沈念sama閱讀 217,185評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異呀打,居然都是意外死亡矢赁,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,652評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門贬丛,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人给涕,你說(shuō)我怎么就攤上這事豺憔。” “怎么了够庙?”我有些...
    開(kāi)封第一講書人閱讀 163,524評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵恭应,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我耘眨,道長(zhǎng)昼榛,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書人閱讀 58,339評(píng)論 1 293
  • 正文 為了忘掉前任剔难,我火速辦了婚禮胆屿,結(jié)果婚禮上奥喻,老公的妹妹穿的比我還像新娘。我一直安慰自己非迹,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,387評(píng)論 6 391
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著桐猬,像睡著了一般挠说。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上纯命,一...
    開(kāi)封第一講書人閱讀 51,287評(píng)論 1 301
  • 那天西剥,我揣著相機(jī)與錄音,去河邊找鬼亿汞。 笑死蔫耽,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的留夜。 我是一名探鬼主播匙铡,決...
    沈念sama閱讀 40,130評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼碍粥!你這毒婦竟也來(lái)了鳖眼?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 38,985評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤嚼摩,失蹤者是張志新(化名)和其女友劉穎钦讳,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體枕面,經(jīng)...
    沈念sama閱讀 45,420評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡愿卒,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,617評(píng)論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了潮秘。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片琼开。...
    茶點(diǎn)故事閱讀 39,779評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖枕荞,靈堂內(nèi)的尸體忽然破棺而出柜候,到底是詐尸還是另有隱情,我是刑警寧澤躏精,帶...
    沈念sama閱讀 35,477評(píng)論 5 345
  • 正文 年R本政府宣布渣刷,位于F島的核電站,受9級(jí)特大地震影響矗烛,放射性物質(zhì)發(fā)生泄漏辅柴。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,088評(píng)論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望碌嘀。 院中可真熱鬧涣旨,春花似錦、人聲如沸筏餐。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,716評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)魁瞪。三九已至穆律,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間导俘,已是汗流浹背峦耘。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 32,857評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留旅薄,地道東北人辅髓。 一個(gè)月前我還...
    沈念sama閱讀 47,876評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像少梁,于是被迫代替她去往敵國(guó)和親洛口。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,700評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容