大有可为的着色器:Shader

QuibblerQuibbler 2020-10-16 约 18 分钟 1781 次阅读

大有可为的着色器:Shader

平时开发的时候或多或少都接触过相关的技术,但是却没有系统详细的学习一下。Android设计到的知识点很多,特点广泛而杂。有网络相关的,硬件相关的,图形图像相关的等等,每一点都得或多或少需要学习掌握一些。

1、Shader

Shader直译过来就叫“着色器”,该类是抽象的基础类,Shader共有五个子类:BitmapShader、LinearGradient、RadialGradient、SweepGradient、ComposeShader,分别代表不同类型的着色器,具体功能后面再仔细看。

1.1、关联Paint

用来设置给Paint画笔,使用Shader setShader(Shader shader)方法。

mPaint.setShader(shader);

给Paint设置好着色器之后,使用该画笔绘制的对象都将从着色器获取颜色。

1.2、填充模式

着色器也是有范围的,设置了一定的区域范围,Paint从这些范围内可以拿到颜色,但是Paint绘制的图像可能比这大,那么就需要一个策略:如何确定着色器“管辖”区域外的颜色呢?

就有了如下三种填充模式:TileMode.CLAMP、TileMode.REPEAT、TileMode.MIRROR。

public enum TileMode {
        /**
         * 如果着色器超出其原始边界,则复制边缘颜色
         */
        CLAMP   (0),
        /**
         * 水平和垂直重复着色器的图像
         */
        REPEAT  (1),
        /**
         * 水平和垂直重复着色器的图像,交替生成镜像,以便相邻的图像始终缝合
         */
        MIRROR  (2);
    }

2、BitmapShader

BitmapShader类似于Photoshop中的印章工具,Paint绘制的区域使用Bitmap中的图像来着色。

2.1、构造BitmapShader

BitmapShader的构造函数如下,需要指定Bitmap图像,以及X、Y轴的填充模式。

/**
     * Call this to create a new shader that will draw with a bitmap.
     *
     * @param bitmap The bitmap to use inside the shader
     * @param tileX The tiling mode for x to draw the bitmap in.
     * @param tileY The tiling mode for y to draw the bitmap in.
     */
    public BitmapShader(Bitmap bitmap,TileMode tileX,TileMode tileY) {
        this(bitmap, tileX.nativeInt, tileY.nativeInt);
    }

2.2、示例

构造好BitmapShader,并设置给Paint画笔,绘制一个矩形区域。看看不同的填充模式,效果如何?

①TileMode.CLAMP:使用着色器边缘填充其它区域

②TileMode.REPEAT:绘制的区域, 超过了着色器颜色范围,那么就用重复策略

③TileMode.MIRROR:不断的通过镜像填充

3、LinearGradient

LinearGradient线性渐变着色器,实现颜色的线性渐变效果。在自定义Drawable背景的时候有接触过,使用<gradient/>标签添加渐变效果,详见ShapeDrawable:Android自定义背景。

3.1、构造线性着色器

有如下5中线性着色器构造方法。前四个参数是指定区域,指定开始颜色和结束时的颜色,最后一个参数TileMode是填充模式。关于Color颜色,详见《Color详解》。

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

线性变换中可以指定多个颜色值[],已经对应的位置[]。

LinearGradient(float x0, float y0, float x1, float y1,int[] colors,float[] positions,TileMode tile)
    LinearGradient(float x0, float y0, float x1, float y1,long[] colors,float[] positions,TileMode tile)
    LinearGradient(float x0, float y0, float x1, float y1,long[] colors,float[] positions,TileMode tile,ColorSpace colorSpace)

3.2、示例

构造一个线性颜色着色器设置给Paint画笔,再使用该画笔绘制文字及其它图形。

mPaint.setShader(new LinearGradient(0, 0,200, 200, 0xff225a1f, 0xffd71345, Shader.TileMode.MIRROR));
    canvas.drawText(text, 0, 200, mPaint);

再结合动画ValueAnimator就可以实现文字的色彩变换。关于属性动画详见《属性动画:ValueAnimator及其监听器》。

//获取要绘制文字的长度
    length = mPaint.measureText(text);
    //创建属性动画
    ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, length * 2);
    valueAnimator.setDuration(3000);
    valueAnimator.setRepeatMode(ValueAnimator.RESTART);
    valueAnimator.setRepeatCount(ValueAnimator.INFINITE);
    valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            start = (float) animation.getAnimatedValue();
            postInvalidate();
        }
    });
    valueAnimator.start();

4、RadialGradient

RadialGradient放射渐变着色器

4.1、构造放射渐变着色器

有如下5中构造方法,就不在一一详细介绍。需要指定中心坐标以及渐变半径radius。

RadialGradient(float centerX, float centerY, float radius,int[] colors,float[] stops,TileMode tileMode)
    RadialGradient(float centerX, float centerY, float radius,long[] colors,float[] stops,TileMode tileMode)
    RadialGradient(float centerX, float centerY, float radius,long[] colors,float[] stops,TileMode tileMode, ColorSpace colorSpace)
    RadialGradient(float centerX, float centerY, float radius,int centerColor,int edgeColor,TileMode tileMode)
    RadialGradient(float centerX, float centerY, float radius,long centerColor,long edgeColor,TileMode tileMode)

