当前位置: 移动技术网 > 移动技术>移动开发>Android > Android ImageView绘制圆角效果

Android ImageView绘制圆角效果

2019年07月24日  | 移动技术网移动技术  | 我要评论

前言

android 开发中,我们经常需要实现图片的圆形/圆角的效果,我们可以使用两种方式来实现这样的效果。一种是使用xfermode,另一种是bitmapshader来实现。下面我将分别介绍这两种用法。

使用xfermode的方式实现
使用该方式的关键代码,如下:

  private bitmap creatabitmap(bitmap bitmap) {

    //用指定的一个bitmap来构建一个画布
    bitmap target = bitmap.createbitmap(1000,1000, bitmap.config.argb_8888);
    canvas canvas = new canvas(target);
    final paint paint = new paint();
    paint.setcolor(color.green);
    paint.setantialias(true);
    //在刚才的画布上绘制一个圆形区域
    canvas.drawcircle(500,500,500,paint);
    //设置xfermode,使用src_in模式,这样可以取到第二张图片重叠后的区域
    paint.setxfermode(new porterduffxfermode(porterduff.mode.src_in));
    //在画布上绘制第二个需要显示的bitmap
    canvas.drawbitmap(bitmap,0,0,paint);
    return target;
  }

上面代码中看出在指定的画布上绘制了两层图像,一个是半径为500像素的圆形,一个是将目标bitmap绘制在上面。之间还调用了paint.setxfermode(new porterduffxfermode(porterduff.mode.src_in));作用是这两个绘制的效果图叠加后,取得第二个图的交集图。所以,我们先绘制一个圆形,然后绘制bitmap,交集为圆形,取出的就是圆形区域的bitmap了。
porterduff.mode中一共有16种效果显示,如下:

可以根据不同的mode,控制显示的效果图。

开始应用

1.自定义属性在attrs.xml中

<?xml version="1.0" encoding="utf-8"?>
<resources>

  <attr name="borderradius" format="dimension" />
  <attr name="type">
    <enum name="circle" value="0"/>
    <enum name="round" value="1"/>
  </attr>
  <attr name="src" format="reference"/>
  <declare-styleable name="roundimageview">
    <attr name="borderradius"/>
    <attr name="type"/>
    <attr name="src"/>
  </declare-styleable>

</resources>

2.自定义view

public class roundimageview extends view {

  private int type;
  private static final int type_circle = 0;
  private static final int type_round = 1;
  //图片
  private bitmap msrc;
  //圆角大小
  private int mradius;
  //高度
  private int mwidth;
  //宽度
  private int mheight;

  public roundimageview(context context, attributeset attrs) {
    super(context, attrs);
    //获取自定义的属性
    typedarray a = context.obtainstyledattributes(attrs,r.styleable.roundimageview);
    //获取自定以属性的数目
    int count = a.getindexcount();
    for (int i=0 ; i<count ; i++){
      int attr = a.getindex(i);
      switch (attr){
        case r.styleable.roundimageview_borderradius:
          int defvalue = (int) typedvalue.applydimension(typedvalue.complex_unit_dip,10f,getresources().getdisplaymetrics());
          mradius = a.getdimensionpixelsize(attr, defvalue);
          break;
        case r.styleable.roundimageview_type:
          type = a.getint(attr,0);
          break;
        case r.styleable.roundimageview_src:
          msrc = bitmapfactory.decoderesource(getresources(),a.getresourceid(attr,0));
          break;
      }
    }

    a.recycle();
  }

  @override
  protected void onmeasure(int widthmeasurespec, int heightmeasurespec) {
    super.onmeasure(widthmeasurespec, heightmeasurespec);
    //设置宽度
    int specmode = measurespec.getmode(widthmeasurespec);
    int specsize = measurespec.getsize(widthmeasurespec);
    if (specmode == measurespec.exactly){
      mwidth = specsize;
    }else {
      int desirebyimg = getpaddingleft() + getpaddingright() + msrc.getwidth();
      if (specmode == measurespec.at_most)// wrap_content
      {
        mwidth = math.min(desirebyimg, specsize);
      } else
        mwidth = desirebyimg;
    }

    //设置高度
    specmode = measurespec.getmode(heightmeasurespec);
    specsize = measurespec.getsize(heightmeasurespec);
    if (specmode == measurespec.exactly){
      mheight = specsize;
    }else {
      int desire = getpaddingtop() + getpaddingbottom() + msrc.getheight();
      if (specmode == measurespec.at_most)// wrap_content
      {
        mheight = math.min(desire, specsize);
      } else
        mheight = desire;
    }

    setmeasureddimension(mwidth,mheight);
  }

  @override
  protected void ondraw(canvas canvas) {
    super.ondraw(canvas);
    switch (type){
      case type_circle:
        int min = math.min(mwidth,mheight);
        //从当前存在的bitmap,按一定的比例创建一个新的bitmap。
        msrc = bitmap.createscaledbitmap(msrc, min, min, false);
        canvas.drawbitmap(createcircleimage(msrc, min), 0, 0, null);

        break;
      case type_round:
        msrc = bitmap.createscaledbitmap(msrc, mwidth, mheight, false);
        canvas.drawbitmap(createroundconerimage(msrc), 0, 0, null);

        break;
    }
  }

  /**
   * 绘制圆角
   * @param source
   * @return
   */
  private bitmap createroundconerimage(bitmap source) {
    final paint paint = new paint();
    paint.setantialias(true);
    bitmap target = bitmap.createbitmap(mwidth, mheight, bitmap.config.argb_8888);
    canvas canvas = new canvas(target);
    rectf rect = new rectf(0, 0, mwidth, mheight);
    canvas.drawroundrect(rect, mradius, mradius, paint);
    paint.setxfermode(new porterduffxfermode(porterduff.mode.src_in));
    canvas.drawbitmap(source, 0, 0, paint);
    return target;
  }

