热门标签 | HotTags
当前位置:  开发笔记 > Android > 正文

Android编程实现自定义ImageView圆图功能的方法

这篇文章主要介绍了Android编程实现自定义ImageView圆图功能的方法,结合实例形式分析了Android自定义ImageView及实现圆图效果的具体步骤与相关操作技巧,需要的朋友可以参考下

本文实例讲述了Android编程实现自定义ImageView圆图功能的方法。分享给大家供大家参考,具体如下:

首先很感谢开源项目Universal Image Loader图片加载框架。之前也看过一段时间框架源码,但是却没有时间进行知识点的总结。

今天项目遇到了需要实现圆头像的编辑显示,Universal就已经提供了这个显示RoundedBitmapDisplayer这个类实现了圆图功能。看它的代码可以发现是实现的Drawable

public static class RoundedDrawable extends Drawable {
    protected final float cornerRadius;
    protected final int margin;
    protected final RectF mRect = new RectF(),
        mBitmapRect;
    protected final BitmapShader bitmapShader;
    protected final Paint paint;
    public RoundedDrawable(Bitmap bitmap, int cornerRadius, int margin) {
      this.cornerRadius = cornerRadius;
      this.margin = margin;
      bitmapShader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
      mBitmapRect = new RectF (margin, margin, bitmap.getWidth() - margin, bitmap.getHeight() - margin);
      paint = new Paint();
      paint.setAntiAlias(true);
      paint.setShader(bitmapShader);
    }
    @Override
    protected void onBoundsChange(Rect bounds) {
      super.onBoundsChange(bounds);
      mRect.set(margin, margin, bounds.width() - margin, bounds.height() - margin);
      // Resize the original bitmap to fit the new bound
      Matrix shaderMatrix = new Matrix();
      shaderMatrix.setRectToRect(mBitmapRect, mRect, Matrix.ScaleToFit.FILL);
      bitmapShader.setLocalMatrix(shaderMatrix);
    }
    @Override
    public void draw(Canvas canvas) {
      canvas.drawRoundRect(mRect, cornerRadius, cornerRadius, paint);
    }
    @Override
    public int getOpacity() {
      return PixelFormat.TRANSLUCENT;
    }
    @Override
    public void setAlpha(int alpha) {
      paint.setAlpha(alpha);
    }
    @Override
    public void setColorFilter(ColorFilter cf) {
      paint.setColorFilter(cf);
    }
  }

其实总结下来,上面圆图实现步骤就是:

1、通过bitmap初始化位图着色器BitmapShader类
2、计算bitmap原始图片的rect
3、计算放置图片需要的rect
4、使用Matrix类对两个rect进行压缩,然后复制给BitmapShader着色器里去。最后是画布画图。
(刚开始一直以为shader是阴影的意思,原来有道一下是着色器的意思,这个翻译其实对我理解代码还是很重要的,所以不要想当然,要勤奋点,这个是优秀程序员必备要素。)

最后我要实现的是继承ImageView实现圆图

public class URoundedImageView extends ImageView {
  private Paint mBitmapPaint,mBackgroundPaint;
  private BitmapShader mBitmapShader;
  private RectF mBitmapRect , mRect;
  private int borderWidth;
  private Bitmap mBitmap;
  private Matrix shaderMatrix;
  public URoundedImageView(Context context, AttributeSet attrs,
      int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    init();
  }
  public URoundedImageView(Context context, AttributeSet attrs) {
    super(context, attrs);
    init();
  }
  public URoundedImageView(Context context) {
    super(context);
    init();
  }
  private void init(){
    mBitmapPaint = new Paint();
    mBitmapPaint.setAntiAlias(true);
    mBackgroundPaint = new Paint();
    mBackgroundPaint.setAntiAlias(true);
    mBackgroundPaint.setColor(Color.WHITE);
    borderWidth = 5;
    mRect = new RectF();
    shaderMatrix = new Matrix();
  }
  @Override
  protected void onLayout(boolean changed, int left, int top, int right,
      int bottom) {
    // TODO Auto-generated method stub
    super.onLayout(changed, left, top, right, bottom);
  }
  @Override
  protected void onDraw(Canvas canvas) {
    mBitmap = ((BitmapDrawable) getDrawable()).getBitmap();
    if (getWidth() == 0 || getHeight() == 0 || mBitmap == null) {
      return;
    }
    int w = getWidth();
    int h = getHeight();
    int radius = Math.min(w, h) / 2;
    canvas.drawCircle(w / 2, h / 2, radius, mBackgroundPaint);
    //传入bitmap初始化位图着色器
    if (mBitmapShader == null) {
      mBitmapShader = new BitmapShader(mBitmap, Shader.TileMode.CLAMP,
          Shader.TileMode.CLAMP);
    }
    if (mBitmapRect == null) {
      mBitmapRect = new RectF(borderWidth, borderWidth,
          mBitmap.getWidth() - borderWidth, mBitmap.getHeight()
              - borderWidth);
    }
    mBitmapPaint.setShader(mBitmapShader);
    mRect.set(borderWidth, borderWidth, w - borderWidth, h - borderWidth);
    //对bitmap原始图进行缩放
    shaderMatrix.setRectToRect(mBitmapRect, mRect, Matrix.ScaleToFit.FILL);
    mBitmapShader.setLocalMatrix(shaderMatrix);
    canvas.drawRoundRect(mRect, radius, radius, mBitmapPaint);
  }
}

