Android高级渲染Shader(上)——基本用法

在安卓中需要做一些渲染的UI的渐变效果。实现这些效果我们需要了解安卓渐变的使用。因此我们需要了解一个非常重要的类——Shader。

Shader

有五个类继承了Shader:

BitmapShader:位图图像渲染。
LinearGradient:线性渲染。
SweepGradient:渐变渲染/梯度渲染。
RadialGradient:环形渲染。
ComposeShader:组合渲染

1、BitmapShader:位图图像渲染####

BitmapShader只作用于Bitmap,用Bitmap对绘制的图形进行渲染着色。
构造函数中需要传入图片的拉升模式TileMode,同时设置不同TileMode会展示的效果也是BitmapShader的重点!

mBitmapShader = new BitmapShader(mBitmap, Shader.TileMode.MIRROR, Shader.TileMode.MIRROR);

使用时,首先paint.setShader(),然后用canvas.draw();

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        mPaint.setShader(mBitmapShader);
        canvas.drawRect(0, 0, 800, 800, mPaint);
    }

这里将一个张图片去填充边长为800的正方形,长宽采用一样的拉伸模式。
CLAMP—— 是拉伸最后一个像素铺满。

CLAMP

MIRROR——是横向纵向不足处不断翻转镜像平铺。

MIRROR

REPEAT ——类似电脑壁纸,横向纵向不足的重复放置。

REPEAT

2、LinearGradient:线性渲染####

    /** 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, int colors[], float positions[],
            TileMode tile)

构造函数中参数的意思:
x0:渲染起点的X坐标
y0:渲染起点的Y坐标
x1:渲染终点的X坐标
y1:渲染终点的Y坐标
colors:渲染的颜色集合。
positions:渲染颜色所占的比例,如果传null,则均匀渲染.
tile : 拉伸模式,和BitmaopShaper类似。
其他构造函数这里不做讲解,传入的参数含义也比较好理解

mLinearGradient = new LinearGradient(0,500,500,500,new int[]{Color.RED,Color.BLUE,Color.GRAY,Color.GREEN},null, Shader.TileMode.MIRROR);
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        mPaint.setShader(mLinearGradient);
        canvas.drawRect(0, 0, 800, 800, mPaint);
    }

效果图:。


LinearGradient

3、SweepGradient:梯度渲染####

/**
     * A subclass of Shader that draws a sweep gradient around a center point.
     *
     * @param cx       The x-coordinate of the center
     * @param cy       The y-coordinate of the center
     * @param colors   The colors to be distributed between around the center.
     *                 There must be at least 2 colors in the array.
     * @param positions May be NULL. The relative position of
     *                 each corresponding color in the colors array, beginning
     *                 with 0 and ending with 1.0. If the values are not
     *                 monotonic, the drawing may produce unexpected results.
     *                 If positions is NULL, then the colors are automatically
     *                 spaced evenly.
     */
    public SweepGradient(float cx, float cy,
                         int colors[], float positions[]) 

构造函数中参数的意思:
cx:渲染圆形中心点的x坐标。
cy:渲染圆形中心点的y坐标。
colors :渲染的颜色集合。
positions:渲染颜色所占的比例,如果传null,则均匀渲染。
其他构造函数这里不做讲解,传入的参数含义也比较好理解

mSweepGradient = new SweepGradient(250, 250, new int[]{Color.GREEN, Color.YELLOW, Color.RED}, null);

使用时,首先paint.setShader(),然后用canvas.draw();

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        mPaint.setShader(mSweepGradient);
        canvas.drawCircle(250, 250, 250, mPaint);
    }

效果图:

SweepGradient

4、RadialGradient:环形渲染####

/** Create a shader that draws a radial gradient given the center and radius.
        @param centerX  The x-coordinate of the center of the radius
        @param centerY  The y-coordinate of the center of the radius
        @param radius   Must be positive. The radius of the circle for this gradient.
        @param colors   The colors to be distributed between the center and edge of the circle
        @param stops    May be <code>null</code>. Valid values are between <code>0.0f</code> and
                        <code>1.0f</code>. The relative position of each corresponding color in
                        the colors array. If <code>null</code>, colors are distributed evenly
                        between the center and edge of the circle.
        @param tileMode The Shader tiling mode
    */
    public RadialGradient(float centerX, float centerY, float radius,
               @NonNull int colors[], @Nullable float stops[], @NonNull TileMode tileMode)

