Android自定义View之绘制圆形头像功能

前言

做APP应用开发的时候,用户头像肯定是必不可少的,但是90%以上的需求头像都是圆形的。那么,如何通过自定义View的方式实现圆形头像呢,那么,本片博文会告诉你不仅仅是实现过程。一定会有意想不到的收获哦!

最终效果

国际惯例,我们先来看最终实现的效果图

自定义RoundImageView继承自ImageView

public class RoundImageView extends ImageView {
  public RoundImageView(Context context) {
    super(context);
  }
  public RoundImageView(Context context, @Nullable AttributeSet attrs) {
    super(context, attrs);
  }
  public RoundImageView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
  }
}

不知你是否注意过每当我们继承自View的时候,系统都会提示我们覆盖重写4个构造方法,这里我们只覆盖了三个,然后就开始在每个构造方法中进行初始化,那么,是不是每次都会调用所有的构造方法呢,如果不是,这三个构造方法又会什么时候调用呢?下面我们来通过例子来验证。

使用自定义View无非就两种情况下,第一种就是直接在xml布局中使用,另一种就是在Activity中new出来,下面我们分别使用上述两种方式,为了便于观察我们在三个构造方法中分别加入一行打印。

首先我们在xml直接使用,运行打印如下:

com.example.roundimageview D/RoundImageView: RoundImageView: 两个参数的构造方法

然后我们在Activity中,new一个RoundImageView

roundImageView = RoundImageView(this@MainActivity)
roundImageView = RoundImageView(this@MainActivity, null)
roundImageView = RoundImageView(this@MainActivity, null,0)

运行打印日志如下:

结论:自定义View当在xml中使用,使用的是第二个构造方法,当在Activity中使用时,实例化时传入几个参数调用的就是含有几个参数的构造方法。

实现圆形头像的思想

我始终认为自定义View的难度只在于它的实现思想,通常我们遇到问题的时候,并不是Google不到,而是压根就不知道这个问题该去如何Google,如果知道了问题所产生的原因,其实问题已经迎刃而解了,最怕的是不知道问题为什么会产生。

实现圆形头像的思想一个简单的图就可以表示了。

矩形区域是完整的图片,圆形区域就是我们最终显示的头像区域,那么就很简单了,圆形区域与矩形区域相交,取并集区域?在矩形中画一个与矩形长或宽相切的圆,而圆的直径是长或宽较短的一边。

编码实现

获取原有头像的bitmap

首先我们需要获取设置头像的bitmap,我们可以直接通过API来获取设置的图片资源,

drawable = this.getDrawable();

再将图片资源转化为bitmap

首先我们判断drawable是否为空,如果为空说明用户没有设置,抛出资源未找到的异常。

if (drawable == null) {
  throw new Resources.NotFoundException("Image resource not set");
}

如果不为空,我们创建一个与图片资源大小相等的bitmap,并将bitmap绘制出来,代码如下所示:

bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(),
    Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, drawable.getIntrinsicWidth(),
    drawable.getIntrinsicHeight());
drawable.draw(canvas);

绘制圆形bitmap

通过上面的代码,我们得到了原有的bitmap图像,紧接着我们需要绘制圆形的bitmap,与上面类似,首先创建一个和bitmap大小一致的位图

circleBitmap = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888);

我们画一个与bitmap等大的矩形

Paint paint = new Paint();
Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
canvas.drawRect(rect,paint);
RectF rectF = new RectF(rect);

将较短的一边设置圆的半径

float roundRa = 0.0f;
if (bitmap.getWidth() > bitmap.getHeight()) {
  roundRa = bitmap.getHeight() / 2.0f;
} else {
  roundRa = bitmap.getWidth() / 2.0f;
}

设置paint和canvas属性

paint.setAntiAlias(true);
canvas.drawARGB(0, 0, 0, 0);
paint.setColor(Color.WHITE);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));

canvas.drawARGB将绘制裁剪设为透明,paint.setXfermode中的PorterDuffXfermode类很强大,后面我们会单独一篇文章讲解。

最终我们重新将bitmap绘制出来即可

canvas.drawBitmap(bitmap, rect, rect, paint);

绘制部分完整代码如下所示:

* 获取圆形裁剪的bitmap
 *
 * @param bitmap 原bitmap
 */
private Bitmap getCircleBitmap(Bitmap bitmap) {
  circleBitmap = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888);
  Canvas canvas = new Canvas(circleBitmap);
  Paint paint = new Paint();
  Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
  RectF rectF = new RectF(rect);
  float roundRa = 0.0f;
  if (bitmap.getWidth() > bitmap.getHeight()) {
    roundRa = bitmap.getHeight() / 2.0f;
  } else {
    roundRa = bitmap.getWidth() / 2.0f;
  }
  paint.setAntiAlias(true);
  canvas.drawARGB(0, 0, 0, 0);
  paint.setColor(Color.GRAY);
  canvas.drawRoundRect(rectF, roundRa, roundRa, paint);
  paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
  canvas.drawBitmap(bitmap, rect, rect, paint);
  return circleBitmap;
}

设置最终的bitmap

得到bitma后我们直接重新设置即可显示

 setImageBitmap(getCircleBitmap(bitmap));

本实例较为简单,就不贴所有代码了,如有需要留言邮箱即可,如有纰漏之处,欢迎指正!晚安!

9.15 22:17 更新

代码已上传github:https://github.com/huanglinqing123/RoundImageView

总结

以上所述是小编给大家介绍的Android自定义View之绘制圆形头像功能,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对我们网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!

