android绘制圆形图片的两种方式示例

发布时间 - 2026-01-10 22:18:38    点击率:

android绘制圆形图片的两种方式

看下效果先

下面有完整的示例代码

使用BitmapShader(着色器)

我们在绘制view 的时候 就是小学上美术课 用水彩笔在本子上画画 使用着色器绘制圆形图片最简单的理解方式 就是把bitmap当做一种颜色 设置给paint ,paint都已经有颜色了 你想让它方了,圆了,扁了 还不是看你心情 canvas调用那个方法咯

实现的大致思路如下:

1. 创建一个类 继承imageView 重写onDraw()

2. 获取到bitmap图片

3. 计算图片的缩放比例 使用矩阵matrix 进行缩放

4. 创建BitmapShader着色器 设置缩放矩阵

5. paint设置着色器 绘制

具体实现 注释也标注的很清楚

  private void shaderCircle(Canvas canvas){
    //获取Drawable
    Drawable resources=getDrawable();
    float scale = 1.0f;//缩放比例
    int mRadius=0;//圆的半径
    if (resources instanceof BitmapDrawable){
      //获取bitmap
      Bitmap bitmap=((BitmapDrawable) resources).getBitmap();
      if (bitmap==null) return;
      // 获取bitmap宽高中的小值
      int minBitMap = Math.min(bitmap.getWidth(), bitmap.getHeight());
      //取view宽高中的小值 尽量保证图片内容的显示
      int minValue=Math.min(getWidth(),getHeight());
      //设置半径
      mRadius=minValue/2;
      //计算缩放比例 一定要*1.0f 因为int之间的计算结果会四舍五入0或1 效果就不美丽了
      scale=minValue*1.0f/minBitMap;
      //设置缩放比例
      matrix.setScale(scale,scale);
      /**
       * 创建着色器 设置着色模式
       * TileMode的取值有三种:
       * CLAMP 拉伸 REPEAT 重复  MIRROR 镜像
       */
      BitmapShader shader=new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
      //设置矩阵
      shader.setLocalMatrix(matrix);
      paint.setShader(shader);
      canvas.drawCircle(mRadius, mRadius, mRadius, paint);
    }
  }

使用Xfermode 设置图片相交模式

简单说呢 在一张画布上画了两张图片 这两张图的以怎样的方式显示出来 例如:只显示上层图片,只显示下层图片 ,显示两张图的交集部分 等等等

实现思路

1.创建一个空bitmap 根据这个bitmap创建一个Canvas

2.设置Canvas透明 画一个想要实现的形状

3.设置图形相交模式

4.获取图片资源 绘制到Canvas

实现代码

 private Bitmap getCircleBitmap(){
    Drawable drawable=getDrawable();

    if (drawable instanceof BitmapDrawable) {
      Paint paint=new Paint();
      paint.setAntiAlias(true);
      //获取资源图片
      Bitmap bitmap = ((BitmapDrawable) drawable).getBitmap();
      //创建空位图
      Bitmap output=Bitmap.createBitmap(getWidth(),getHeight(),Bitmap.Config.ARGB_8888);
      //创建画板
      Canvas canvas=new Canvas(output);
      //绘制整个画板为透明
      canvas.drawColor(Color.TRANSPARENT);
      paint.setColor(Color.WHITE);
      //绘制圆角图片
      if (type==ROUND){
        canvas.drawRoundRect(new RectF(0, 0, getWidth(), getHeight()), mRound, mRound,paint);
      }else{
        //绘制圆形图片
      
        //取view宽高中的小值 尽量保证图片内容的显示
        int minValue = Math.min(getWidth(), getHeight());
        //设置半径
        mRadius = minValue / 2;
        canvas.drawCircle(mRadius,mRadius,mRadius,paint);
      }
      //设置图形相交模式
      paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));

      Rect src=new Rect(0,0,bitmap.getWidth(),bitmap.getHeight());
      Rect dst=new Rect(0,0,output.getWidth(),output.getHeight());
      canvas.drawBitmap(bitmap,src,dst,paint);
      return output;
    }
    return null;

  }

这个特别经典的图......

