Android自定义View实现圆形切图效果
程序员文章站
2022-07-01 16:20:17
使用自定义view实现圆形imageview的效果,具体内容如下
目前圆形边框还需要调整,这里有点问题
实现思路
使用一个paint,将得到的bitmap设置成p...
使用自定义view实现圆形imageview的效果,具体内容如下
目前圆形边框还需要调整,这里有点问题
实现思路
使用一个paint,将得到的bitmap设置成paint的shader,设置完成后,使用matrix调整图片至居中,使用rectf约束边框,最后完成绘制
初始化paint,设置shader
private void init() { getbitmapfromdrawable(); if (mbitmap == null) { return; } mshader = new bitmapshader(mbitmap, shader.tilemode.clamp, shader.tilemode.clamp); // bitmap paint mfillpaint = new paint(); mfillpaint.setantialias(true); mfillpaint.setstyle(paint.style.fill); mfillpaint.setshader(mshader); // border paint mboundpaint = new paint(); mboundpaint.setantialias(true); mboundpaint.setstyle(paint.style.stroke); mboundpaint.setstrokewidth(mborderwidth); mboundpaint.setcolor(mbordercolor); // border rectf mborderbound.set(calculatebitmapbound()); // bitmap rectf mbitmapbound.set(calculatebitmapbound()); mbitmapbound.inset(mborderwidth - 10, mborderwidth - 10); updateshadermatrix(); }
获取drawable
private bitmap getbitmapfromdrawable() { drawable drawable = getdrawable(); if (drawable instanceof bitmapdrawable) { mbitmap = ((bitmapdrawable) drawable).getbitmap(); mbitmapwidth = mbitmap.getwidth(); mbitmapheight = mbitmap.getheight(); return mbitmap; } return null; }
计算边距
/** * 计算bitmap边距 */ private rectf calculatebitmapbound() { int availablewidth = getwidth() - getpaddingleft() - getpaddingright(); int availableheight = getheight() - getpaddingtop() - getpaddingbottom(); int sidelength = math.min(availablewidth, availableheight); // 可用的直径 mradius = sidelength / 2; int left = getpaddingleft() + (availablewidth - sidelength) / 2; int top = getpaddingtop() + (availableheight - sidelength) / 2; log.d(tag, "calculatebitmapbound: left >>> " + left + " top >>> " + top + " right >>> " + (left + sidelength) + " right >>> " + top + " bottom >>> " + (top + sidelength)); return new rectf(left, top, left + sidelength, top + sidelength); }
调整matrix,防止只显示图片边角
/** * 调整图片缩放,目前只支持centercrop */ private void updateshadermatrix() { float scale; float dx = 0; float dy = 0; mshadermatrix.set(null); // 调整缩放,使图片居中 if (mbitmapwidth * mbitmapbound.height() > mbitmapbound.width() * mbitmapheight) { scale = mbitmapbound.height() / (float) mbitmapheight; dx = (mbitmapbound.width() - mbitmapwidth * scale) * 0.5f; } else { scale = mbitmapbound.width() / (float) mbitmapwidth; dy = (mbitmapbound.height() - mbitmapheight * scale) * 0.5f; } log.d(tag, "updateshadermatrix: scale >>> " + scale); mshadermatrix.setscale(scale, scale); // todo: 16-10-15 http://chroya.iteye.com/blog/713869 // 回到中心点,便于下次缩放 mshadermatrix.posttranslate((int) (dx + 0.5f) + mbitmapbound.left, (int) (dy + 0.5f) + mbitmapbound.top); mshader.setlocalmatrix(mshadermatrix); }
ondraw
@override protected void ondraw(canvas canvas) { if (mbitmap == null) { super.ondraw(canvas); } log.d(tag, "ondraw: centerx >>> " + mbitmapbound.centerx() + " centery >>> " + mbitmapbound.centery()); canvas.drawcircle(mbitmapbound.centerx(), mbitmapbound.centery(), mradius, mfillpaint); // 绘制边框 canvas.drawcircle(mborderbound.centerx(), mborderbound.centery(), mradius, mboundpaint); }
完整代码
/** * created by shixi_tianrui1 on 16-10-7. * 显示圆形图片的imageview */ public class circleimageview extends imageview { private static final string tag = "logger"; private bitmapshader mshader; private paint mfillpaint; // 绘图 private paint mboundpaint; // 绘制圆边 private bitmap mbitmap; private drawable mdrawable; private int mbordercolor; // 边框颜色 private float mborderwidth; // 边框宽度 private rectf mborderbound = new rectf(); private rectf mbitmapbound = new rectf(); private matrix mshadermatrix = new matrix(); private int mradius; private int mbitmapwidth; private int mbitmapheight; private static final float default_border_width = 5; public circleimageview(context context) { this(context, null); } public circleimageview(context context, attributeset attrs) { this(context, attrs, 0); } public circleimageview(context context, attributeset attrs, int defstyleattr) { super(context, attrs, defstyleattr); typedarray a = getresources().obtainattributes(attrs, r.styleable.circleimageview); mbordercolor = a.getcolor(r.styleable.circleimageview_bordercolor, color.blue); mborderwidth = a.getdimension(r.styleable.circleimageview_borderwidth, default_border_width); mborderwidth = a.getdimensionpixelsize(r.styleable.circleimageview_borderwidth, 20); a.recycle(); } private void init() { getbitmapfromdrawable(); if (mbitmap == null) { return; } mshader = new bitmapshader(mbitmap, shader.tilemode.clamp, shader.tilemode.clamp); // bitmap paint mfillpaint = new paint(); mfillpaint.setantialias(true); mfillpaint.setstyle(paint.style.fill); mfillpaint.setshader(mshader); // border paint mboundpaint = new paint(); mboundpaint.setantialias(true); mboundpaint.setstyle(paint.style.stroke); mboundpaint.setstrokewidth(mborderwidth); mboundpaint.setcolor(mbordercolor); // border rectf mborderbound.set(calculatebitmapbound()); // bitmap rectf mbitmapbound.set(calculatebitmapbound()); mbitmapbound.inset(mborderwidth - 10, mborderwidth - 10); updateshadermatrix(); } @override protected void onsizechanged(int w, int h, int oldw, int oldh) { super.onsizechanged(w, h, oldw, oldh); init(); } /** * 计算bitmap边距 */ private rectf calculatebitmapbound() { int availablewidth = getwidth() - getpaddingleft() - getpaddingright(); int availableheight = getheight() - getpaddingtop() - getpaddingbottom(); int sidelength = math.min(availablewidth, availableheight); // 可用的直径 mradius = sidelength / 2; int left = getpaddingleft() + (availablewidth - sidelength) / 2; int top = getpaddingtop() + (availableheight - sidelength) / 2; log.d(tag, "calculatebitmapbound: left >>> " + left + " top >>> " + top + " right >>> " + (left + sidelength) + " right >>> " + top + " bottom >>> " + (top + sidelength)); return new rectf(left, top, left + sidelength, top + sidelength); } private bitmap getbitmapfromdrawable() { drawable drawable = getdrawable(); if (drawable instanceof bitmapdrawable) { mbitmap = ((bitmapdrawable) drawable).getbitmap(); mbitmapwidth = mbitmap.getwidth(); mbitmapheight = mbitmap.getheight(); return mbitmap; } return null; } @override protected void ondraw(canvas canvas) { if (mbitmap == null) { super.ondraw(canvas); } log.d(tag, "ondraw: centerx >>> " + mbitmapbound.centerx() + " centery >>> " + mbitmapbound.centery()); canvas.drawcircle(mbitmapbound.centerx(), mbitmapbound.centery(), mradius, mfillpaint); // 绘制边框 canvas.drawcircle(mborderbound.centerx(), mborderbound.centery(), mradius, mboundpaint); } /** * 调整图片缩放,目前只支持centercrop */ private void updateshadermatrix() { float scale; float dx = 0; float dy = 0; mshadermatrix.set(null); // 调整缩放,使图片居中 if (mbitmapwidth * mbitmapbound.height() > mbitmapbound.width() * mbitmapheight) { scale = mbitmapbound.height() / (float) mbitmapheight; dx = (mbitmapbound.width() - mbitmapwidth * scale) * 0.5f; } else { scale = mbitmapbound.width() / (float) mbitmapwidth; dy = (mbitmapbound.height() - mbitmapheight * scale) * 0.5f; } log.d(tag, "updateshadermatrix: scale >>> " + scale); mshadermatrix.setscale(scale, scale); // todo: 16-10-15 http://chroya.iteye.com/blog/713869 // 回到中心点,便于下次缩放 mshadermatrix.posttranslate((int) (dx + 0.5f) + mbitmapbound.left, (int) (dy + 0.5f) + mbitmapbound.top); mshader.setlocalmatrix(mshadermatrix); } }
目前仍有点问题,解决后会及时更新。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
上一篇: 赵明解读荣耀M/N/V/X四大系列:5G V系列首发
下一篇: android仿支付宝密码输入框效果