4.2、示例

使用该着色器结合动画可以实现各种效果。

//给画笔设置着色器
    mPaint.setShader(new RadialGradient(600, 600, radial + 1, 0xff225a1f, 0xffd71345, Shader.TileMode.CLAMP));
    //使用该画笔绘制圆形,结合动画会呈现各种效果
    canvas.drawCircle(600, 600, 200, mPaint);

5、SweepGradient

SweepGradient扫描渐变着色器。

5.1、构造扫描渐变着色器

如下几种构造函数。注意只有一个坐标点,意味着只需要指定中心区域,扫描范围是无限的。

SweepGradient(float cx, float cy,int[] colors,float[] positions)
    SweepGradient(float cx, float cy,long[] colors,float[] positions)
    SweepGradient(float cx, float cy,long[] colors,float[] positions, ColorSpace colorSpace)
    SweepGradient(float cx, float cy,int color0,int color1)
    SweepGradient(float cx, float cy,long color0,long color1)

5.2、示例

简单的渐变图如下,如何实现雷达扫描图的动画效果呢?可以发挥想象力。

mPaint.setShader(new SweepGradient(600, 600, 0xff225a1f, 0xffd71345));
    canvas.drawCircle(600, 600, 200, mPaint);

            

6、ComposeShader

ComposeShader组合着色器,将其它着色器组合成为一个混合着色器。

6.1、组合着色器

有两种构造方法

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

6.2、混合模式*

组合两个不同的着色器有如下两种模式:PorterDuff.Mode和BlendMode 。简单了解一下即可,也不需要记住,会用比会背更重要!

①PorterDuff.Mode

public enum Mode {
        // these value must match their native equivalents. See SkXfermode.h
        CLEAR       (0),
        SRC         (1),
        DST         (2),
        SRC_OVER    (3),
        DST_OVER    (4),
        SRC_IN      (5),
        DST_IN      (6),
        SRC_OUT     (7),
        DST_OUT     (8),
        SRC_ATOP    (9),
        DST_ATOP    (10),
        XOR         (11),
        DARKEN      (16),
        LIGHTEN     (17),
        MULTIPLY    (13),
        SCREEN      (14),
        ADD         (12),
        OVERLAY     (15);
    }

②BlendMode 

public enum BlendMode {
        CLEAR(0),
        SRC(1),
        DST(2),
        SRC_OVER(3),
        DST_OVER(4),
        SRC_IN(5),
        DST_IN(6),
        SRC_OUT(7),
        DST_OUT(8),
        SRC_ATOP(9),
        DST_ATOP(10),
        XOR(11),
        PLUS(12),
        MODULATE(13),
        SCREEN(14),
        OVERLAY(15),
        DARKEN(16),
        LIGHTEN(17),
        COLOR_DODGE(18),
        COLOR_BURN(19),
        HARD_LIGHT(20),
        SOFT_LIGHT(21),
        DIFFERENCE(22),
        EXCLUSION(23),
        MULTIPLY(24),
        HUE(25),
        SATURATION(26),
        COLOR(27),
        LUMINOSITY(28);
    }

相关资料:

         Reference > Shader">Android Developers > Reference > Shader

         Reference > BitmapShader">Android Developers > Reference > BitmapShader

         Reference > LinearGradient">Android Developers > Reference > LinearGradient

         Reference > RadialGradient">Android Developers > Reference > RadialGradient

         Reference > SweepGradient">Android Developers > Reference > SweepGradient

        Reference > ComposeShader">Android Developers > Reference > ComposeShader

        自定义View之Paint - ComposeShader

        Android SweepGradient类介绍


相关推荐

精选
ViewPager和PagerAdapter、FragmentPagerAdapter、FragmentStatePager
Android

ViewPager和PagerAdapter、FragmentPagerAdapter、FragmentStatePager

ViewPager1、ViewPagerandroidx.viewpager.widget.ViewPager,Android中使用非常广泛的控件,可以说是APP必备:首次打开引导页、页面Banner广告等。常用方法:setAdapter() 设置适配器setOffscreenPageLimit() 设置缓存的页面个数,默认是 1setCurrentItem() 跳转到特定的页面setOnPage

1.1k
获取Android内置WebView内核版本
Android

获取Android内置WebView内核版本

获取Android内置WebView内核版本竟然能遇到这样奇葩的事情,网页用的技术过于新颖,以至于只支持高版本Chromium内核的,低版本安卓系统中内置的内核版本较低,无法加载前端页面。1、设置查看在系统设置里 > 应用 > 应用管理 > 显示系统应用,查看WebView组件:2、页面查看通过WebView发起的网络请求,都会带上浏览器的UA,通常页面都可以通过UA判断浏览器的内核版本。这里有两

1.1w
Android 14适配总结
Android

Android 14适配总结

Android 14适配总结毕业工作至今已经适配了三个Android大版本,从Android 11到Android 12、再到Android 13。2023年,Google即将推出的Android 14,上半年已经开始第一批适配。现在,第四个Android版本已经适配完,总结记录一下。1、Android 14计划Google一般会在2月份对外发布预告,同时放出开发者预览版。“拉通”各大平台、厂商以

1.1w