PorterDuff.Mode.CLEAR 清除画布上图像
PorterDuff.Mode.SRC 显示上层图像
PorterDuff.Mode.DST 显示下层图像
PorterDuff.Mode.SRC_OVER上下层图像都显示,上层居上显示
PorterDuff.Mode.DST_OVER 上下层都显示,下层居上显示
PorterDuff.Mode.SRC_IN 取两层图像交集部分只显示上层图像
PorterDuff.Mode.DST_IN 取两层图像交集部分,只显示下层图像
PorterDuff.Mode.SRC_OUT 取上层图像非交集部分
PorterDuff.Mode.DST_OUT 取下层图像非交集部分
PorterDuff.Mode.SRC_ATOP 取下层图像非交集部分与上层图像交集部分
PorterDuff.Mode.DST_ATOP 取上层图像非交集部分与下层图像交集部分
PorterDuff.Mode.XOR 取两层图像的非交集部分

参考文档

继承ImageVIew完成圆形和圆角图片控件的实现过程(使用着色器)

  <declare-styleable name="CircleImage">
    <attr name="imageRound" format="dimension"/>
    <attr name="imageType">
      <enum name="circle" value="0"/>
      <enum name="round" value="1"/>
    </attr>

  </declare-styleable>
public class CircleImage extends ImageView {

  private Matrix matrix;
  private Paint paint;
  private int mRound;//圆角度数
  private int mRadius;//圆的半径
  private int type;//控件类型
  private final int CIRCLE=0;//圆形
  private final int ROUND=1;//圆角

  public CircleImage(Context context) {
    super(context,null);
  }

  public CircleImage(Context context, AttributeSet attrs) {
    super(context, attrs);
    matrix=new Matrix();
    paint=new Paint();
    paint.setAntiAlias(true);
    initAttrValues(context,attrs);
  }

  @Override
  protected void onDraw(Canvas canvas) {
    if (getDrawable() == null) {
      return;
    }
    setShader();
    if (type==CIRCLE){
      canvas.drawCircle(mRadius, mRadius, mRadius, paint);
    }else{
      canvas.drawRoundRect(new RectF(0, 0, getWidth(), getHeight()), mRound, mRound,paint);
    }
  }

  /**
   * 初始化属性集合
   * @param context
   * @param attrs
   */
  private void initAttrValues(Context context, AttributeSet attrs){
    TypedArray typedArray=context.obtainStyledAttributes(attrs, R.styleable.CircleImage);
    for (int i=0;i<typedArray.getIndexCount();i++){
      int index=typedArray.getIndex(i);
      switch (index){
        case R.styleable.CircleImage_imageRound:
          mRound =typedArray.getDimensionPixelSize(index,
              (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,10,getResources().getDisplayMetrics()));
          break;
        case R.styleable.CircleImage_imageType:
          type=typedArray.getInt(index,CIRCLE);
          break;
      }
    }
  }

  /**
   * 设置着色器
   */
  private void setShader() {
    //获取Drawable
    Drawable resources=getDrawable();
    float scale = 1.0f;//缩放比例
    if (resources instanceof BitmapDrawable) {
      //获取bitmap
      Bitmap bitmap = ((BitmapDrawable) resources).getBitmap();
      if (bitmap == null) return;
      //圆形
      if (type==CIRCLE){
        // 获取bitmap宽高中的小值
        int minBitMap = Math.min(bitmap.getWidth(), bitmap.getHeight());
        //取view宽高中的小值 尽量保证图片内容的显示
        int minValue = Math.min(getWidth(), getHeight());
        //设置半径
        mRadius = minValue / 2;
        //计算缩放比例 一定要*1.0f 因为int之间的计算结果会四舍五入0或1 效果就不美丽了
        scale = minValue * 1.0f / minBitMap;
      }else{
        //比较view和图片宽高比例大的 要让缩放后的图片大于view
        scale = Math.max(getWidth() * 1.0f / bitmap.getWidth(), getHeight()
            * 1.0f / bitmap.getHeight());
      }
      //设置缩放比例
      matrix.setScale(scale, scale);
      /**
       * 创建着色器 设置着色模式
       * TileMode的取值有三种:
       * CLAMP 拉伸 REPEAT 重复  MIRROR 镜像
       */
      BitmapShader shader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
      //设置矩阵
      shader.setLocalMatrix(matrix);
      //设置着色
      paint.setShader(shader);
    }
  }


  /**
   * 测试转换效果 没什么卵用 可以删除
   * @param event
   * @return
   */
  @Override
  public boolean onTouchEvent(MotionEvent event) {
    if (event.getAction()==MotionEvent.ACTION_DOWN){
      if (type==CIRCLE){
        mRound =10;
        type=ROUND;
      }else{
        type=CIRCLE;
      }
      invalidate();
    }
    return super.onTouchEvent(event);
  }
}

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


