自定义View:自定义CircleImageView实现及图形渲染
来源:互联网 发布:python获取当前日期 编辑:程序博客网 时间:2024/06/11 07:54
在很多应用中头像是以圆形图片展示的,默认图片的话可以让UI切一套圆形的,但是用户设置头像的话不可能也让UI切。其实已经有很多前辈牛人已经写了成熟完善的工具类供程序猿使用。当然实现方式也多种多样。这里道长使用图形渲染实现CircleImageView,然后说一下图形渲染的一些知识。
一、CircleImageView实现
- 构造方法初始化变量
public CircleImageView(Context context, AttributeSet attrs) { super(context, attrs); mMatrix = new Matrix(); mBitmapPaint = new Paint(); mBitmapPaint.setAntiAlias(true); } public CircleImageView(Context context) { this(context, null); }
- 测量并设置控件宽高
@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); mWidth = Math.min(getMeasuredWidth(), getMeasuredHeight()); mRadius = mWidth / 2; setMeasuredDimension(mWidth, mWidth); }
- 给Paint设置渲染规则
private void setPaintShader() { Drawable drawable = getDrawable(); if (drawable == null) { return; } Bitmap bitmap = drawable2Bitmap(drawable); // 创建Bitmap渲染对象 mBitmapShader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); float scale = 1.0f; // 比较bitmap宽和高,获得较小值 int bSize = Math.min(bitmap.getWidth(), bitmap.getHeight()); scale = mWidth * 1.0f / bSize; // shader的变换矩阵,用于放大或者缩小 mMatrix.setScale(scale, scale); // 设置变换矩阵 mBitmapShader.setLocalMatrix(mMatrix); // 设置shader mBitmapPaint.setShader(mBitmapShader); } /** * drawable转bitmap * * @param drawable * @return */ private Bitmap drawable2Bitmap(Drawable drawable) { if (drawable instanceof BitmapDrawable) { BitmapDrawable bd = (BitmapDrawable) drawable; return bd.getBitmap(); } int w = drawable.getIntrinsicWidth(); int h = drawable.getIntrinsicHeight(); Bitmap bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(bitmap); drawable.setBounds(0, 0, w, h); drawable.draw(canvas); return bitmap; }
- 在画布上绘制图片
@Override protected void onDraw(Canvas canvas) { if (getDrawable() == null) { return; } try { setPaintShader(); canvas.drawCircle(mRadius, mRadius, mRadius, mBitmapPaint); } catch (Exception e) { e.printStackTrace(); } }
- 在布局中添加如下代码
<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center"> <ImageView android:id="@+id/iv_default" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="5dp" android:src="@drawable/head" /> <com.yushan.picturerenderdemo.CircleImageView android:layout_width="30dp" android:layout_height="30dp" android:layout_below="@id/iv_default" android:layout_margin="5dp" android:src="@drawable/head" /></RelativeLayout>
- 上面的为原图,下面的为CircleImageView,效果图如下
就这么简单,是不是so easy~当然这个代码中有一个弊端道长没有处理,就是在测量设置控件宽高时道长只是简单的取了一个宽高最小值,然后除以2就设置了。这就导致了CircleImageView最大只能展示原图大小。这个大家可以自行处理。然后我们说一下图形渲染……
二、图形渲染
在实现自定义CircleImageView中道长使用了图形渲染中的图像渲染,而前面道长说过的画布实现自定义View(折线图实现),在绘制限制区域时道长使用的就是图形渲染中的线性渲染。这里道长就不贴代码了,前面有链接童鞋们可以去看一下。图形渲染大概分为五种:
- BitmapShader(图像渲染)
/** * @param bitmap 用来作为纹理填充的位图 * @param tileX 在位图X方向上位图衔接形式 * @param tileY 在位图Y方向上位图衔接形式 */ public BitmapShader(Bitmap bitmap, Shader.TileMode tileX, Shader.TileMode tileY);
Shader.TileMode有3种参数可供选择,分别为CLAMP、REPEAT和MIRROR。
CLAMP - 如果渲染器超出原始边界范围,则会复制边缘颜色对超出范围的区域进行着色。
REPEAT - 在横向和纵向上以平铺的形式重复渲染位图。
MIRROR - 在横向和纵向上以镜像的方式重复渲染位图。
简单使用:
/** * 图像渲染 * * @param canvas * @param paint */ private void drawBitmapShader(Canvas canvas, Paint paint) { // 加载图像资源 Bitmap mBitmap = ((BitmapDrawable) getResources().getDrawable(R.drawable.head)).getBitmap(); // 创建Bitmap渲染对象 Shader mBitmapShader = new BitmapShader(mBitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); // 绘制Bitmap渲染的圆 paint.setShader(mBitmapShader); canvas.drawCircle(100, 100, 100, paint); }
- LinearGradient(线性渲染)
/** * @param x0 渐变的起始点x坐标 * @param y0 渐变的起始点y坐标 * @param x1 渐变的终点x坐标 * @param y1 渐变的终点y坐标 * @param colors 渐变的颜色数组 * @param positions 指定颜色数组的相对位置 * @param tile 平铺方式 */ public LinearGradient (float x0, float y0, float x1, float y1, int[] colors, float[] positions, Shader.TileMode tile);
注意:参数positions设为null,表示颜色数组以斜坡线的形式均匀分布。
简单使用:
/** * 线性渲染 * * @param canvas * @param paint */ private void drawLinearGradient(Canvas canvas, Paint paint) { // 创建线性渲染对象 int mColorLinear[] = {Color.WHITE, Color.YELLOW, Color.GREEN, Color.BLUE}; Shader mLinearGradient = new LinearGradient(150, 150, 100, 100, mColorLinear, null, Shader.TileMode.REPEAT); // 绘制线性渐变的矩形 paint.setShader(mLinearGradient); canvas.drawRect(100, 300, 400, 500, paint); }
- ComposeShader(混合渲染)
/** * @param shaderA 一种渲染效果 * @param shaderB 一种渲染效果 * @param mode 两种渲染效果的叠加模式 */ public ComposeShader (Shader shaderA, Shader shaderB, PorterDuff.Mode mode);
PorterDuff.Mode有16种参数可供选择,分别为:CLEAR、SRC、DST、SRC_OVER、DST_OVER、SRC_IN、DST_IN、SRC_OUT、DST_OUT、SRC_ATOP、DST_ATOP、XOR、DARKEN、LIGHTEN、MULTIPLY、SCREEN。
叠加模式的具体叠加效果如下图所示:
简单使用:
/** * 混合渲染 * * @param canvas * @param paint */ private void drawComposeShader(Canvas canvas, Paint paint) { // 创建线性渲染对象 int mColorLinear[] = {Color.WHITE, Color.YELLOW, Color.GREEN, Color.BLUE}; Shader mLinearGradient = new LinearGradient(150, 150, 100, 100, mColorLinear, null, Shader.TileMode.REPEAT); // 创建环形渲染对象 int mColorRadial[] = {Color.GREEN, Color.RED, Color.BLUE, Color.WHITE}; Shader mRadialGradient = new RadialGradient(300, 300, 75, mColorRadial, null, Shader.TileMode.REPEAT); //创建混合渲染对象 Shader mComposeShader = new ComposeShader(mLinearGradient, mRadialGradient, PorterDuff.Mode.DARKEN); //绘制混合渐变(线性与环形混合)的矩形 paint.setShader(mComposeShader); canvas.drawRect(10, 420, 250, 570, paint); }
- RadialGradient(环形渲染)
/** * @param x 圆心x坐标 * @param y 圆心y坐标 * @param radius 半径 * @param colors 渐变的颜色数组 * @param positions 颜色数组的相对位置 * @param tile 平铺的方式 */ public RadialGradient (float x, float y, float radius, int[] colors, float[] positions, Shader.TileMode tile);
简单使用:
/** * 环形渲染 * * @param canvas * @param paint */ private void drawRadialGradient(Canvas canvas, Paint paint) { // 创建环形渲染对象 int mColorRadial[] = {Color.WHITE, Color.YELLOW, Color.GREEN, Color.BLUE}; Shader mRadialGradient = new RadialGradient(500, 500, 100, mColorRadial, null, Shader.TileMode.REPEAT); // 绘制环形渐变的圆 paint.setShader(mRadialGradient); canvas.drawCircle(500, 500, 100, paint); }
- SweepGradient(梯度渲染)
/** * @param cx 扫描的中心x坐标 * @param cy 扫描的中心y坐标 * @param colors 渐变的颜色数组 * @param positions 颜色数组的相对位置 */ public SweepGradient (float cx, float cy, int[] colors, float[] positions);
简单使用:
/** * 梯度渲染 * * @param canvas * @param paint */ private void drawSweepGradient(Canvas canvas, Paint paint) { // 创建梯形渲染对象 int mColorSweep[] = {Color.GREEN, Color.RED, Color.BLUE, Color.YELLOW, Color.GREEN}; Shader mSweepGradient = new SweepGradient(650, 700, mColorSweep, null); // 绘制梯形渐变的矩形 paint.setShader(mSweepGradient); canvas.drawRect(600, 600, 700, 800, paint); }
到了这里关于自定义CircleImageView的实现以及图形渲染已经说完了,其实道长说自定义CircleImageView是一个引子,重点是说一下图形渲染,这个图形渲染在自定义View中还是比较常用的。好了,希望这篇博客能够为你提供一些帮助。
- 自定义View:自定义CircleImageView实现及图形渲染
- 自定义View之CircleImageView
- 自定义View实现渲染
- Android使用BitmapShader图形渲染实现圆形、圆角和椭圆自定义图片View
- 通过分析CircleImageView掌握自定义View流程
- android 自定义view实现图形移动
- 自定义view--绘制图形
- 自定义Behavior实现CircleImageView跟随AppBarLayout缩放
- 0917Android基础自定义View(颜色渲染PorterDuff及Xfermode)
- Android 中CircleImageView自定义View(圆形头像)
- 自定义圆形图片CircleImageView
- 自定义CircleImageView(一)
- 自定义圆形头像CircleImageView
- 自定义CircleImageView圆形头像
- CircleImageView 自定义圆形ImageView
- 使用自定义图形的 view
- 自定义View绘制各种图形
- 自定义view图形的步骤
- LUA中的一些API
- SSH小结
- 最全Java笔试题
- Spring面向切面编程(AOP)
- 类的启动过程
- 自定义View:自定义CircleImageView实现及图形渲染
- js函数作用域及this指向
- mysqli使用预处理技术进行数据库查询的方法
- ZooKeeper 入门
- 做一个简单的太阳系(二)
- Maven介绍,包括作用、核心概念、用法、常用命令、扩展及配置
- 山东省第八届ACM省赛 K 题 CF (排序01背包)
- "<<"运算符的重载
- Maven