刚开始写的不够规范,直接在ondraw方法里面new一些需要的对象,lint提醒我们Avoid object allocations during draw/layout operations (preallocate and reuse instead)这个warning。因为ondraw会不断调用,如果一直new对象的话会吃内存。所以为了避免重复new对象,根据自己的需求进行判空操作。具体根据自己需求来优化代码,有时候为了达到需求也没办法做到在ondraw方法里不出现重复new对象的现象。

总结:多参考优秀的开源项目,用正确的方法做正确的事情!

更多关于Android相关内容感兴趣的读者可查看本站专题:《Android图形与图像处理技巧总结》、《Android开发入门与进阶教程》、《Android调试技巧与常见问题解决方法汇总》、《Android基本组件用法总结》、《Android视图View技巧总结》、《Android布局layout技巧总结》及《Android控件用法总结》

希望本文所述对大家Android程序设计有所帮助。


推荐阅读
  • 探索新一代API文档工具,告别Swagger的繁琐
    对于后端开发者而言,编写和维护API文档既繁琐又不可或缺。本文将介绍一款全新的API文档工具,帮助团队更高效地协作,简化API文档生成流程。 ... [详细]
  • 程序员如何优雅应对35岁职业转型?这里有深度解析
    本文探讨了程序员在职业生涯中如何通过不断学习和技能提升,优雅地应对35岁左右的职业转型挑战。我们将深入分析当前热门技术趋势,并提供实用的学习路径。 ... [详细]
  • Python 内存管理机制详解
    本文深入探讨了Python的内存管理机制,涵盖了垃圾回收、引用计数和内存池机制。通过具体示例和专业解释,帮助读者理解Python如何高效地管理和释放内存资源。 ... [详细]
  • 本文深入探讨了面向切面编程(AOP)的概念及其在Spring框架中的应用。通过详细解释AOP的核心术语和实现机制,帮助读者理解如何利用AOP提高代码的可维护性和开发效率。 ... [详细]
  • 深入解析Java虚拟机(JVM)架构与原理
    本文旨在为读者提供对Java虚拟机(JVM)的全面理解,涵盖其主要组成部分、工作原理及其在不同平台上的实现。通过详细探讨JVM的结构和内部机制,帮助开发者更好地掌握Java编程的核心技术。 ... [详细]
  • 本月初,我们为大家推荐了一系列精选书单,助力大家提升技术水平。月底,我们将介绍几位行业大牛,帮助大家找到人生导师。InfoQ一直致力于为用户提供有价值的资源和支持。 ... [详细]
  • 深入解析SpringMVC核心组件:DispatcherServlet的工作原理
    本文详细探讨了SpringMVC的核心组件——DispatcherServlet的运作机制,旨在帮助有一定Java和Spring基础的开发人员理解HTTP请求是如何被映射到Controller并执行的。文章将解答以下问题:1. HTTP请求如何映射到Controller;2. Controller是如何被执行的。 ... [详细]
  • HTML基础入门指南
    本文将深入浅出地介绍HTML的基础知识,包括其定义、开发工具、制定机构、特性、基本标签及更多实用内容。 ... [详细]
  • Linux环境下进程间通信:深入解析信号机制
    本文详细探讨了Linux系统中信号的生命周期,从信号生成到处理函数执行完毕的全过程,并介绍了信号编程中的注意事项和常见应用实例。通过分析信号在进程中的注册、注销及处理过程,帮助读者理解如何高效利用信号进行进程间通信。 ... [详细]
  • 2004年春节,作者与父亲讨论了未来的职业规划,并决定尝试创业开设家教培训班。然而,创业过程中的种种困难和挑战最终导致了项目的失败。 ... [详细]
  • 设计模式在软件开发中被广泛应用,但如果不当使用,可能会导致系统复杂性增加。例如,过度添加类可能导致类图难以理解,代码跟踪变得复杂。本文探讨如何在使用设计模式时保持系统的简洁和高效。 ... [详细]
  • Go语言实现经典排序算法:归并排序
    本文介绍如何使用Go语言实现经典的归并排序算法,探讨其原理、代码实现及性能特点。适合Golang开发者和编程爱好者。 ... [详细]
  • 深入理解Java多线程并发处理:基础与实践
    本文探讨了Java中的多线程并发处理机制,从基本概念到实际应用,帮助读者全面理解并掌握多线程编程技巧。通过实例解析和理论阐述,确保初学者也能轻松入门。 ... [详细]
  • SpringMVC RestTemplate的几种请求调用(转)
    SpringMVCRestTemplate的几种请求调用(转),Go语言社区,Golang程序员人脉社 ... [详细]
  • 程序员版情书:王思聪的编程式告白
    当程序员用代码表达爱意,会产生怎样的化学反应?一起来看看这封充满技术感的情书,网友笑称这才是真爱! ... [详细]
author-avatar
CJT--陳嘉婷
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有