centerX:渲染圆形中心点的x坐标。
centerY:渲染圆形中心点的y坐标。
radius:渲染圆形的半径。
colors :渲染的颜色集合。
stops:渲染颜色所占的比例,如果传null,则均匀渲染。
tileMode :拉伸模式,和BitmaopShaper类似。
其他构造函数这里不做讲解,传入的参数含义也比较好理解

mRadialGradient = new RadialGradient(250, 250, 250, new int[]{Color.RED, Color.GREEN, Color.BLACK}, null, Shader.TileMode.CLAMP);
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        mPaint.setShader(mRadialGradient);
        canvas.drawCircle(250, 250, 250, mPaint);
    }

效果图:

RadialGradient

5、ComposeShader:组合渲染####

ComposeShader会将两种渲染叠加。为什么是两种呢?因为:

    /** Create a new compose shader, given shaders A, B, and a combining mode.
        When the mode is applied, it will be given the result from shader A as its
        "dst", and the result from shader B as its "src".
        @param shaderA  The colors from this shader are seen as the "dst" by the mode
        @param shaderB  The colors from this shader are seen as the "src" by the mode
        @param mode     The mode that combines the colors from the two shaders. If mode
                        is null, then SRC_OVER is assumed.
    */
    public ComposeShader(Shader shaderA, Shader shaderB, Xfermode mode) {
        mType = TYPE_XFERMODE;
        mShaderA = shaderA;
        mShaderB = shaderB;
        mXferMode = mode;
        init(nativeCreate1(shaderA.getNativeInstance(), shaderB.getNativeInstance(),
                (mode != null) ? mode.native_instance : 0));
    }

    /** Create a new compose shader, given shaders A, B, and a combining PorterDuff mode.
        When the mode is applied, it will be given the result from shader A as its
        "dst", and the result from shader B as its "src".
        @param shaderA  The colors from this shader are seen as the "dst" by the mode
        @param shaderB  The colors from this shader are seen as the "src" by the mode
        @param mode     The PorterDuff mode that combines the colors from the two shaders.
    */
    public ComposeShader(Shader shaderA, Shader shaderB, PorterDuff.Mode mode) {
        mType = TYPE_PORTERDUFFMODE;
        mShaderA = shaderA;
        mShaderB = shaderB;
        mPorterDuffMode = mode;
        init(nativeCreate2(shaderA.getNativeInstance(), shaderB.getNativeInstance(),
                mode.nativeInt));
    }

它的构造函数只能传两种渲染效果。(但是,是否可以在ComposeShader的构造函数中传入ComposeShader达到多种渲染效果叠加?)
构造函数中的第三个参数是设置叠加模式:http://blog.csdn.net/t12x3456/article/details/10432935

public class ComposeShaderTestView extends View {

    private ComposeShader composeShader;

    //位图渲染
    private BitmapShader mBitmapShader;
    private Bitmap mBitmap;

    //线性渲染
    private LinearGradient mLinearGradient;

    private Paint mPaint;

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

    public ComposeShaderTestView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public ComposeShaderTestView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.hy2);
        mBitmapShader = new BitmapShader(mBitmap, Shader.TileMode.REPEAT, Shader.TileMode.REPEAT);

        mLinearGradient = new LinearGradient(0, mBitmap.getHeight(), mBitmap.getWidth(), mBitmap.getHeight(), new int[]{Color.RED, Color.BLUE, Color.GRAY, Color.GREEN}, null, Shader.TileMode.MIRROR);

        //组合渲染
        composeShader = new ComposeShader(mBitmapShader, mLinearGradient, PorterDuff.Mode.MULTIPLY);

        mPaint = new Paint();
        mPaint.setAntiAlias(true);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        mPaint.setShader(composeShader);
        canvas.drawRect(0, 0, mBitmap.getWidth(), mBitmap.getHeight(), mPaint);
    }
}

这里将线性渲染和位图渲染叠加了,效果图:

ComposeShader

如果基本了解了Shader的用法,那就看一下看一下Shader的实例效果:
http://www.jianshu.com/p/3ded93e3b863

代码地址:https://github.com/AxeChen/Gradient

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,736评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,167评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,442评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,902评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,302评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,573评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,847评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,562评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,260评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,531评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,021评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,367评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,016评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,068评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,827评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,610评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,514评论 2 269

推荐阅读更多精彩内容