Android自定义控件之Shader(着色器/渲染器)
2016-10-08 22:27
162 查看
Android自定义控件之Shader(着色器/渲染器)
在Paint有一个方法mPaint.setShader(Shader shader);
Shader有五个子类:
BitmapShader,
ComposeShader,
LinearGradient,
RadialGradient,
SweepGradient
在这几种子类的构造中可能会用到Shader.TileMode
Shader.TileMode有三种模式:
Shader.TileMode.CLAMP 最后一个像素进行拉伸填充
Shader.TileMode.MIRROR 镜像
Shader.TileMode.REPEAT 重复
1.BitmapShader : 用一张图片进行着色
它只有一个构造方法:/** * @param bitmap 着色中使用的位图 * @param tileX X方向上绘图模式 * @param tileY Y方向上绘图模式 */ BitmapShader (Bitmap bitmap, Shader.TileMode tileX, Shader.TileMode tileY)
学习了这些知识点可以做一个小练习,望远镜效果
public class TelescopeView extends View { //画笔:一个绘制圆的画笔,一个绘制边框的画笔 private Paint mPaint,strokePaint; //圆心 private float posX, posY; //半径 private int radios = 200; //是否显示望远镜头 private boolean isShow; public TelescopeView(Context context) { this(context, null); } public TelescopeView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public TelescopeView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } //初始化 private void init() { //创建望远镜画笔 mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); //设置图片着色器 mPaint.setShader(new BitmapShader(BitmapFactory.decodeResource(getResources(), R.mipmap.one_bg), Shader.TileMode.REPEAT, Shader.TileMode.MIRROR)); //创建边框画笔 strokePaint = new Paint(Paint.ANTI_ALIAS_FLAG); strokePaint.setStyle(Paint.Style.STROKE); strokePaint.setColor(Color.BLACK); strokePaint.setStrokeWidth(10); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); canvas.drawColor(Color.GRAY); if (isShow) { canvas.drawCircle(posX, posY, radios, mPaint); canvas.drawCircle(posX,posY, radios,strokePaint); } } @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()) { c e7cd ase MotionEvent.ACTION_DOWN: isShow = true; posX = event.getX(); posY = event.getY(); postInvalidate(); break; case MotionEvent.ACTION_MOVE: posX = event.getX(); posY = event.getY(); postInvalidate(); break; case MotionEvent.ACTION_UP: isShow = false; postInvalidate(); break; } return true; } }
2.LinearGradient 线性着色器
构造:/** @param x0 开始的X坐标 @param y0 开始的Y坐标 @param x1 结束的X坐标 @param y1 结束的Y坐标 @param color0 起始的颜色 @param color1 结束的颜色 @param tile TileMode模式 */ public LinearGradient(float x0, float y0, float x1, float y1, int color0, int color1, TileMode tile)
/** Create a shader that draws a linear gradient along a line. @param x0 开始的X坐标 @param y0 开始的Y坐标 @param x1 结束的X坐标 @param y1 结束的Y坐标 @param colors 颜色组 @param positions 这个参数可以为null, 如果为null则所有颜色均匀分布, 如果不为空则数组个数必须与颜色的个数相等, 并且元素大小在0-1之间,代表从百分之多少开始对应的颜色 @param tile TileMode模式 */ public LinearGradient(float x0, float y0, float x1, float y1, int colors[], float positions[], TileMode tile)
了解了构造就可以来简单实现以下了
构造 1:
public LinearGradient(float x0, float y0, float x1, float y1, int color0, int color1,TileMode tile)
mPaint.setShader(new LinearGradient(0,0,getWidth(),getHeight(), Color.RED,Color.GREEN, Shader.TileMode.CLAMP));
因为在这行代码中我设置的是自定义控件整个的大小,所以Shader.TileMode改变了并看不出来什么影响。
如果我设置成这样就可以看出效果了
mPaint.setShader(new LinearGradient(0,0,getWidth()/2,getHeight()/2, Color.RED,Color.GREEN, Shader.TileMode.REPEAT));
变成了这个样子,其他效果可以自己来做一做
构造 2:
public LinearGradient(float x0, float y0, float x1, float y1, int colors[], float positions[],TileMode tile)
mPaint.setShader(new LinearGradient(0,0,getWidth(),getHeight(),new int[]{Color.BLUE,Color.CYAN,Color.RED,Color.YELLOW,Color.GREEN},new float[]{0,0.3f,0.7f,0.8f,0.9f}, Shader.TileMode.MIRROR));
效果:
用这个着色器可以做一个小练习,图片的倒影效果,附上自定义控件代码
public class ReflectionsView extends View { //倒影和源图的间距 private static final int JULI = 10; //画笔 private Paint mPaint; //源图和倒影图 private Bitmap srcBit,daoBit; //图片的起始X,Y private int bitX,bitY; //倒影图片的起始和宽高 float startX,startY, daoWid, daoHei; public ReflectionsView(Context context) { this(context,null); } public ReflectionsView(Context context, AttributeSet attrs) { this(context, attrs,0); } public ReflectionsView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(context); } private void init(Context context) { //获取源图 srcBit = BitmapFactory.decodeResource(getResources(), R.mipmap.one_bg); //通过矩阵翻转源图生成倒影 Matrix matrix = new Matrix(); matrix.setScale(1f,-1f); //生成倒影图 daoBit = Bitmap.createBitmap(srcBit,0,srcBit.getHeight()-srcBit.getHeight()/3,srcBit.getWidth(),srcBit.getHeight()/3,matrix,true); //获取屏幕宽高 WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); DisplayMetrics dm = new DisplayMetrics(); wm.getDefaultDisplay().getMetrics(dm); int sWid = dm.widthPixels; int sHei = dm.heightPixels; bitX = sWid/2-srcBit.getWidth()/2; bitY = sHei/2-srcBit.getHeight()/2; startX = bitX+srcBit.getWidth()/2; startY = bitY+ JULI +srcBit.getHeight(); daoWid = startX; daoHei = startY + srcBit.getHeight()/3; //设置线性着色器 LinearGradient linearGradient = new LinearGradient(startX,startY, daoWid, daoHei,0x55000000, Color.TRANSPARENT, Shader.TileMode.CLAMP); //创建画笔 mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); //设置着色器 mPaint.setShader(linearGradient); //设置混合模式Xfermode; mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN)); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); //绘制源图 canvas.drawBitmap(srcBit,bitX,bitY,null); //保存画布,用于处理Xfermode int sl = canvas.saveLayer(bitX,startY,bitX+srcBit.getWidth(), daoHei,null,Canvas.ALL_SAVE_FLAG); //绘制源图 canvas.drawBitmap(daoBit,bitX,bitY+ JULI +srcBit.getHeight(),null); //绘制倒影的矩形 canvas.drawRect(0,0,getWidth(),getHeight(),mPaint); //还原 canvas.restoreToCount(sl); } }
3.SweepGradient 角度渐变着色器
构造:/** * @param cx 该中心的X坐标 * @param cy 该中心的Y坐标 * @param color0 起始颜色 * @param color1 结束颜色 */ public SweepGradient(float cx, float cy, int color0, int color1)
/** * A subclass of Shader that draws a sweep gradient around a center point. * * @param cx 该中心的X坐标 * @param cy 该中心的Y坐标 * @param colors 颜色组 * @param positions 这个参数可以为null, 如果为null则所有颜色均匀分布, 如果不为空则数组个数必须与颜色的个数相等, 并且元素大小在0-1之间,代表从百分之多少开始对应的颜色 */ public SweepGradient(float cx, float cy, int colors[], float positions[])
这个类使用是蛮简单的,类似LinearGradient,就不累赘了
效果是这个样子
4.RadialGradient 径向渐变着色器
构造:/** @param centerX 圆心的X坐标 @param centerY 圆心的Y坐标 @param radius 径向渐变半径 @param centerColor 中心起始颜色 @param edgeColor 结束颜色 @param tileMode TileMode模式 */ public RadialGradient(float centerX, float centerY, float radius, int centerColor, int edgeColor, TileMode tileMode)
/** Create a shader that draws a radial gradient given the center and radius. @param centerX 圆心的X坐标 @param centerY 圆心的Y坐标 @param radius 径向渐变半径 @param colors 颜色组 @param stops 这个参数可以为null, 如果为null则所有颜色均匀分布, 如果不为空则数组个数必须与颜色的个数相等, 并且元素大小在0-1之间,代表从百分之多少开始对应的颜色 @param tileMode TileMode模式 */ public RadialGradient(float centerX, float centerY, float radius, int colors[], float stops[], TileMode tileMode)
例 1:
mPaint.setShader(new RadialGradient(getWidth()/2,getHeight()/2,getWidth(), Color.YELLOW,Color.RED, Shader.TileMode.CLAMP));
效果:
例 2:
mPaint.setShader(new RadialGradient(getWidth()/2,getHeight()/2,getWidth(), new int[]{Color.BLUE,Color.CYAN,Color.RED,Color.YELLOW,Color.GREEN},null, Shader.TileMode.CLAMP));
这个有点吓人了,噗噗噗,将就看吧,嘿嘿
5.ComposeShader 着色器组合
构造:/** @param shaderA 渲染器A,Shader及其子类对象 @param shaderB 渲染器B,Shader及其子类对象 @param mode 两种渲染器组合的模式,ProterDuff.Mode对象 */ public ComposeShader(Shader shaderA, Shader shaderB, PorterDuff.Mode mode)
/** @param shaderA 渲染器A,Shader及其子类对象 @param shaderB 渲染器B,Shader及其子类对象 @param mode 两种渲染器组合的模式,Xfermode对象 */ public ComposeShader(Shader shaderA, Shader shaderB, Xfermode mode)
使用方法也很简单
linearGradient = new LinearGradient(0,0,200,200,new int[]{Color.RED,Color.YELLOW,Color.WHITE,Color.BLACK,Color.CYAN},null, Shader.TileMode.REPEAT); radialGradient = new RadialGradient(getWidth()/2,getHeight()/2,60,new int[]{Color.RED,Color.YELLOW,Color.WHITE,Color.BLACK,Color.CYAN},null, Shader.TileMode.MIRROR); composeShader = new ComposeShader(linearGradient, radialGradient, PorterDuff.Mode.ADD);
效果:
注:混合着色器需要关闭硬件加速,否则无法显示。
setLayerType(LAYER_TYPE_SOFTWARE,null);
本文在之后会更新对应着色器的实例,向望远镜那样的。
我是个走在android“不归路”上的小白~~希望可以和大神们学习到更多东西
最后附上aigestudio大神的非常好的学习系列文章:http://blog.csdn.net/column/details/androidcustomview.html
相关文章推荐
- android自定义控件的创建和使用
- Android 实现自定义控件效果1
- Android中自定义控件
- Android declare-styleable:自定义控件的属性(attr.xml,TypedArray)的使用
- [转]Android.自定义控件的实现
- android中使用自定义控件是报android.view.InflateException: Binary XML 异常
- Android 自定义控件-SnakeLayout (仿gallery)
- android EditText里面嵌入两个按钮,通过按钮可以加减EditText里的数字,组合自定义控件。
- android shader
- Android 实现自定义控件效果2
- Android 自定义控件 eBook 翻书效果
- Android 自定义控件 eBook 翻书效果
- Android 自定义控件的 拖拽、移动 实现 方法
- Android 自定义控件 仿乐Phone UI
- 【转】Android自定义控件中自定义属性的处理方式
- android 自定义控件属性
- Android 自定义控件-SnakeLayout (仿gallery)
- android自定义控件的创建和使用
- android 自定义控件
- Android应用之个人应用软件开发(4)【深度UI设计自定义控件】