当前位置 博文首页 > 启舰:自定义控件三部曲之绘图篇(十九)——LinearGradient与闪动

    启舰:自定义控件三部曲之绘图篇(十九)——LinearGradient与闪动

    作者:[db:作者] 时间:2021-06-30 15:31

    前言:家和万事兴

    相关文章:
    《Android自定义控件三部曲文章索引》:http://blog.csdn.net/harvic880925/article/details/50995268

    博主这段时间工作实在是太忙了,全天无尿点……博客一直没更新,实在对不住大家……

    这篇就给大家讲setShader的另一个参数,LinearGradient,使用过shape标签的同学,对这个方法估计都不莫生,就是线性渐变。跟PhotoShop中的线性渐变的原理和作用是一样的。这篇文章的最终会实现一个闪动文字效果控件:
    在这里插入图片描述

    ###一、引言
    有关渐变,以前有讲过一篇《详解shape标签》,其中讲述了<gradient/>标签的用法:

    <gradient   
        android:type=["linear" | "radial" | "sweep"]    //共有3中渐变类型,线性渐变(默认)/放射渐变/扫描式渐变    
        android:angle="integer"     //渐变角度,必须为45的倍数,0为从左到右,90为从上到下    
        android:centerX="float"     //渐变中心X的相当位置,范围为0~1    
        android:centerY="float"     //渐变中心Y的相当位置,范围为0~1    
        android:startColor="color"   //渐变开始点的颜色    
        android:centerColor="color"  //渐变中间点的颜色,在开始与结束点之间    
        android:endColor="color"    //渐变结束点的颜色    
        android:gradientRadius="float"  //渐变的半径,只有当渐变类型为radial时才能使用    
        android:useLevel=["true" | "false"] />  //使用LevelListDrawable时就要设置为true。设为false时才有渐变效果    
    

    其中的渐变类型有"linear" | “radial” | “sweep”,在代码中对应的类分别是LinearGradient、RaialGradient、SweepGradient;有关<gradient/>各个渐变效果的用法,不知道的同学强烈建议你先看看这篇文章。
    这篇我们要讲就是线性渐变的LinearGradient;
    ###二、LinearGradient基本使用
    ####1、构造函数
    我们先来看下LinearGradient的构造函数:
    第一个构造函数:

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

    用过PhotoShop的线性激变工具的同学,应该都知道,线性渐变其实是在指定的两个点之间填充渐变颜色。

    • 参数中的(x0,y0)就是起始渐变点坐标,参数中(x1,y1)就是结束渐变点坐标;
    • color0就是起始颜色,color1就是终止颜色;颜色值必须使用0xAARRGGBB形式的16进制表示!表示透明度的AA一定不能少。
    • TileMode tile:与BitmapShader一样,用于指定控件区域大于指定的渐变区域时,空白区域的颜色填充方法。

    很显然!这个方法,只能指定两种颜色之间的渐变。如果需要多种颜色之间的渐变,就需要使用下面的这个构造函数了。

    第二个构造函数:

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

    同样,(x0,y0)就是起始渐变点坐标,参数中(x1,y1)就是结束渐变点坐标
    colors[]用于指定渐变的颜色值数组,同样,颜色值必须使用0xAARRGGBB形式的16进制表示!表示透明度的AA一定不能少。
    positions[]与渐变的颜色相对应,取值是0-1的float类型,表示在每一个颜色在整条渐变线中的百分比位置
    ####2、两色渐变使用示例
    我们先来看看两色渐变的构造函数是如何来使用的:

    public class LinearGradientView extends View {
        private Paint mPaint;
        public LinearGradientView(Context context) {
            super(context);
            init();
        }
    
        public LinearGradientView(Context context, AttributeSet attrs) {
            super(context, attrs);
            init();
        }
    
        public LinearGradientView(Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
            init();
        }
    
        private void init(){
    	    setLayerType(LAYER_TYPE_SOFTWARE,null);
            mPaint = new Paint();
        }
    
        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            mPaint.setShader(new LinearGradient(0,getHeight()/2,getWidth(),getHeight()/2,0xffff0000,0xff00ff00, Shader.TileMode.CLAMP));
            canvas.drawRect(0,0,getWidth(),getHeight(),mPaint);
        }
    }
    

    很简单,只需要在绘图的时候构造LinearGradient实例,通过Paint.setShader设置进去即可。
    大家注意一下,我这里设置的渐变范围是从控件的左边中点到右边中点:

    mPaint.setShader(new LinearGradient(0,getHeight()/2,getWidth(),getHeight()/2,0xffff0000,0xff00ff00, Shader.TileMode.CLAMP));
    

    最后通过canvas.drawRect把整个控件区域画出来:

    canvas.drawRect(0,0,getWidth(),getHeight(),mPaint);
    

    这里大家注意一下,上面我们也已经提到了,颜色值必须使用0xAARRGGBB的完整16进制的颜色样式表示,我们这里的颜色值就是0xffff0000和0xff00ff00;大家自己可以进行尝试,如果把红色的透明度值去掉,改写成0xff00000,是不会有任何显示的。
    效果图如下:
    在这里插入图片描述
    ####3、多色渐变使用示例
    下面我们来看第二个构造函数,多色渐变的使用方法:

    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        int[] colors = {0xffff0000,0xff00ff00,0xff0000ff,0xffffff00,0xff00ffff};
        float[]  pos = {0f,0.2f,0.4f,0.6f,1.0f};
        LinearGradient multiGradient = new LinearGradient(0,getHeight()/2,getWidth(),getHeight()/2,colors,pos, Shader.TileMode.CLAMP);
        mPaint.setShader(multiGradient);
        canvas.drawRect(0,0,getWidth(),getHeight(),mPaint);
    }
    

    从这里可以看出,渐变的开始点同样是控件左边中点,渐变的结束点也同样是控件右边中点;这里我们指定了五种渐变颜色,而且指定了每个颜色的位置,前四种颜色是按20%均匀分布的,最后两种颜色相距40%;最后通过canvas.drawRect把整个控件区域画出来

    效果图如下:
    在这里插入图片描述

    注意:
    colors和pos的个数一定要相等,也就是说必须指定每一个颜色值的位置!如果多或少都会直接报错:(Signal 11是SO内部错误)
    在这里插入图片描述
    ####2、渐变起始坐标与填充的关系——矩形填充
    我们上面的示例中都是从控件左边中间到控件右边中点;如果我们改成从左上角到右上角的填充方式,结果会怎样呢?

    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        int[] colors = {0xffff0000,0xff00ff00,0xff0000ff,0xffffff00,0xff00ffff};
        float[]  pos = {0f,0.2f,0.4f,0.6f,1.0f};
        LinearGradient multiGradient = new LinearGradient(0,0,getWidth(),getHeight(),colors,pos, Shader.TileMode.CLAMP);
        mPaint.setShader(multiGradient);
        canvas.drawRect(0,0,getWidth(),getHeight(),mPaint);
    }        
    

    渐变线是从控件的左上角到控件的右下角位置:

    LinearGradient multiGradient = new LinearGradient(0,0,getWidth(),getHeight(),colors,pos, Shader.TileMode.CLAMP);
    

    效果图如下:
    在这里插入图片描述
    形成原理如下:
    在这里插入图片描述
    就是说,首先是两个渐变点之间连线,然后以连线为对角线形成一个矩形,各种颜色都是以这条对角线为矩形的填充的。
    ####3、TileMode重复方式
    在讲到BitmapShader的时候,我们已经详细讲过TileMode的意义:当控件区域大小渐变区域时,用于填充空白位置的。
    下面我们就逐个看一下TileMode不同时,对于线性渐变的有什么作用。
    (1)、X、Y轴共用填充参数
    首先,我们再回来看一下LinearGradient的构造函数:

    public LinearGradient(float x0, float y0, float x1, float y1,int colors[], float positions[], TileMode tile)
    public LinearGradient(float x0, float y0, float x1, float y1,int color0, int color1, TileMode tile)
    

    从构造函数中可以看出,LiearGradient只有一个TileMode参数,这说明X轴与Y轴共用这一个TileMode填充参数,而不能像BitmapShader那样分别指定X轴与Y轴的填充参数。
    (2)、TileMode.CLAMP

    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
            多色渐变
        int[] colors = {0xffff0000,0xff00ff00,0xff0000ff,0xffffff00,0xff00ffff};
        float[]  pos = {0f,0.2f,0.4f,0.6f,1.0f};
        LinearGradient multiGradient = new LinearGradient(0,0,getWidth()/2,getHeight()/2,colors,pos, Shader.TileMode.CLAMP);
        mPaint.setShader(multiGradient);
        canvas.drawRect(0,0,getWidth(),getHeight(),mPaint);
    }
    

    这里做了一个多色渐变,渐变点是从(0,0)到屏幕的中间点(width/2,height.2);
    效果图如下:
    在这里插入图片描述