Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> Android開發 >> 關於android開發 >> 轉載:Android繪圖Canvas十八般武器之Shader詳解及實戰篇(下),androidcanvas

轉載:Android繪圖Canvas十八般武器之Shader詳解及實戰篇(下),androidcanvas

編輯:關於android開發

轉載:Android繪圖Canvas十八般武器之Shader詳解及實戰篇(下),androidcanvas


LinearGradient 線性漸變渲染器

LinearGradient中文翻譯過來就是線性漸變的意思。線性漸變通俗來講就是給起點設置一個顏色值如#faf84d,終點設置一個顏色值如#CC423C,然後在一個區域內繪圖,這個圖像的顏色將呈現非常美妙的效果,顏色會從起點顏色到終點顏色過渡。給一張圖,大家直觀感受一下 
這裡寫圖片描述

我們看LinearGradient的API,發現它只有兩個構造方法,非常簡單。

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

//x0 和y0是顏色漸變的起點坐標。
//x1和y1是顏色漸變的終點坐標。
//color0是起點顏色值 
//color0是終點顏色值。
//tile 就是TileMode類型參數,這個我們上一篇已經講過了。

LinearGradient的用法。

//1   創建LinearGradient對象,並設置它的起點坐標,終點坐標,起點顏色值,終點顏色值,然後設置TileMode
mShader = new LinearGradient(0,0,w,0,Color.parseColor("#faf84d"),
                Color.parseColor("#CC423C"), Shader.TileMode.CLAMP);  

//2  將Shader賦值給Paint對象。
mPaint.setShader(mShader);  

//3  繪制圖形
canvas.drawRect(0,0,w,h/2,mPaint);

用法非常簡單。

LinearGradient還有一個構造方法。

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

需要注意的是,這裡有一個int[] colorsfloat[] positions它們代表什麼意思呢? 
實際上LinearGradient除了可以指定起點顏色值和終點顏色值外,還有可以指定許多中間顏色值。就如彩虹一般。而colors[]數組存放的就是這樣的顏色值組合。大家看看代碼和圖片效果就可能直觀感受到。

//漸變的是一個顏色序列(#faf84d,#003449,#808080,#cc423c)
mShader = new LinearGradient(0,0,w,0,new int[]{Color.parseColor("#faf84d"),Color.parseColor("#003449"),
        Color.parseColor("#808080"),
        Color.parseColor("#CC423C")},null,Shader.TileMode.CLAMP);
mPaint.setShader(mShader);
canvas.drawRect(0,0,w,h/2,mPaint);

 

這裡寫圖片描述

顏色很豐富是不是?顏色從一個顏色過渡到另外一個顏色直到過渡到終點顏色。

大家有沒有注意到,我將上面代碼中的float[] positon置為null,而它代表了什麼呢?它其實與colors數組對應,代表了各個顏色值在位置,positions數組中的值大小范圍從0.0到1.0,0.0代表起點位置,1.0代表終點位置。如果這個數組被置為空的話,顏色就會平均分配。 ,如果這個數組不為空呢?我們結合代碼效果來講解。

mShader = new LinearGradient(0,0,w,0,new int[]{Color.parseColor("#faf84d"),Color.parseColor("#003449"),
        Color.parseColor("#808080"),
        Color.parseColor("#CC423C")},new float[]{0.0f,0.6f,0.8f,1.0f},Shader.TileMode.CLAMP);
mPaint.setShader(mShader);
canvas.drawRect(0,0,w,h/2,mPaint);

這裡寫圖片描述

代碼中colors[]並沒有改變,只是多了positon[],效果卻不一樣了。

new int[]{Color.parseColor("#faf84d"),Color.parseColor("#003449"),
        Color.parseColor("#808080"),
        Color.parseColor("#CC423C")}

new float[]{0.0f,0.6f,0.8f,1.0f}

// #faf84d對應的position值是0.0  所以為起點位置。
// #003449對應0.6    所以這個顏色位置起點到終點中間0.6比率的地方。
// #808080對應0.8    這個顏色在0.8比率的地方
// #cc423c對應1.0    這個顏色為終點處的顏色

