1. 程式人生 > >Android中自定義檢視View

Android中自定義檢視View

標籤:

前言

好長時間沒寫blog了,心裡感覺有點空蕩蕩的,今天有時間就來寫一個關於自定義檢視的的blog吧。關於這篇blog,網上已經有很多案例了,其實沒什麼難度的。但是我們在開發的過程中有時候會用到一些自定義的View以達到我們所需要的效果。其實網上的很多案例我們看完之後,發現這部分沒什麼難度的,我總結了兩點:

1、準備紙和筆,計算座標

2、在onDraw方法中開始畫圖,invalidate方法重新整理,onTouchEvent方法監聽觸控事件

對於繪圖相關的知識,之前在弄JavaSE相關的知識的時候,寫過俄羅斯方塊,也是用畫筆繪製的,然後在重新整理。原理都一樣的。

在這個過程中,我們需要了解兩個很重要的東西:

畫筆:Paint

畫布:Canvas

引用資料

講解內容

那麼下面我們就開始來介紹相關的內容了。我主要分一下步驟來講解一下:

1、介紹Android中的Paint和Canvas的概念和使用方法

2、介紹Android中重要的概念渲染物件Shader

3、自定義一個LabelView(和Android中的TextView差不多)

4、自定義漸變的圓形和長條的SeekBar

5、自定義顏色選擇器

6、自定義閃爍的TextView

7、實現360手機衛士中的流量監控的折線圖

那麼我們也知道今天的文章內容應該會很多,所以大家要有耐心的看完。這篇文章如果看懂了,也耐心的看完了,相信對自定義View的相關知識瞭解的應該也差不多了,自己在開發的過程中實現自己想要的簡單的View應該是沒有問題的。

內容講解

下面開始正式介紹內容

一、介紹Android中的Paint和Canvas的概念和使用方法

Android中的Paint和Canvas的概念是很簡單的,就是我們用畫筆在畫布上進行繪製沒什麼難度的,我們只要拿到畫筆Paint和畫布Canvas物件就可以進行操作了。當然Canvas物件提供了很多繪製圖形的方法,下面來看一下程式碼吧:

package com.example.drawpathdemo;

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.graphics.Shader;
import android.util.AttributeSet;
import android.view.View;

public class DrawView extends View {

	public DrawView(Context context) {
		super(context);
	}
	
	public DrawView(Context context, AttributeSet attributeSet) {  
	    super(context, attributeSet);  
	}

	@SuppressLint("DrawAllocation")
	@Override
	protected void onDraw(Canvas canvas) {
		super.onDraw(canvas);
		/*
		 * 方法 說明 drawRect 繪製矩形 drawCircle 繪製圓形 drawOval 繪製橢圓 drawPath 繪製任意多邊形
		 * drawLine 繪製直線 drawPoin 繪製點
		 */
		// 建立畫筆
		Paint p = new Paint();
		p.setColor(Color.RED);// 設定紅色

		canvas.drawText("畫圓:", 10, 20, p);// 畫文字
		canvas.drawCircle(60, 20, 10, p);// 小圓
		p.setAntiAlias(true);// 設定畫筆的鋸齒效果。 true是去除,大家一看效果就明白了
		canvas.drawCircle(120, 20, 20, p);// 大圓

		canvas.drawText("畫線及弧線:", 10, 60, p);
		p.setColor(Color.GREEN);// 設定綠色
		canvas.drawLine(60, 40, 100, 40, p);// 畫線
		canvas.drawLine(110, 40, 190, 80, p);// 斜線
		//畫笑臉弧線
		p.setStyle(Paint.Style.STROKE);//設定空心
		RectF oval1=new RectF(150,20,180,40);
		canvas.drawArc(oval1, 180, 180, false, p);//小弧形
		oval1.set(190, 20, 220, 40);
		canvas.drawArc(oval1, 180, 180, false, p);//小弧形
		oval1.set(160, 30, 210, 60);
		canvas.drawArc(oval1, 0, 180, false, p);//小弧形

		canvas.drawText("畫矩形:", 10, 80, p);
		p.setColor(Color.GRAY);// 設定灰色
		p.setStyle(Paint.Style.FILL);//設定填滿
		canvas.drawRect(60, 60, 80, 80, p);// 正方形
		canvas.drawRect(60, 90, 160, 100, p);// 長方形

		canvas.drawText("畫扇形和橢圓:", 10, 120, p);
		/* 設定漸變色 這個正方形的顏色是改變的 */
		Shader mShader = new LinearGradient(0, 0, 100, 100,
				new int[] { Color.RED, Color.GREEN, Color.BLUE, Color.YELLOW,
						Color.LTGRAY }, null, Shader.TileMode.REPEAT); // 一個材質,打造出一個線性梯度沿著一條線。
		p.setShader(mShader);
		// p.setColor(Color.BLUE);
		RectF oval2 = new RectF(60, 100, 200, 240);// 設定個新的長方形,掃描測量
		canvas.drawArc(oval2, 200, 130, true, p);
		// 畫弧,第一個引數是RectF:該類是第二個引數是角度的開始,第三個引數是多少度,第四個引數是真的時候畫扇形,是假的時候畫弧線
		//畫橢圓,把oval改一下
		oval2.set(210,100,250,130);
		canvas.drawOval(oval2, p);

		canvas.drawText("畫三角形:", 10, 200, p);
		// 繪製這個三角形,你可以繪製任意多邊形
		Path path = new Path();
		path.moveTo(80, 200);// 此點為多邊形的起點
		path.lineTo(120, 250);
		path.lineTo(80, 250);
		path.close(); // 使這些點構成封閉的多邊形
		canvas.drawPath(path, p);

		// 你可以繪製很多任意多邊形,比如下面畫六連形
		p.reset();//重置
		p.setColor(Color.LTGRAY);
		p.setStyle(Paint.Style.STROKE);//設定空心
		Path path1=new Path();
		path1.moveTo(180, 200);
		path1.lineTo(200, 200);
		path1.lineTo(210, 210);
		path1.lineTo(200, 220);
		path1.lineTo(180, 220);
		path1.lineTo(170, 210);
		path1.close();//封閉
		canvas.drawPath(path1, p);
		/*
		 * Path類封裝複合(多輪廓幾何圖形的路徑
		 * 由直線段*、二次曲線,和三次方曲線,也可畫以油畫。drawPath(路徑、油漆),要麼已填充的或撫摸
		 * (基於油漆的風格),或者可以用於剪斷或畫畫的文字在路徑。
		 */
		
		//畫圓角矩形
		p.setStyle(Paint.Style.FILL);//充滿
		p.setColor(Color.LTGRAY);
		p.setAntiAlias(true);// 設定畫筆的鋸齒效果
		canvas.drawText("畫圓角矩形:", 10, 260, p);
		RectF oval3 = new RectF(80, 260, 200, 300);// 設定個新的長方形
		canvas.drawRoundRect(oval3, 20, 15, p);//第二個引數是x半徑,第三個引數是y半徑
		
		//畫貝塞爾曲線
		canvas.drawText("畫貝塞爾曲線:", 10, 310, p);
		p.reset();
		p.setStyle(Paint.Style.STROKE);
		p.setColor(Color.GREEN);
		Path path2=new Path();
		path2.moveTo(100, 320);//設定Path的起點
		path2.quadTo(150, 310, 170, 400); //設定貝塞爾曲線的控制點座標和終點座標
		canvas.drawPath(path2, p);//畫出貝塞爾曲線
		
		//畫點
		p.setStyle(Paint.Style.FILL);
		canvas.drawText("畫點:", 10, 390, p);
		canvas.drawPoint(60, 390, p);//畫一個點
		canvas.drawPoints(new float[]{60,400,65,400,70,400}, p);//畫多個點
		
		//畫圖片,就是貼圖
		Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);
		canvas.drawBitmap(bitmap, 250,360, p);
	}
}
執行一下看效果圖:

技術分享

1、Path物件

在程式碼中我們看到了我們新建了一個Paint畫筆物件,對於畫筆物件,它有很多設定屬性的:

void  setARGB(int a, int r, int g, int b)  設定Paint物件顏色,引數一為alpha透明通道

void  setAlpha(int a)  設定alpha不透明度,範圍為0~255

void  setAntiAlias(boolean aa)  //是否抗鋸齒,預設值是false

void  setColor(int color)  //設定顏色,這裡Android內部定義的有Color類包含了一些常見顏色定義

void  setFakeBoldText(boolean fakeBoldText)  //設定偽粗體文字

void  setLinearText(boolean linearText)  //設定線性文字

PathEffect  setPathEffect(PathEffect effect)  //設定路徑效果

Rasterizer  setRasterizer(Rasterizer rasterizer) //設定光柵化

Shader  setShader(Shader shader)  //設定陰影 ,我們在後面會詳細說一下Shader物件的

void  setTextAlign(Paint.Align align)  //設定文字對齊

void  setTextScaleX(float scaleX)  //設定文字縮放倍數,1.0f為原始

void  setTextSize(float textSize)  //設定字型大小

Typeface  setTypeface(Typeface typeface)  //設定字型,Typeface包含了字型的型別,粗細,還有傾斜、顏色等

注:

Paint mp = new paint();
mp.setTypeface(Typeface.DEFAULT_BOLD)

常用的字型型別名稱還有:
Typeface.DEFAULT //常規字型型別
Typeface.DEFAULT_BOLD //黑體字型型別
Typeface.MONOSPACE //等寬字型型別
Typeface.SANS_SERIF //sans serif字型型別
Typeface.SERIF //serif字型型別

除了字型型別設定之外,還可以為字型型別設定字型風格,如設定粗體:
Paint mp = new Paint();
Typeface font = Typeface.create(Typeface.SANS_SERIF, Typeface.BOLD);
p.setTypeface( font );

常用的字型風格名稱還有:
Typeface.BOLD //粗體
Typeface.BOLD_ITALIC //粗斜體
Typeface.ITALIC //斜體
Typeface.NORMAL //常規

void  setUnderlineText(boolean underlineText)  //設定下劃線

void  setStyle(Style style) //設定畫筆樣式

注:

常用的樣式

Paint.Style.FILL
Paint.Style.STROKE
Paint.Style.FILL_AND_STROKE

這裡的FILL和STROKE兩種方式用的最多,他們的區別也很好理解的,FILL就是填充的意思,STROKE就是空心的意思,只有圖形的輪廓形狀,內部是空的。

void setStrokeWidth(float width) //在畫筆的樣式為STROKE的時候,圖形的輪廓寬度

2、Canvas物件

對於畫布物件Canvas我們是從onDraw方法中獲取到的,所以這裡我們就可以看不來了,我們在自定義檢視的時候都會繼承View類,然後在他的onDraw方法中拿到Canvas物件,進行各種繪製了。下面就來一一看一下各種繪製的方法吧:

首先來看一下如何建立一個畫筆物件:

Paint p = new Paint();
p.setColor(Color.RED);// 設定紅色
我們可以設定畫筆的顏色,當然還有其他的方法,我們可以設定畫筆的粗細,是否有鋸齒等,後面會說道。

1)、畫圓(drawCircle)

我們想一下,如果畫出一個圓形的話需要哪些要素,學過幾何的同學都知道:圓形座標+半徑 就可以確定一個圓形了

canvas.drawCircle(120, 20, 20, p);
引數一:圓心的x座標

引數二:圓心的y座標

引數三:圓的半徑

引數四:畫筆物件

還有一個這裡我們設定了畫筆是否有鋸齒:

p.setAntiAlias(true);// 設定畫筆的鋸齒效果。 true是去除,大家一看效果就明白了
關於這個鋸齒,其實很好理解,就是如果沒有鋸齒效果,那麼畫出來的圓形就很光滑,有鋸齒看上去的圓形很粗糙的。但是預設情況下,畫筆是有鋸齒的。之所以這樣,是因為在沒有鋸齒效果的情況下,繪製圖形效率會比有鋸齒效果低,所以系統考慮了效率問題,就把預設值設定成有鋸齒了,我們在實際繪圖過程中需要衡量一下的。

2)、畫直線(drawLine)

我們想一下,如果畫出一個直線的話需要哪些要素,起始點座標+終點座標 就可以確定一條直線了

canvas.drawLine(60, 40, 100, 40, p);// 畫線
引數一:起始點的x座標

引數二:起始點的y座標

引數三:終點的x座標

引數四:終點的y座標

引數五:畫筆物件

3)、畫橢圓(drawOval)

我們想一下,如果畫出橢圓的話需要哪些要素,長軸+短軸的長度

RectF oval1=new RectF(150,20,180,40);
canvas.drawOval(oval2, p);

引數一:橢圓的外接矩形

引數二:畫筆物件

這裡先來說一下RectF的相關知識吧:在繪圖中這個物件是十分重要的,它表示的是一個矩形,它有四個引數:

left,top,right,bottom

這四個值是相對於裝置螢幕的起始點開始的。

<span style="padding: 0px; font-size: 14px;">RectF oval1=new RectF(150,20,180,40);</span>
比如上面的這個矩形,說白了就是這樣:

技術分享
矩形的左上角的座標是:(150,20)

矩形的右下角的座標是:(180,30)

那麼我們就知道這個矩形的寬是:180-150=30;高是:40-20=20

其實還有與RectF物件對應的還有一個物件:Rect,它也是四個引數,和RectF唯一的區別就是,Rect中的引數是float型別的,RectF中的引數是int型別的

那麼一個矩形就可以確定一個橢圓的,這個矩形就是和這個橢圓外接:

技術分享

那麼橢圓的長軸就是矩形的寬,短軸就是矩形的高

這樣就可以確定一個橢圓了,那麼如果我們想畫一個圓形的話用這種方式也是可以的,只要把RectF設定成正方形就可以了。

4)、畫弧線/畫扇形(drawArc)

我們想一下,如果畫出一個弧線的話需要哪些要素,起始的弧度+弧線的弧度+外圍的矩形大小

這個和上面畫橢圓很相似的,就相當於在他的基礎上多了其實弧度+弧線的弧度

p.setStyle(Paint.Style.STROKE);//設定空心
RectF oval1=new RectF(150,20,180,40);
canvas.drawArc(oval1, 180, 180, false, p);//小弧形

引數一:外接弧形的矩形

引數二:弧線開始的弧度

引數三:弧線的弧度

引數四:是一個boolean型別的引數:true的時候畫扇形,是false的時候畫弧線

引數五:畫筆物件

5)、畫矩形(drawRect)

RectF oval1=new RectF(150,20,180,40);
canvas.drawRect(oval1, p);
引數一:矩形物件

引數二:畫筆物件

6)、畫圓角矩形(drawRoundRect)

RectF oval3 = new RectF(80, 260, 200, 300);// 設定個新的長方形
canvas.drawRoundRect(oval3, 20, 15, p);//第二個引數是x半徑,第三個引數是y半徑
引數一:矩形大小

引數二:圓角的x半徑(橢圓的長軸的一半)

引數三:圓角的y半徑(橢圓的短軸的一半)

引數四:畫筆物件

技術分享
其實這個和正常的矩形不一樣的是:在四個角是有弧度的,那麼弧度的話,就會想到橢圓了,我們在上面說道橢圓的幾個要素:長軸和短軸,那麼這裡就是取長軸的一半和短軸的一半。

7)、畫三角形/多邊形(drawPath)

我們想一下,如果繪製三角形/多邊形的話需要哪些要素,能確定多邊形的形狀最重要的因素就是角,那麼這些角就是一個座標

Path path = new Path();
path.moveTo(80, 200);// 此點為多邊形的起點
path.lineTo(120, 250);
path.lineTo(80, 250);
path.close(); // 使這些點構成封閉的多邊形
canvas.drawPath(path, p);
這裡需要介紹一下Path物件了,這個物件見名知意,是路徑的意思,它有兩個引數:

引數一:x座標

引數二:y座標

路徑是多個點相連線的。所以Path提供了兩個方法:moveTo和lineTo

moveTo方法的作用是設定我們繪製路徑的開始點,如果沒有這個方法的呼叫的話,系統預設的開始點是(0,0)點

lineTo方法就是將路徑的上一個座標點和當前座標點進行連線,或者可以認為設定多邊形的每個角的座標點

那麼對於三角形的話,我們需要三個點即可。