# android绘制圆形图片  # android  # 绘制圆形  # Android裁剪图片为圆形图片的实现原理与代码  # Android中Glide加载圆形图片和圆角图片实例代码  # Android实现圆形图片的两种方式  # 详解Android中Glide与CircleImageView加载圆形图片的问题  # 分享一个Android设置圆形图片的特别方法  # Android编程绘制圆形图片的方法  # Android自定义View实现旋转的圆形图片  # Android实现圆形图片或者圆角图片  # Android使用自定义ImageView实现圆形图片效果  # Android实现圆形图片效果  # 着色器  # 只显示  # 两张  # 圆角  # 创建一个  # 两层  # 就不  # 镜像  # 有三种  # 四舍五入  # 居上  # 两种  # 你想  # 看你  # 重写  # 要让  # 很清楚  # 让它  # 用水  # 最简单 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: zabbix利用python脚本发送报警邮件的方法  Claude怎样写约束型提示词_Claude约束提示词写法【教程】  HTML5空格在Angular项目里怎么处理_Angular中空格的渲染问题【详解】  Laravel如何实现多表关联模型定义_Laravel多对多关系及中间表数据存取【方法】  ,在苏州找工作,上哪个网站比较好?  Java遍历集合的三种方式  高端云建站费用究竟需要多少预算?  想要更高端的建设网站,这些原则一定要坚持!  详解ASP.NET 生成二维码实例(采用ThoughtWorks.QRCode和QrCode.Net两种方式)  专业商城网站制作公司有哪些,pi商城官网是哪个?  北京网页设计制作网站有哪些,继续教育自动播放怎么设置?  打开php文件提示内存不足_怎么调整php内存限制【解决方案】  如何在香港服务器上快速搭建免备案网站?  Laravel如何获取当前用户信息_Laravel Auth门面获取用户ID  Laravel如何将应用部署到生产服务器_Laravel生产环境部署流程  Linux网络带宽限制_tc配置实践解析【教程】  武汉网站设计制作公司,武汉有哪些比较大的同城网站或论坛,就是里面都是武汉人的?  浅析上传头像示例及其注意事项  如何在企业微信快速生成手机电脑官网?  Laravel Seeder填充数据教程_Laravel模型工厂Factory使用  Laravel如何与Pusher实现实时通信?(WebSocket示例)  深圳防火门网站制作公司,深圳中天明防火门怎么编码?  进行网站优化必须要坚持的四大原则  魔方云NAT建站如何实现端口转发?  大连企业网站制作公司,大连2025企业社保缴费网上缴费流程?  原生JS获取元素集合的子元素宽度实例  韩国服务器如何优化跨境访问实现高效连接?  php结合redis实现高并发下的抢购、秒杀功能的实例  大学网站设计制作软件有哪些,如何将网站制作成自己app?  焦点电影公司作品,电影焦点结局是什么?  Laravel如何实现URL美化Slug功能_Laravel使用eloquent-sluggable生成别名【方法】  Python进程池调度策略_任务分发说明【指导】  Internet Explorer官网直接进入 IE浏览器在线体验版网址  微博html5版本怎么弄发超话_超话进入入口及发帖格式要求【教程】  php json中文编码为null的解决办法  教你用AI将一段旋律扩展成一首完整的曲子  Laravel如何使用Gate和Policy进行权限控制_Laravel权限判定与策略规则配置  详解免费开源的DotNet二维码操作组件ThoughtWorks.QRCode(.NET组件介绍之四)  网站优化排名时,需要考虑哪些问题呢?  如何在自有机房高效搭建专业网站?  如何快速重置建站主机并恢复默认配置?  javascript中数组(Array)对象和字符串(String)对象的常用方法总结  JavaScript如何实现错误处理_try...catch如何捕获异常?  Laravel如何理解并使用服务容器(Service Container)_Laravel依赖注入与容器绑定说明  如何在橙子建站上传落地页?操作指南详解  如何用已有域名快速搭建网站?  Laravel如何编写单元测试和功能测试?(PHPUnit示例)  海南网站制作公司有哪些,海口网是哪家的?  怎么制作网站设计模板图片,有电商商品详情页面的免费模板素材网站推荐吗?  移动端手机网站制作软件,掌上时代,移动端网站的谷歌SEO该如何做?