(0)

相关推荐

  • Android自定义View实现抽奖转盘

    本文实例为大家分享了Android自定义View实现抽奖转盘的具体代码,供大家参考,具体内容如下 public class LuckCircle extends SurfaceView implements SurfaceHolder.Callback,Runnable { private SurfaceHolder mHolder; private Canvas mCanvas; //用于绘制的线程 private Thread mThread; //线程开关的控制 private boole

  • Android自定义View实现渐变色仪表盘

    前言:最近一直在学自定义View的相关知识,感觉这在Android中还是挺难的一块,当然这也是每个程序员必经之路,正好公司项目要求实现类似仪表盘的效果用于直观的显示公司数据,于是就简单的写了个demo,记录实现的过程.上篇<Android自定义View实现圆弧进度效果>简单记录了圆弧及文字的绘制,渐变色的仪表盘效果将更加升入的介绍canvas及paint的使用(如画布旋转,paint的渐变色设置等). 知识梳理 1.圆弧渐变色(SweepGradient) 2.圆弧上刻度绘制 3.指针指示当前

  • Android自定义View实现课程表表格

    自己闲下来时间写的一个课表控件,使用的自定义LinearLayout,里面View都是用代码实现的,最终效果如下图,写的可能有问题希望多多指点 创建一个自定义LinearLayout 控件用来装载课程的信息和课程的周数,和节数大概的布局三这样的 根据上面的看来觉得总体布局我分了两个 上面的星期是一个 下面的节数和格子是一个  总体使用Vertical  而单独内部者使用了Horizontal布局  中间使用了两种布局线条 是这样的 /** * 横的分界线 * * @return */ priva

  • Android自定义ViewPager实现纵向滑动翻页效果

    抖音几乎已经成为了我们日常生活中使用比较频繁的App,无聊之时或工作之后可以刷一刷短视频来供我们娱乐与放松.看到抖音的视屏切换效果,觉得用ViewPager可以做出一样的效果.想一想之前用的ViewPager都是横向切换的,虽然很经常用,但是从来没实现过竖向的切换效果,说做就做吧. 我们先看一波效果图: 那么,要想实现这样的效果,当然是自定义ViewPager啦.问了一下度娘,看到有这样一种思路: 首先,把Touch事件的x,y坐标做一下交换,从原先的x坐标差值转变成y坐标的差值,正符合了我们手

  • Android基于wheelView实现自定义日期选择器

    本文实例为大家分享了Android实现自定义日期选择器的具体代码,供大家参考,具体内容如下 项目要求效果图: 要求 "6月20 星期五" 这一项作为一个整体可以滑动,"7时"."48分"分别作为一个滑动整体. 系统自带的DatePicker.TimePicker大家都知道,只有这种效果: 百度了很多,试了NumberPicker等都不行,本来打算自己写.网友推荐了一个开源组件WheelView,下下来试了试,发现他已经定义的很完善了,在他的基础上

  • Android自定义view渐变圆形动画

    本文实例为大家分享了Android自定义view渐变圆形动画的具体代码,供大家参考,具体内容如下 直接上效果图 自定义属性 attrs.xml文件 <resources> <declare-styleable name="ProgressRing"> <!--进度起始色--> <attr name="pr_progress_start_color" format="color" /> <!--

  • Android自定义wheelview实现滚动日期选择器

    本文实例为大家分享了Android实现滚动日期选择器的具体代码,供大家参考,具体内容如下 wheelview滚动效果的View 这段时间需要用到一个时间选择器,但是不能使用日期对话框, 因为它是筛选条件框架下的,只能是View!这个WheelView改造后可以达到要求! 这个wheelview框架使用的类不多,就几个,还有一些资源文件. 我根据这个框架设计了日期的选择器. 主页面: 第一种日期选择器页面: 动态效果: 使用: 具体的实现是一个LoopView的类,这是一个继承View的类! 理解

  • Android自定义View实现水平带数字百分比进度条

    这个进度条可以反映真实进度,并且完成百分比的文字时随着进度增加而移动的,所在位置也恰好是真实完成的百分比位置,效果如下: 思路如下:第一部分是左侧的蓝色直线,代表已经完成的进度:第二部分是右侧灰色的直线,代表未完成的进度:第三部分是红色的百分比的数字百分比文本,显示当前确切的完成进度. 最关键的部分就是要确定百分比文本的确切位置,这里用了paint的getTextBounds方法,得到文本的宽高,然后再精确确定它的位置. view代码如下: public class NumberProgress

  • Android自定义View app更新动画详解

    为了做一个有温度的IT男,我决定在以后的文章中给大家分享一些看到的,听到的一些东西,如果你不喜欢请留言让我知道,如果你喜欢请点个赞.你也可留言写下自己想分享的东西,温暖你我他.这次分享的是一首歌,毛不易的<消愁>,分享这首歌主要是这首歌的歌词,借用薛之谦的评价:"我是研究歌词的人,我研究了十几年,但是你写到我想给你跪!",下面贴部分歌词供大家欣赏 一杯敬朝阳,一杯敬月光 唤醒我的向往,温柔了寒窗 于是可以不回头的逆风飞翔 不怕心头有雨,眼底有霜 一杯敬故乡,一杯敬远方 守着

  • Android自定义View实现简单文字描边功能

    本文实例为大家分享了Android实现简单文字描边功能的具体代码,供大家参考,具体内容如下 效果图: 实现代码: package com.example.zhangyu.myview.widget; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.

随机推荐