需要注意的是,position[]數組中的數組最好是由小到大,這是為什麼呢?它不支持0.8 然後再到0.6之類。大家看代碼。

mShader = new LinearGradient(0,0,w,0,new int[]{Color.parseColor("#faf84d"),Color.parseColor("#003449"),
        Color.parseColor("#808080"),
        Color.parseColor("#CC423C")},new float[]{0.6f,0.8f,0.2f,0.0f},Shader.TileMode.CLAMP);

 

這裡寫圖片描述

可以看到顏色可以從0.6的位置過渡到0.8,後面的就不起作用了。

RadialGradient 環行渲染器

我喜歡稱它為徑向漸變,因為PHOTOSHOP中就對應有徑向漸變的概念。 
徑向漸變,所謂徑向就是輻射狀,由中心向四周輻射。 
徑向漸變也只有兩個構造方法,基本用法跟線性漸變差不多。

RadialGradient (float centerX, 
                float centerY, 
                float radius, 
                int centerColor, 
                int edgeColor, 
                Shader.TileMode tileMode)

//centerX  圓心的X坐標
//centerY  圓心的Y坐標
//radius   圓的半徑
//centerColor  中心顏色
//edgeColor   邊緣顏色
//tileMode   這個不用介紹了吧?

上代碼。

mShader = new RadialGradient(w/2,h/2,w/2,Color.parseColor("#faf84d"),
                Color.parseColor("#CC423C"), Shader.TileMode.CLAMP);
mPaint.setShader(mShader);
canvas.drawRect(0,0,w,h,mPaint);

效果: 
這裡寫圖片描述

RadialGradient (float centerX, 
                float centerY, 
                float radius, 
                int[] colors, 
                float[] stops, 
                Shader.TileMode tileMode)

同LinearGradient一樣,這裡也有一個顏色數組和位置數組,意義也是一樣的,stop[]也可以為null,如果為null的話,color[]數組的顏色就會平均分配在區域之中。否則,它對應的顏色就會按照比例填充。

mShader = new RadialGradient(w/2,h/2,w/2,new int[]{Color.parseColor("#00aa00"),Color.parseColor("#880033"),
        Color.parseColor("#F8795A"),
        Color.parseColor("#CC423C")},new float[]{0.0f,0.2f,0.8f,1.0f}, Shader.TileMode.CLAMP);
mPaint.setShader(mShader);
canvas.drawRect(0,0,w,h,mPaint);

 

這裡寫圖片描述

SweepGradient 梯度漸變渲染器

梯度漸變,或者叫做掃描漸變。我覺得掃描更適合吧,它是指從x軸出發,以逆時鐘為方向,以掃描360度形成的區域進行顏色的變換。

SweepGradient (float cx, 
                float cy, 
                int color0, 
                int color1)
//color0是起始顏色
//color1是終止顏色

代碼示例:

mShader = new SweepGradient(w/2,h/2,Color.RED,Color.BLUE);
mPaint.setShader(mShader);
canvas.drawRect(0,0,w,h,mPaint);

效果: 
這裡寫圖片描述

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

 

大家應該也明白這個方法中每個參數的含義。

mShader = new SweepGradient(w/2,h/2,new int[]{Color.RED,Color.CYAN,Color.YELLOW,
                Color.GREEN,Color.MAGENTA,Color.BLUE},new float[]{0.0f,0.2f,0.3f,0.4f,0.8f,1.0f});
mPaint.setShader(mShader);
canvas.drawRect(0,0,w,h,mPaint);

我們把顏色豐富點,本來想弄成赤橙黃綠青藍紫,結果因為懶,就隨便弄了點,效果如下:

這裡寫圖片描述

ComposeShader 組合渲染器

混合渲染,在這裡我又開始稱Shader為渲染了,因為ComposeShader不僅僅用於顏色,它能將兩個Shader對象參考Xfermode規則進行顏色混合。