這個畫三角形其實我們用上面的畫直線的方法也可以實現的,反過來也是,我們用Path物件也是可以畫出一條直線的,那麼他們的本質區別是:

繪製路徑方式的焦點是角(座標點)

繪製直線的方式的焦點是邊(長度)

8)、畫點(drawPoint)

canvas.drawPoint(60, 390, p);//畫一個點
canvas.drawPoints(new float[]{60,400,65,400,70,400}, p);//畫多個點
這裡有兩個方法:

drawPoint

引數一:點的x座標

引數二:點的y座標

引數三:畫筆物件

drawPoints

引數一:多個點的陣列

引數二:畫筆物件

9)、畫貝塞爾曲線(drawPath)

這種曲線其實我們在開發過程中很少用到,不過在圖形學中繪製貝塞爾曲線的時候,我們需要的要素是:起始點+控制點+終點

Path path2=new Path();
path2.moveTo(100, 320);//設定Path的起點
path2.quadTo(150, 310, 170, 400); //設定貝塞爾曲線的控制點座標和終點座標
canvas.drawPath(path2, p);//畫出貝塞爾曲線
它也是使用Path物件的。不過用的是quadTo方法

引數一:控制點的x座標

引數二:控制點的y座標

引數三:終點的x座標

引數四:終點的y座標

這裡需要注意的是,呼叫moveTo方法來確定開始座標的,如果沒有呼叫這個方法,那麼起始點座標預設是:(0,0)

10)、繪製圖片(drawBitmap)

//畫圖片,就是貼圖
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);
canvas.drawBitmap(bitmap, 250,360, p);
引數一:圖片物件Bitmap

引數二:圖片相對於裝置螢幕的left值

引數二:圖片相對於裝置螢幕的top值

其實我們可以把圖片認為是一個矩形,因為圖片本身是有長度和寬度的,所以這裡只需要矩形的左上角的座標點,就可以確定這張圖片在螢幕中的位置了。

上面就介紹完了Path物件和Canvas物件,他們兩個物件是我們自定義檢視的基礎,所以這部分內容一定要掌握,當然這兩個物件沒什麼難度的,只要對幾何圖形有點了解的同學,這些東東是很簡單的。

二、顏色渲染器Shader物件

下面再來看下一個知識點:顏色渲染Shader物件

為什麼我要把Shader物件單獨拿出來說一下呢?因為這個物件在對於我們處理圖形特效的時候是非常有用的

下面來看一下Android中Shader物件

在Android Api中關於顏色渲染的幾個重要的類:
Shader,BitmapShader,ComposeShader,LinearGradient,RadialGradient,SweepGradient
它們之間的關係是:

Shader是後面幾個類的父類


該類作為基類主要是返回繪製時顏色的橫向跨度。其子類可以作用與Piant。通過 paint.setShader(Shader shader);來實現一些渲染效果。之作用與圖形不作用與bitmap。
構造方法為預設的構造方法。  

列舉: 
emun Shader.TileMode 

定義了平鋪的3種模式: 
static final Shader.TileMode CLAMP: 邊緣拉伸.
static final Shader.TileMode MIRROR:在水平方向和垂直方向交替景象, 兩個相鄰影象間沒有縫隙.
Static final Shader.TillMode REPETA:在水平方向和垂直方向重複擺放,兩個相鄰影象間有縫隙縫隙.

 
方法: 
1. boolean getLoaclMatrix(Matrix localM); 如果shader有一個非本地的矩陣將返回true.
localM:如果不為null將被設定為shader的本地矩陣.
2. void setLocalMatrix(Matrix localM); 
設定shader的本地矩陣,如果localM為空將重置shader的本地矩陣。  


Shader的直接子類:
BitmapShader    : 點陣圖影象渲染
LinearGradient  : 線性渲染
RadialGradient  : 環形渲染
SweepGradient   : 掃描漸變渲染/梯度渲染
ComposeShader   : 組合渲染,可以和其他幾個子類組合起來使用

是不是很像Animation及其子類的關係(AlphaAnimation,RotateAnimation,ScaleAnimation,TranslateAnimation, AnimationSet)
既有具體的渲染效果,也有渲染效果的組合

下面說下Shader的使用步驟:
1. 構建Shader物件
2. 通過Paint的setShader方法設定渲染物件
3.設定渲染物件
4.繪製時使用這個Paint物件

那麼下面就開始來介紹各個Shader的相關知識:

1、BitmapShader

public   BitmapShader(Bitmap bitmap,Shader.TileMode tileX,Shader.TileMode tileY)
呼叫這個方法來產生一個畫有一個位圖的渲染器(Shader)。
bitmap   在渲染器內使用的點陣圖
tileX      The tiling mode for x to draw the bitmap in.   在點陣圖上X方向渲染器平鋪模式
tileY     The tiling mode for y to draw the bitmap in.    在點陣圖上Y方向渲染器平鋪模式
TileMode:
CLAMP  :如果渲染器超出原始邊界範圍,會複製範圍內邊緣染色。
REPEAT :橫向和縱向的重複渲染器圖片,平鋪。
MIRROR :橫向和縱向的重複渲染器圖片,這個和REPEAT重複方式不一樣,他是以映象方式平鋪。

程式碼:

package com.tony.shader;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Shader;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.ShapeDrawable;
import android.graphics.drawable.shapes.OvalShape;
import android.util.AttributeSet;
import android.view.View;

public class BitmapShaderView extends View {

	private BitmapShader bitmapShader = null;
	private Bitmap bitmap = null;
	private Paint paint = null;
	private ShapeDrawable shapeDrawable = null;
	private int BitmapWidth = 0;
	private int BitmapHeight = 0;

	public BitmapShaderView(Context context) {
		super(context);

		// 得到影象
		bitmap = ((BitmapDrawable) getResources().getDrawable(R.drawable.cat))
				.getBitmap();
		BitmapWidth = bitmap.getWidth();
		BitmapHeight = bitmap.getHeight();
		// 構造渲染器BitmapShader
		bitmapShader = new BitmapShader(bitmap, Shader.TileMode.MIRROR,Shader.TileMode.REPEAT);
	}
	
	public BitmapShaderView(Context context,AttributeSet set) {
		super(context, set);
	}
	
	
	@Override
	protected void onDraw(Canvas canvas) {
        // TODO Auto-generated method stub
	super.onDraw(canvas);
	//將圖片裁剪為橢圓形    
        //構建ShapeDrawable物件並定義形狀為橢圓    
        shapeDrawable = new ShapeDrawable(new OvalShape());  
        //得到畫筆並設定渲染器  
        shapeDrawable.getPaint().setShader(bitmapShader);  
        //設定顯示區域  
        shapeDrawable.setBounds(20, 20,BitmapWidth-140,BitmapHeight);  
        //繪製shapeDrawable  
        shapeDrawable.draw(canvas);  
	}

}
效果圖:

技術分享

2、LinearGradient

相信很多人都看過歌詞同步的效果, 一是豎直方向的滾動,另一方面是水平方面的歌詞顏色漸變點亮效果,這種效果怎麼做呢? 這就需要用到LinearGradient線性渲染,下面還是先看具體的使用:

LinearGradient有兩個建構函式;
public LinearGradient(float x0, float y0, float x1, float y1, int[] colors, float[] positions,Shader.TileMode tile) 
引數:
float x0: 漸變起始點x座標
float y0:漸變起始點y座標
float x1:漸變結束點x座標
float y1:漸變結束點y座標
int[] colors:顏色 的int 陣列
float[] positions: 相對位置的顏色陣列,可為null,  若為null,可為null,顏色沿漸變線均勻分佈
Shader.TileMode tile: 渲染器平鋪模式

public LinearGradient(float x0, float y0, float x1, float y1, int color0, int color1,Shader.TileMode tile)
float x0: 漸變起始點x座標
float y0:漸變起始點y座標
float x1:漸變結束點x座標
float y1:漸變結束點y座標
int color0: 起始漸變色
int color1: 結束漸變色
Shader.TileMode tile: 渲染器平鋪模式

程式碼:

package com.tony.shader;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.graphics.Shader;
import android.view.View;

public class LinearGradientView extends View {

	private LinearGradient linearGradient = null;  
    private Paint paint = null;  
	
    public LinearGradientView(Context context)  
    {  
        super(context);  
        linearGradient = new LinearGradient(0, 0, 100, 100, new int[] {  
                Color.YELLOW, Color.GREEN, Color.TRANSPARENT, Color.WHITE }, null,  
                Shader.TileMode.REPEAT);  
        paint = new Paint();  
    }  
    
	public LinearGradientView(Context context, AttributeSet attrs) {
		super(context, attrs);
	}
	
	@Override
	protected void onDraw(Canvas canvas) {
		// TODO Auto-generated method stub
		super.onDraw(canvas);
		//設定渲染器
		paint.setShader(linearGradient);  
                //繪製圓環
		canvas.drawCircle(240, 360, 200, paint); 
	}

}
效果:

技術分享

關於這個渲染物件,我們需要多解釋一下了,因為這個渲染器用的地方很多:

我們在具體看一下他的構造方法中的引數含義:

Paint paint2 = new Paint();
paint2.setColor(Color.BLACK);
paint2.setStrokeWidth(5);
paint2.setStyle(Paint.Style.FILL);
Shader mShader = new LinearGradient(0,0,100,100,
		Color.RED,
		Color.BLUE, Shader.TileMode.CLAMP);
paint2.setShader(mShader);
Rect rect = new Rect();
rect.left = 0;
rect.right = 300;
rect.top = 0;
rect.bottom = 300;
canvas.drawRect(rect, paint2);
效果圖:

技術分享
我們把構造方法中的值改變一下:

Shader mShader = new LinearGradient(0,0,300,300,
		Color.RED,
		Color.BLUE, Shader.TileMode.CLAMP);
在看一下效果:

技術分享
這裡我們就是到了構造方法中的四個引數值的含義了:

引數一:渲染開始點的x座標

引數二:渲染開始點的y座標

引數三:渲染結束點的x座標

引數四:渲染結束點的y座標

因為這裡我們設定矩形的大小是高和寬都是300

所以,從第一個例子中我們可以看出:渲染結束點之後的顏色是最後一種顏色:藍色

我們在將程式碼改變一下:

Shader mShader = new LinearGradient(0,0,300,0,
		Color.RED,
		Color.BLUE, Shader.TileMode.CLAMP);
效果:

技術分享
結束點的座標設定成:(300,0)就實現了橫向渲染

當然我們也可以實現縱向渲染的,這裡就不演示了。

在修改一下程式碼:

Shader mShader = new LinearGradient(0,0,100,100,
                Color.RED,
                Color.BLUE, Shader.TileMode.MIRROR);
效果:

技術分享
我們將渲染模式改成:Shader.TileMode.MIRROR 映象模式了

我們看到效果,當渲染結束點是(100,100)的時候,那麼後面還是會繼續渲染的,而且是相反的(就像照鏡子一樣),然後在渲染一下,每次渲染的效果都是和之前的相反。因為矩形的長度和寬度都是300,所以這裡會渲染三次。

我們在將程式碼修改一下:

Shader mShader = new LinearGradient(0,0,100,100,
                Color.RED,
                Color.BLUE, Shader.TileMode.REPEAT);
將渲染模式改成:Shader.TileMode.REPEAT 重複模式了

效果:

技術分享
這裡看到也是會渲染三次的,但是和映象模式不同的是,它們的渲染方向都是一致的。

從上面的三種渲染模式可以看出來,之後渲染的結束點小於渲染圖形的大小的時候才會有效果的,如果我們把大小改一下:

Shader mShader = new LinearGradient(0,0,300,300,
                Color.RED,
                Color.BLUE, Shader.TileMode.REPEAT);
我們渲染結束點改成矩形的高度和寬度大小
效果:

技術分享

效果和Shader.TileMode.CLAMP一樣的。

這種渲染器用的地方還是很多的,我們後面介紹長條漸變的SeekBar就要用到這種渲染器

3、RadialGradient

圓形渲染器,這種渲染器很好理解,就是同心圓的渲染機制

public RadialGradient(float x, float y, float radius, int[] colors, float[] positions,Shader.TileMode tile)
float x:  圓心X