自定义圆形头像CircleImageView
2016-05-16 15:24
615 查看
圆形头像很常用功能,于是想自己写个自定义的圆形的view。搜索了一下,android中可以通过BitmapShader实现这个效果。
BitmapShader是Shader的子类,可以通过Paint.setShader(Shader shader)进行设置、
这里我们只关注BitmapShader,构造方法:
bitmapShader = new BitmapShader(bitmap, TileMode.CLAMP, TileMode.CLAMP);
参数1:bitmap
参数2,参数3:TileMode;
TileMode的取值有三种:
CLAMP 拉伸
REPEAT 重复
MIRROR 镜像
如果大家给电脑屏幕设置屏保的时候,如果图片太小,可以选择重复、拉伸、镜像;
重复:就是横向、纵向不断重复这个bitmap
镜像:横向不断翻转重复,纵向不断翻转重复;
拉伸:这个和电脑屏保的模式应该有些不同,这个拉伸的是图片最后的那一个像素;横向的最后一个横行像素,不断的重复,纵项的那一列像素,不断的重复;
首先现在values下新建attrs.xml,自定义属性。
CircleImageView.java
首先获取自定义属性的值,然后在onMeasure方法里获得控件宽高,initView方法里设置画笔的参数,创建BitmapShader并给paint设置shader。最后在onDraw方法里绘制就可以了。具体使用:
记得使用自定义view的自定义属性需要在布局文件中引入
参考资料:Android自定义属性时TypedArray的使用方法
Android学习笔记进阶15之Shader渲染
Android学习笔记进阶16之BitmapShader
详解Paint的各种set方法
BitmapShader是Shader的子类,可以通过Paint.setShader(Shader shader)进行设置、
这里我们只关注BitmapShader,构造方法:
bitmapShader = new BitmapShader(bitmap, TileMode.CLAMP, TileMode.CLAMP);
参数1:bitmap
参数2,参数3:TileMode;
TileMode的取值有三种:
CLAMP 拉伸
REPEAT 重复
MIRROR 镜像
如果大家给电脑屏幕设置屏保的时候,如果图片太小,可以选择重复、拉伸、镜像;
重复:就是横向、纵向不断重复这个bitmap
镜像:横向不断翻转重复,纵向不断翻转重复;
拉伸:这个和电脑屏保的模式应该有些不同,这个拉伸的是图片最后的那一个像素;横向的最后一个横行像素,不断的重复,纵项的那一列像素,不断的重复;
首先现在values下新建attrs.xml,自定义属性。
<?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="CircleImageView"> <attr name="mborder_color" format="color"></attr> <attr name="mborder_width" format="dimension"></attr> <attr name="msrc" format="reference"></attr> </declare-styleable> </resources>
CircleImageView.java
package com.sy.callme.view; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Bitmap; import android.graphics.BitmapShader; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Shader; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.util.AttributeSet; import android.view.View; import com.sy.callme.R; /** * Created by SY on 2016/5/16. */ public class CircleImageView extends View { private Bitmap bitmap; private int borderWidth; private Drawable drawable; private int borderColor; private int width; private int height; private Bitmap src; private BitmapShader shader; private Paint paint; private int radius; private int circleX; private int circleY; private Paint borderPaint; public CircleImageView(Context context) { super(context); } public CircleImageView(Context context, AttributeSet attrs) { super(context, attrs); //获取自定义属性 TypedArray type = context.obtainStyledAttributes(attrs, R.styleable.CircleImageView); borderColor = type.getColor(R.styleable.CircleImageView_mborder_color, 0); borderWidth = type.getDimensionPixelSize(R.styleable.CircleImageView_mborder_width, 2); drawable = type.getDrawable(R.styleable.CircleImageView_msrc); //转换为bitmap BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable; bitmap = bitmapDrawable.getBitmap(); } private int measureHeight(int heightMeasureSpec) { int size = MeasureSpec.getSize(heightMeasureSpec); int sizeMode = MeasureSpec.getMode(heightMeasureSpec); int result = 0; if (sizeMode == MeasureSpec.EXACTLY) { //如果是精确尺寸就直接返回结果 result = size; } else { //不是就尺寸设置最大为200 result = 200; if (sizeMode == MeasureSpec.AT_MOST) { //如果是最大尺寸就返回实际尺寸和最大尺寸之中较小的 result = Math.min(result, size); } } return result; } private int measureWidth(int widthMeasureSpec) { int size = MeasureSpec.getSize(widthMeasureSpec); int sizeMode = MeasureSpec.getMode(widthMeasureSpec); int result = 0; if (sizeMode == MeasureSpec.EXACTLY) { //如果是精确尺寸就直接返回结果 result = size; } else { //如果是精确尺寸就直接返回结果 result = 200; if (sizeMode == MeasureSpec.AT_MOST) { //如果是最大尺寸就返回实际尺寸和最大尺寸之中较小的 result = Math.min(result, size); } } return result; } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); width = measureWidth(widthMeasureSpec); height = measureHeight(heightMeasureSpec); width = height = Math.min(width, height); initView();//初始化画笔参数 setMeasuredDimension(width, height); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); canvas.drawCircle(circleX, circleY, radius, paint); canvas.drawCircle(circleX, circleY, radius, borderPaint); } private void initView() { src = Bitmap.createScaledBitmap(bitmap, width, height, true); shader = new BitmapShader(src, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); paint = new Paint(); paint.setShader(shader);//设置shader radius = (width - borderWidth * 2) / 2; circleX = (width) / 2; circleY = (height) / 2; borderPaint = new Paint(); borderPaint.setStyle(Paint.Style.STROKE); borderPaint.setStrokeWidth(borderWidth); borderPaint.setColor(borderColor); borderPaint.setStrokeJoin(Paint.Join.ROUND);//接合处的圆滑 borderPaint.setStrokeCap(Paint.Cap.ROUND);//圆角的笔触 } public void setImageResoure(Drawable drawable) { //转换为bitmap BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable; bitmap = bitmapDrawable.getBitmap(); shader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); paint = new Paint(); paint.setShader(shader); requestLayout(); invalidate(); } }
首先获取自定义属性的值,然后在onMeasure方法里获得控件宽高,initView方法里设置画笔的参数,创建BitmapShader并给paint设置shader。最后在onDraw方法里绘制就可以了。具体使用:
<com.sy.callme.view.CircleImageView android:id="@+id/c_image" android:layout_width="80dp" android:layout_height="80dp" android:layout_marginTop="20dp" android:layout_gravity="center_horizontal" app:mborder_color="#ff7700" app:mborder_width="3dp" app:msrc="@mipmap/touxiang" />
记得使用自定义view的自定义属性需要在布局文件中引入
xmlns:app="http://schemas.android.com/apk/res-auto"
参考资料:Android自定义属性时TypedArray的使用方法
Android学习笔记进阶15之Shader渲染
Android学习笔记进阶16之BitmapShader
详解Paint的各种set方法
相关文章推荐
- 设计模式——单例模式
- RDD之flatMap与Map对比
- 使用pscp在Linux和Windows上传输数据可能存在的问题
- loadrunner 监控linux
- OC语言笔记(四):OC点语法、继承、类别
- [IOS笔记] - addChildViewController
- nodejs实践-代码组织
- JAVA中线程的状态
- CGI getenv 参数
- [Javascript] Grouping and Nesting Console Log Output
- XMPP协议实现原理介绍
- php pdo oracle中文乱码的快速解决方法
- log4j日志技术的使用
- frame加载完成之后执行操作
- windows + nginx + php + mysql +phpStorm +xdebug +chrome xdebug helper
- 解决viewpager嵌套viewpager,子viewpager无法滑动的问题
- POJ 1258
- 实现页面登录后仍然跳回当前页面
- android使用FastJson
- 由三目运算符(? : ;)与++混用导致的陷阱而引申出++,-- 运算符使用说明