網上的一張圖: 
這裡寫圖片描述

這張圖詳細的解釋了混合模式的組合效果,我機會我也寫一篇相關博文。 
再看ComposeShader的兩個構造方法。

ComposeShader (Shader shaderA, 
                Shader shaderB, 
                Xfermode mode)


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

接下來,我們寫代碼驗證一下。

實戰1

public class CircleView extends View {
    private Paint mPaint;
    private Shader mShader;

    public CircleView(Context context) {
        this(context,null);
    }

    public CircleView(Context context, AttributeSet attrs) {
        this(context, attrs,0);
    }

    public CircleView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        mPaint = new Paint();
        mPaint.setAntiAlias(true);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        //這裡為了方便演示,將尺寸固定為400*400
        setMeasuredDimension(400,400);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        int w = getWidth();
        int h = getHeight();
        int radius = w <= h ? w/2 : h/2;


        Bitmap bmp = BitmapFactory.decodeResource(getResources(),R.drawable.repeat);
        Bitmap result = Bitmap.createScaledBitmap(bmp,w,h,false);
        //1. 編寫1個BitmapShader.
        BitmapShader bitmapShader = new BitmapShader(result, Shader.TileMode.REPEAT, Shader.TileMode.REPEAT);

        //2. 編寫1個RadiasGradient。
        RadialGradient radialGradient = new RadialGradient(radius,radius,radius,Color.BLACK,Color.TRANSPARENT, Shader.TileMode.CLAMP);
        //3. 將它們進行混合產生新的Shader.
        ComposeShader composeShader = new ComposeShader(bitmapShader,radialGradient,new PorterDuffXfermode(PorterDuff.Mode.DST_IN));

        mPaint.setShader(composeShader);
        //4. 以新的Shader繪制一個圓。
        canvas.drawCircle(w/2,h/2,radius,mPaint);

    }
}

我們來看看混合後的效果是怎麼樣的。

這裡寫圖片描述

哇,好夢幻的狗狗。

實戰2 倒影功能

以前剛開始學Android的時候,項目裡面要用到倒影,當時的自己是寫不出來的,好在網上有現成的代碼可以copy。現在我們可以運用ComposeShader來實現這麼一個View。

需求分析

好了為了節省篇幅,我只粘貼onDraw()中的代碼。

protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //定義各種寬高
        int bmpWidth = 200;
        int bmpHeight = 200;
        int gap = 5;
        int reflectionHeight = bmpHeight / 4;

        //繪制原圖
        Bitmap bmp = BitmapFactory.decodeResource(getResources(),R.drawable.repeat);
        Bitmap result = Bitmap.createScaledBitmap(bmp,bmpWidth,bmpHeight,false);
        canvas.drawBitmap(result,0,0,null);

        canvas.save();
        //向下移動准備在原圖下方繪制倒影
        canvas.translate(0,bmpHeight+gap);
        Matrix m = new Matrix();
        m.postScale(-1f,1f);
        m.postRotate(-180);
        //將原圖水平翻轉
        Bitmap texture = Bitmap.createBitmap(result,0,0,result.getWidth(),result.getHeight(),m,false);
        //創建BitmapShader和LinearShader。
        BitmapShader bitmapShader = new BitmapShader(texture, Shader.TileMode.REPEAT, Shader.TileMode.REPEAT);
        LinearGradient linearGradient = new LinearGradient(0,0,0,reflectionHeight,Color.BLACK,Color.TRANSPARENT, Shader.TileMode.CLAMP);
        ComposeShader composeShader = new ComposeShader(bitmapShader,linearGradient,new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
        mPaint.setShader(composeShader);
        //以混合模式繪制矩形區域,可以獲得倒影效果。
        canvas.drawRect(0,0,bmpWidth,reflectionHeight,mPaint);

        canvas.restore();

}

效果: 
這裡寫圖片描述

倒影出來了。

Android繪圖Canvas十八般武器之Shader詳解及實戰篇(上)

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved