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

Android ImageView绘制圆角效果

程序员文章站 2024-02-24 18:42:04
前言 android 开发中,我们经常需要实现图片的圆形/圆角的效果,我们可以使用两种方式来实现这样的效果。一种是使用xfermode,另一种是bitmapshader来...

前言

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种效果显示,如下:

Android  ImageView绘制圆角效果

可以根据不同的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;
  }
}

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