  /**
   * 绘制圆形
   * @param source
   * @param min
   * @return
   */
  private bitmap createcircleimage(bitmap source, int min) {
    final paint paint = new paint();
    paint.setantialias(true);
    bitmap target = bitmap.createbitmap(min, min, bitmap.config.argb_8888);
    canvas canvas = new canvas(target);
    canvas.drawcircle(min/2,min/2,min/2,paint);
    paint.setxfermode(new porterduffxfermode(porterduff.mode.src_in));
    canvas.drawbitmap(source, 0, 0, paint);
    return target;
  }
}

3.布局文件

<?xml version="1.0" encoding="utf-8"?>
<linearlayout xmlns:android="http://schemas.android.com/apk/res/android"
       xmlns:roundview="http://schemas.android.com/apk/res-auto"
       xmlns:tools="http://schemas.android.com/tools"
       android:id="@+id/activity_main"
       android:layout_width="match_parent"
       android:layout_height="match_parent"
       android:orientation="vertical"
       android:padding="10dp"
       tools:context="mo.yumf.com.myviews.mainactivity">


  <mo.yumf.com.myviews.roundimageview
    android:layout_width="200dp"
    android:layout_height="200dp"
    android:layout_margintop="20dp"
    roundview:borderradius="10dp"
    roundview:src="@drawable/ac_default_icon"
    roundview:type="round"/>

  <mo.yumf.com.myviews.roundimageview
    android:layout_width="200dp"
    android:layout_height="200dp"
    android:layout_margintop="20dp"
    roundview:src="@drawable/ac_default_icon"
    roundview:type="circle"/>
</linearlayout>

上面的自定义view中,存在一个局限,那就是只能在布局中设置要加载的图片资源,不能在代码中设置图片。下面我们使用同样的方式,选择自定义imageview来实现。

public class roundimageview extends imageview {

  private int type;
  private static final int type_circle = 0;
  private static final int type_round = 1;
  //图片
  private bitmap msrc;
  //圆角大小
  private int mradius;

  public roundimageview(context context, attributeset attrs) {
    super(context, attrs);
    //获取自定义的属性
    typedarray a = context.obtainstyledattributes(attrs,r.styleable.roundimageview);
    //获取自定以属性的数目
    int count = a.getindexcount();
    for (int i=0 ; i<count ; i++){
      int attr = a.getindex(i);
      switch (attr){
        case r.styleable.roundimageview_borderradius:
          int defvalue = (int) typedvalue.applydimension(typedvalue.complex_unit_dip,10f,getresources().getdisplaymetrics());
          mradius = a.getdimensionpixelsize(attr, defvalue);
          break;
        case r.styleable.roundimageview_type:
          type = a.getint(attr,0);
          break;
      }
    }

    a.recycle();
  }

  @override
  protected void ondraw(canvas canvas) {
    if (getdrawable() != null){
      bitmap bitmap = getbitmap(getdrawable());
      if (bitmap != null){
        switch (type){
          case type_circle:
            //获取imageview中的宽高,取最小值
            int min = math.min(getmeasuredwidth(),getmeasuredheight());
            //从当前存在的bitmap,按一定的比例创建一个新的bitmap。
            msrc = bitmap.createscaledbitmap(bitmap, min, min, false);
            canvas.drawbitmap(createcircleimage(msrc, min), 0, 0, null);

            break;
          case type_round:
            msrc = bitmap.createscaledbitmap(bitmap, getmeasuredwidth(), getmeasuredheight(), false);
            canvas.drawbitmap(createroundconerimage(msrc), 0, 0, null);

            break;
        }
      }
    }else {

      super.ondraw(canvas);
    }
  }

  private bitmap getbitmap(drawable drawable) {
    if (drawable instanceof bitmapdrawable){
      return ((bitmapdrawable)drawable).getbitmap();
    }else if (drawable instanceof colordrawable){
      rect rect = drawable.getbounds();
      int width = rect.right - rect.left;
      int height = rect.bottom - rect.top;
      int color = ((colordrawable)drawable).getcolor();
      bitmap bitmap = bitmap.createbitmap(width,height, bitmap.config.argb_8888);
      canvas canvas = new canvas(bitmap);
      canvas.drawargb(color.alpha(color),color.red(color), color.green(color), color.blue(color));
      return bitmap;
    }else {
      return null;
    }
  }


  /**
   * 绘制圆角
   * @param source
   * @return
   */
  private bitmap createroundconerimage(bitmap source) {
    final paint paint = new paint();
    paint.setantialias(true);
    bitmap target = bitmap.createbitmap(getmeasuredwidth(), getmeasuredheight(), bitmap.config.argb_8888);
    canvas canvas = new canvas(target);
    rectf rect = new rectf(0, 0, getmeasuredwidth(), getmeasuredheight());
    canvas.drawroundrect(rect, mradius, mradius, paint);
    paint.setxfermode(new porterduffxfermode(porterduff.mode.src_in));
    canvas.drawbitmap(source, 0, 0, paint);
    return target;
  }

  /**
   * 绘制圆形
   * @param source
   * @param min
   * @return
   */
  private bitmap createcircleimage(bitmap source, int min) {
    final paint paint = new paint();
    paint.setantialias(true);
    bitmap target = bitmap.createbitmap(min, min, bitmap.config.argb_8888);
    canvas canvas = new canvas(target);
    canvas.drawcircle(min/2,min/2,min/2,paint);
    paint.setxfermode(new porterduffxfermode(porterduff.mode.src_in));
    canvas.drawbitmap(source, 0, 0, paint);
    return target;
  }
}

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

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网