阴影和渐变

阴影

  可以为文字和图形指定阴影。在绘图中,有一个叫做layer(层)的概念。默认情况下,我们的文字和图形绘制在主层(main layer)上,其实也可以将内容绘制在新建的layer上。实际上阴影就是在main layer的下面添加了一个阴影层(shader layer),可以为阴影指定模糊度、偏移量和阴影颜色。

  Paint类定义了一个名为setShadowLayer()的方法,如下:

//radius:阴影半径;
//dx:x方向阴影的偏移量;
//dy:y方向阴影的偏移量;
//shadowColor:阴影的颜色;
public void setShadowLayer(float radius, float dx, float dy, int shadowColor)

  阴影layer显示阴影时,shader layer有两种类型:View.LAYER_TYPE_SOFTWARE和View.LAYER_TYPE_HARDWARE,layer的默认类型为LAYER_TYPE_HARDWARE,但阴影只能在View.LAYER_TYPE_SOFTWARE环境下工作,所以,我们需要调用View类的setLayerType()方法为Paint对象指定层的类型,即setLayerType(View.LAYER_TYPE_SOFTWARE,paint)。

Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setTextSize(100);
this.setLayerType(View.LAYER_TYPE_SOFTWARE,paint);
paint.setShadowLayer(10,1,1,Color.RED);
canvas.drawText("Android开发测试",100,100,paint);

  上面代码中,我们使用paint.setShadowLayer(10,1,1,Color.RED)这一句定义了一个模糊半径为10,x方向和y方向偏移量都为1的红色阴影。当偏移量足够小时,效果可以认为是发光效果。当偏移量比较大的时候,就可以看到阴影效果了。

  一旦定义了阴影层,接下来所有的绘制都会带阴影效果了。如果想取消阴影,将setShadowLayer()方法的radius参数设置为0即可。但是先前应用了阴影的效果还在,只是接下来不再受阴影的影响了。

渐变

  渐变是绘图过程中颜色或位图以特定规律进行变化。
  渐变种类有如下:
1 . 线性渐变:LinearGradient;
2 . 径向渐变:RadialGradient;
3 . 扫描渐变:SweepGradient;
4 . 位图渐变:BitmapShader;
5 . 混合渐变:ComposeShader;

  其中,线性渐变、径向渐变、扫描渐变属于颜色渐变,指定2种或2种以上的颜色,根据颜色过渡算法自动计算出中间的过渡颜色,从而形成渐变效果。位图渐变则不再是简单的颜色渐变,而是以图片做为贴片有规律的变化,类似于壁纸平铺。混合渐变则能将多种渐变进行组合,实现更加复杂的渐变效果。

  如果A、B分别代表两种不同的颜色,我们将渐变分为三种,如下:
1 . ABAB型:A、B两种颜色重复变化,通过TileMode类的REPEAT常量来表示;
2 . ABBA型:A、B两种颜色镜像变化,通过TileMode类的MIRROR常量来表示;
3 . AABB型:A、B两种颜色只出现一次,通过TileMode类的CLAMP常量来表示;

  定义渐变时,必须指定一个渐变区域,根据定义的渐变内容和渐变模式填满该区域。每一种渐变被定义为一个类,他们都继承自同一个父类--Shader。绘图时,调用Paint类的setShader()方法指定一种渐变类型,绘制出来的绘图填充区域都将使用指定的渐变颜色或位图进行填充。
  TileMode是Shader类中的内部枚举类,如下:

public static enum TileMode {
    CLAMP,
    MIRROR,
    REPEAT;

    private TileMode() {
    }
}

  讨论渐变时,虽然一般是指填充区域的渐变,但绘图样式为STROKE时,线条同样可以使用渐变效果。

线性渐变

  线性渐变(LinearGradient)根据指定的角度、颜色和模式使用渐变颜色填充绘图区域。我们必须定义两个点(x0,y0)和(x1,y1),渐变的方向与这两个点的连线垂直。

//x0、y0:用于决定线性方向的第一个点的坐标(x0,y0);
//x1、y1:用于决定线性方向的第二个点的坐标(x1,y1);
//color0:第一种颜色;
//color1:第二种颜色;
//tile:渐变模式;
public LinearGradient(float x0, float y0, float x1, float y1,
            @ColorInt int color0, 
            @ColorInt int color1,
            @NonNull TileMode tile)     
Rect rect1 = new Rect(100, 100, 500, 400); 
LinearGradient lg = new LinearGradient(rect1.left, rect1.top, rect1.right, rect1.bottom, Color.RED, Color.BLUE, Shader.TileMode.CLAMP); 
paint.setShader(lg);
canvas.drawRect(rect1, paint);

  如果两种颜色无法满足绘图需求,LinearGradient也支持三种及三种以上颜色的渐变,也就是另一种构造方法,如下:

//x0、y0:起始点的坐标;
//x1、y1:终止点的坐标;
//colors:多种颜色; 
//positions:颜色的位置(比例); 
//TileMode:渐变模式;
public LinearGradient(float x0, float y0, float x1, float y1, 
            @NonNull @ColorInt int colors[],
            @Nullable float positions[], 
            @NonNull TileMode tile)  

  参数colors和positions都是数组,前者用于指定多种颜色,后者用于指定每种颜色的起始比例位置。positions数组中的元素个数要与colors数组中的个数相同,且是0至1的数值,[0,1]是临界区,如果小于0则当0处理,如果大于1则当1处理。

径向渐变

  径向渐变是以指定的点为中心,向四周以渐变颜色进行圆周扩散,和线性渐变一样,支持两种或多种颜色。
  径向渐变的两种构造方法如下:

//该构造方法支持两种颜色;
//x、y:中心点坐标;
//radius:渐变半径;
//color0:起始颜色;
//color1:结束颜色; 
//TileMode:渐变模式;
public RadialGradient(float centerX, float centerY, float radius,
            @ColorInt int centerColor, 
            @ColorInt int edgeColor, 
            @NonNull TileMode tileMode)
    
//该构造方法支持三种及三种以上颜色的渐变;    
//x、y:中心点坐标;
//radius:渐变半径;
//colors:多种颜色;
//positions:颜色的位置(比例); 
//TileMode:渐变模式;  
public RadialGradient(float centerX, float centerY, float radius,
            @NonNull @ColorInt int colors[], 
            @Nullable float stops[],
            @NonNull TileMode tileMode)
Rect rect = new Rect(100, 100, 500, 500); 
RadialGradient rg = new RadialGradient(300, 300, 200, Color.RED, Color.GREEN, Shader.TileMode.MIRROR); 
Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);
p.setShader(rg);
canvas.drawRect(rect, p);

扫描渐变

  SweepGradient类似于雷达扫描效果,固定圆心,将半径假想为有形并旋转一周而绘制的渐变颜色。SweepGradient的两个构造方法,如下:

//该方法支持两种颜色的扫描渐变;
//cx、cy:圆点坐标; 
//color0:起始颜色; 
//color1:结束颜色;
public SweepGradient(float cx, float cy, @ColorInt int color0, @ColorInt int color1)

//支持多种颜色的扫 渐变;
//cx、cy:圆点坐标;
//colors:多种颜色;
//positions:颜色的位置(比例);
public SweepGradient(float cx, float cy,@NonNull @ColorInt int colors[], @Nullable float positions[])
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); 
SweepGradient sg = new SweepGradient(300, 300, Color.GREEN, Color.YELLOW); 
paint.setShader(sg);
canvas.drawRect(new Rect(0, 0, 600, 600), paint);

位图渐变

  位图渐变其实就是在绘制的图形中将指定的位图做为背景,如果图形比位图小,则通过渐变模式进行屏幕,TileMode.CLAMP模式不平铺,TileMode.REPEAT模式表示平铺,TileMode.MIRROR模式也表示平铺,但是交错的位图是彼此的镜像,方向相反。可以同时指定水平和垂直两个方向的渐变模式。
  BitmapShader只有一个构造方法,如下:

//bitmap:位图;
//tileX:x 方向的重复模式;
//tileY:y 方向的重复模式;
public BitmapShader(@NonNull Bitmap bitmap, @NonNull TileMode tileX, @NonNull TileMode tileY)
Bitmap bmp = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher); 
BitmapShader bs = new BitmapShader(bmp,Shader.TileMode.REPEAT, Shader.TileMode.MIRROR); 
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); 
paint.setShader(bs);
canvas.drawRect(new Rect(0, 0,getMeasuredWidth(), getMeasuredHeight()), paint);

混合渐变

  混合渐变ComposeShader是将两种不同的渐变通过位图运算后得到的一种更加复杂的渐变。位图运算有16种方法。
  ComposeShader有两个构造方法,如下:

public ComposeShader(@NonNull Shader shaderA, @NonNull Shader shaderB, @NonNull PorterDuff.Mode mode)
       
public ComposeShader(@NonNull Shader shaderA, @NonNull Shader shaderB, @NonNull Xfermode mode)     

  shaderA和shaderB是两个渐变对象,mode为位图运算类型。

渐变与Matrix

  渐变类都继承自同一个类--Shader,该类并不复杂,不过定义了一个方法:setLocalMatrix(Matrix matrix),该方法能和渐变结合,在填充渐变颜色的时候实现移位、旋转、缩放和拉斜的效果。

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-----------------------last line for now----------------------