当前位置 博文首页 > 启舰:自定义控件三部曲之绘图篇(二十)——RadialGradient与水波
前言:每当感叹自己的失败时,那我就问你,如果让你重新来一次,你会不会成功?如果会,那说明并没有拼尽全力。
系列文章:
Android自定义控件三部曲文章索引:http://blog.csdn.net/harvic880925/article/details/50995268
最近博主实在是太忙了,博客更新实在是太慢了,真是有愧大家。
这篇将是Shader的最后一篇,下部分,我们将讲述Canvas变换的知识。在讲完Canvas变换以后,就正式进入第三部曲啦,是不是有点小激动呢……
今天给大家讲的效果是使用RadialGradient来实现水波纹按钮效果,水波纹效果是Android L平台上自带的效果,这里我们就看看它是如何实现的,本篇的最终效果图如下
###一、RadialGradient详解
RadialGradient的意思是放射渐变,即它会向一个放射源一样,从一个点开始向外从一个颜色渐变成另一种颜色;
RadialGradient有两个构造函数
//两色渐变
RadialGradient(float centerX, float centerY, float radius, int centerColor, int edgeColor, Shader.TileMode tileMode)
//多色渐变
RadialGradient(float centerX, float centerY, float radius, int[] colors, float[] stops, Shader.TileMode tileMode)
(1)、两色渐变构造函数使用实例
下面我们来看一下两色渐变构造函数的使用方法。
RadialGradient(float centerX, float centerY, float radius, int centerColor, int edgeColor, Shader.TileMode tileMode)
这个两色渐变的构造函数的各项参数意义如下:
下面我们举个例子来看下用法:
public class DoubleColorRadialGradientView extends View {
private Paint mPaint;
private RadialGradient mRadialGradient;
private int mRadius = 100;
public DoubleColorRadialGradientView(Context context) {
super(context);
init();
}
public DoubleColorRadialGradientView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public DoubleColorRadialGradientView(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 onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mRadialGradient = new RadialGradient(w/2,h/2,mRadius,0xffff0000,0xff00ff00, Shader.TileMode.REPEAT);
mPaint.setShader(mRadialGradient);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawCircle(getWidth()/2,getHeight()/2,mRadius,mPaint);
}
}
代码量不大,这里首先在onSizeChange中,创建RadialGradient实例。onSizeChange会在布局发生改变时调用,onSizeChanged(int w, int h, int oldw, int oldh)
传过来四个参数,前两个参数就代表当前控件所应显示的宽和高。有关onSizeChange的具体意义,我们会在第三部曲讲解回调函数流程中具体讲到,这里大家就先理解到这吧。
在onSizeChange中,我们创建了一个RadialGradient,以控件的中心点为圆点,创建一个半径为mRadius的,从0xffff0000到0xff00ff00的放射渐变。我们这里指定的空白填充方式为Shader.TileMode.REPEAT。
然后在绘图的时候:
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawCircle(getWidth()/2,getHeight()/2,mRadius,mPaint);
}
在绘图时,依然是以控件中心点为圆心,画一个半径为mRadius的圆;注意我们画的圆的大小与所构造的放射渐变的大小是一样的,所以不存在空白区域的填充问题。
效果图如下:
(2)、多色渐变构造函数使用实例
多色渐变的构造函数如下:
RadialGradient(float centerX, float centerY, float radius, int[] colors, float[] stops, Shader.TileMode tileMode)
这里与两色渐变不同的是两个函数:
下面我们举个例子来看下用法:
public class MultiColorRadialGradientView extends View {
private Paint mPaint;
private RadialGradient mRadialGradient;
private int mRadius = 100;
public MultiColorRadialGradientView(Context context) {
super(context);
init();
}
public MultiColorRadialGradientView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public MultiColorRadialGradientView(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 onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
int[] colors = new int[]{0xffff0000,0xff00ff00,0xff0000ff,0xffffff00};
float[] stops = new float[]{0f,0.2f,0.5f,1f};
mRadialGradient = new RadialGradient(w/2,h/2,mRadius,colors,stops, Shader.TileMode.REPEAT);
mPaint.setShader(mRadialGradient);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawCircle(getWidth()/2,getHeight()/2,mRadius,mPaint);
}
}
这里主要看下多色渐变的构造方法:
int[] colors = new int[]{0xffff0000,0xff00ff00,0xff0000ff,0xffffff00};
float[] stops = new float[]{0f,0.2f,0.5f,1f};
mRadialGradient = new RadialGradient(w/2,h/2,mRadius,colors,stops, Shader.TileMode.REPEAT);
这里构造了一个四色颜色数组,渐变位置对应{0f,0.2f,0.5f,1f},然后创建RadialGradient实例。没什么难度。
然后在绘画的时候,同样以控件中心为半径,以放射渐变的半径为半径画圆。由于画的圆半径与放射渐变的大小相同,所以不存在空白位置填充的问题,所以TileMode.REPEAT并没有用到。
效果图如下:
###二、TileMode重复方式
TileMode的问题,已经重复讲了几篇文章了,其实虽然每种Shader所表现出来的效果不一样,但是形成原理都是相同的。下面我们再来看一下RadialGradient在不同的TileMode下的具体表现。
(1)、X、Y轴共用填充参数
与LinearGradient一样,从构造函数中,可以明显看出RadialGradient只有一个填充模式:
//两色渐变
RadialGradient(float centerX, float centerY, float radius, int centerColor, int edgeColor, Shader.TileMode tileMode)
//多色渐变
RadialGradient(float centerX, float centerY, float radius, int[] colors, float[] stops, Shader.TileMode tileMode)
这就说明了,当填充空白区域时,X轴和Y轴使用同一种填充模式。而不能像BitmapShader那样分别指定X轴与Y轴的填充参数。
(2)、TileMode.CLAMP——边缘填充
我们依然使用双色渐变的示例来看下效果,为了显示填充效果,我们这次画一个屏幕大小的矩形:
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mRadialGradient = new RadialGradient(w/2,h/2