欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android自定义View实现圆形切图效果

程序员文章站 2022-07-01 16:20:17
使用自定义view实现圆形imageview的效果,具体内容如下 目前圆形边框还需要调整,这里有点问题 实现思路 使用一个paint,将得到的bitmap设置成p...

使用自定义view实现圆形imageview的效果,具体内容如下

Android自定义View实现圆形切图效果

目前圆形边框还需要调整,这里有点问题

实现思路

使用一个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);
 }
}

目前仍有点问题,解决后会及时更新。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。