Android应用市场中几乎所有APP中都会涉及用户体系.当然也就需要页面去处理用户信息的展示、用户头像的展示等.对于用户头像展示,有很多优秀的图片加载框架,平常写项目会经常使用到这些图片加载框架,使用起来也很方便,效率也比较高.但是面对不同的需求时,处理的方式可能就有些不同.下面分析几种需求.

文章使用Glide框架, 当然其他的图片加载框架处理方式应该相似,就不多做介绍.简单介绍下Glide的集成配置

首先配置一下Glide.在build.grade中添加对Gilde的引用及网络框架的引用

compile 'com.github.bumptech.glide:glide:3.7.0'
//OkHttp 3.x
compile 'com.github.bumptech.glide:okhttp3-integration:1.4.0@aar'
compile 'com.squareup.okhttp3:okhttp:3.2.0’

然后配置一下权限

<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE”/>

接着就可以使用Glide了.


分析

1) 第一种需求

设置一个默认的头像图片显示,这种需求是最常见,也是最容易处理的.
用Glide一句代码就可以实现,如下

Glide.with(Activity).load("头像地址URL").placeholder(R.mipmap.xxxx).dontAnimate().into(ImageView);

with中的参数可以是Activity,fragment,context.
placeholder中的参数就是项目中默认图片的资源.
dontAnimate方法是取消动画效果
into中的参数当然就是需要展示图像的ImageView

2) 第二种需求

设置一个圆形(圆角)的默认头像图片显示,这种需求也比较常见,唯一的问题就是圆形(圆角)的图片展示.对于圆形图片展示,因为用到Glide所以这里想到最简便的解决方法就是找一个继承自ImageView的自定义控件.有很多,文章选用CircleImageView来进行演示,有兴趣的童鞋可以深入看一下实现.
github地址https://github.com/hdodenhof/CircleImageView

那面对这种需求,就可以这样写

Glide.with(Activity).load("头像地址URL").placeholder(R.mipmap.xxxx).dontAn imate().into(CircleImageView);

into中参数为圆形自定义控件.

3) 第三种需求

设置一个带有随机背景颜色和文字的默认图片展示,这种需求往往出现在通讯录,好友等场景下,文字的目的是为了让用户更快的找到自己想找的目标(当然,我也是最近写项目,产品提的这种需求),随机背景颜色是为了更加美观(我认为的- -~).
好了,面对这种需求,得先考虑一下怎么去做,如果去适应Glide,那就看一下placeholder方法,可以看到Glide提供了两种方法,如下

/*** {@inheritDoc}*/
@Override
public DrawableRequestBuilder<ModelType> placeholder(int resourceId) {super.placeholder(resourceId);return this;
}/*** {@inheritDoc}*/
@Override
public DrawableRequestBuilder<ModelType> placeholder(Drawable drawable) {super.placeholder(drawable);return this;
}

第一个方法是之前用到的,参数是一个默认的资源文件,第二个重载方法的参数是一个Drawable,显然文字是变化的,资源文件并不合适,只能在第二个重载方法上考虑一下.怎么做呢?其实很简单,可以通过安卓提供的方法创建一个带有文字和背景颜色的Drawable对象.贴一下完整代码,比较简单

package com.angent.defaultavatardemo.utils;import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;/*** Created by junweiliu on 17/1/18.*/
public class MakeRandomPhoto {/*** 默认字体大小*/private final int DEFAULT_FONT_SIZE = 20;/*** 默认字体大小*/private final int DEFAULT_FONT_COLOR = Color.WHITE;/*** 默认的图片宽*/private final int DEFAULT_WIDTH = 60;/*** 默认的图片高*/private final int DEFAULT_HEIGHT = 60;/*** 默认显示的文字数目*/private final int DEFAULT_SHOW_NUM = 2;/*** 默认的图片颜色*/private final int DEFAULT_COLOR = Color.BLUE;/*** 图片宽高*/private int width = DEFAULT_WIDTH, height = DEFAULT_HEIGHT;/*** 图片颜色*/private int color = DEFAULT_COLOR;/*** 文字大小*/private int fontSize = DEFAULT_FONT_SIZE;/*** 文字颜色*/private int fontColor = DEFAULT_FONT_COLOR;/*** 默认显示的文字数*/private int showNum = DEFAULT_SHOW_NUM;/*** 画笔*/private Paint mPaint;/*** 画笔属性*/private Paint.FontMetrics fm;/*** 单例*/public static MakeRandomPhoto instance;/*** 获取单例** @return*/public static MakeRandomPhoto getInstance() {if (instance == null) {synchronized (MakeRandomPhoto.class) {if (instance == null) {instance = new MakeRandomPhoto();}}}return instance;}/*** 设置图片宽** @return*/public MakeRandomPhoto setWidth(int width) {if (0 == width) {this.width = DEFAULT_WIDTH;} else {this.width = width;}return instance;}/*** 设置图片背景颜色** @return*/public MakeRandomPhoto setBackGroudColor(int color) {if (0 == color) {this.color = DEFAULT_COLOR;} else {this.color = color;}return this;}/*** 设置图片高** @return*/public MakeRandomPhoto setHeight(int height) {if (0 == height) {this.height = DEFAULT_HEIGHT;} else {this.height = height;}return this;}/*** 设置文字颜色** @return*/public MakeRandomPhoto setTxtColor(int fontcolor) {if (0 == fontcolor) {this.fontColor = DEFAULT_FONT_COLOR;} else {this.fontColor = fontcolor;}return this;}/*** 设置文字大小** @return*/public MakeRandomPhoto setTxtSize(int fontsize) {if (0 == fontsize) {this.fontSize = DEFAULT_FONT_SIZE;} else {this.fontSize = fontsize;}return this;}/*** 设置显示文字个数** @return*/public MakeRandomPhoto setShowNum(int showNum) {if (0 == showNum) {this.showNum = DEFAULT_SHOW_NUM;} else {this.showNum = showNum;}return this;}/*** 创建随机图片** @return*/public Bitmap makeRandomPhotoBp(String txt) {if (null == txt || "".equals(txt)) {txt = "    ";}// 处理展示的文字if (txt.length() > showNum) {txt = txt.substring(txt.length() - showNum);}// 这里使用RGB_565,系统开销小一点Bitmap bp = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);Canvas c = new Canvas(bp);mPaint = new Paint();mPaint.setColor(fontColor);mPaint.setTextSize(fontSize);mPaint.setTextAlign(Paint.Align.CENTER);mPaint.setAntiAlias(true);fm = mPaint.getFontMetrics();// 设置背景颜色c.drawColor(ColorUtils.getRandomColor(txt.hashCode()));// 居中显示c.drawText(txt, width / 2, height / 2 - fm.descent + (fm.descent - fm.ascent) / 2, mPaint);c.save(Canvas.ALL_SAVE_FLAG);//保存c.restore();//return bp;}/*** 创建随机图片(Drawable)** @return*/public Drawable makeRandomPhotoDrawable(String txt) {Drawable db = new BitmapDrawable(makeRandomPhotoBp(txt));return db;}/*** 创建群组图像** @param leftTopBp* @param rightTopBp* @param leftBottomBp* @param rightBottomBp* @return*/public Bitmap makeGroupPhotoBp(Bitmap leftTopBp, Bitmap rightTopBp, Bitmap leftBottomBp, Bitmap rightBottomBp) {Bitmap bp = Bitmap.createBitmap(width * 2, height * 2, Bitmap.Config.RGB_565);Canvas c = new Canvas(bp);Paint mPaint = new Paint();// 绘制左上角c.drawBitmap(leftTopBp, 0, 0, mPaint);// 绘制右上角c.drawBitmap(rightTopBp, width, 0, mPaint);// 绘制左下角c.drawBitmap(leftBottomBp, 0, height, mPaint);// 绘制右下角c.drawBitmap(rightBottomBp, width, height, mPaint);c.save(Canvas.ALL_SAVE_FLAG);//保存c.restore();return bp;}/*** 创建群组图片(Drawable)** @return*/public Drawable makeGroupPhotoDrawable(Bitmap leftTopBp, Bitmap rightTopBp, Bitmap leftBottomBp, Bitmap rightBottomBp) {Drawable db = new BitmapDrawable(makeGroupPhotoBp(leftTopBp, rightTopBp, leftBottomBp, rightBottomBp));return db;}
}

使用方法,例如在适配器中

    @Overridepublic View getView(final int position, View convertView, ViewGroup parent) {viewHolder = null;UserBean bean = mDatas.get(position);if (convertView == null) {convertView = mInflater.from(mContext).inflate(R.layout.item_user, null);viewHolder = new ViewHolder();viewHolder.userNameTv = (TextView) convertView.findViewById(R.id.tv_user_name);viewHolder.userPhotoIv = (ImageView) convertView.findViewById(R.id.ci_user_photo);viewHolder.userPhotoTv = (TextView) convertView.findViewById(R.id.tv_user_photo);convertView.setTag(viewHolder);} else {viewHolder = (ViewHolder) convertView.getTag();}viewHolder.userNameTv.setText(bean.getUserName());// Glide加载Glide.with(mContext).load(bean.getUserPhoto()).placeholder(MakeRandomPhoto.getInstance().setWidth(48).setHeight(48).setTxtSize(20).setTxtColor(Color.parseColor("#ffffff")).setShowNum(2).makeRandomPhotoDrawable(bean.getUserName())).dontAnimate().into(viewHolder.userPhotoIv);return convertView;}

封装了一个制作默认头像的工具类,提供方法设置相关属性,每个设置方法都会返回对象本身是为了方便连缀使用,看一下核心方法

/*** 创建随机图片** @return*/
public Bitmap makeRandomPhotoBp(String txt) {if (null == txt || "".equals(txt)) {txt = "    ";}if (txt.length() > showNum) {txt = txt.substring(txt.length() - showNum);}// 这里使用RGB_565,系统开销小一点Bitmap bp = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);Canvas c = new Canvas(bp);mPaint = new Paint();mPaint.setColor(fontColor);mPaint.setTextSize(fontSize);mPaint.setTextAlign(Paint.Align.CENTER);mPaint.setAntiAlias(true);fm = mPaint.getFontMetrics();// 设置背景颜色c.drawColor(ColorUtils.getRandomColor(txt.hashCode()));// 居中显示c.drawText(txt, width / 2, height / 2 - fm.descent + (fm.descent - fm.ascent) / 2, mPaint);c.save(Canvas.ALL_SAVE_FLAG);//保存c.restore();//return bp;
}

首先对传入的文字进行处理,截取出需要显示的文字,默认显示字符串的最后两个字符,当然也可以自己设置.然后创建了一个Bitmap,这里使用RGB_565而不是ARGB_8888,是因为RGB_565的开销要小于ARGB_8888,一个背景色对画质的要求不是很高.最后就是创建画布,在画布中去完成背景色和文字的绘制.有一个ColorUtils,这个是封装的一个随机颜色工具,一起看一下.

package com.angent.defaultavatardemo.utils;import android.graphics.Color;
import android.support.annotation.IntRange;import com.angent.defaultavatardemo.R;/*** Created by junweiliu on 17/1/18.*/
public class ColorUtils {/*** 随机颜色起始*/private static final int RANDOM_COLOR_START_RANGE = 0;/*** 随机颜色终止*/private static final int RANDOM_COLOR_END_RANGE = 7;/*** 获取随机color名称** @param colorPosition 唯一值,这里用string的hashcode* @return*/public static String getRandomColorName(@IntRange(from = RANDOM_COLOR_START_RANGE, to = RANDOM_COLOR_END_RANGE)int colorPosition) {colorPosition = Math.abs(colorPosition) % RANDOM_COLOR_END_RANGE;return String.format("random_color_%d", colorPosition + 1);}/*** 获取随机color颜色** @param colorPosition 唯一值,这里用string的hashcode* @return*/public static int getRandomColor(@IntRange(from = RANDOM_COLOR_START_RANGE, to = RANDOM_COLOR_END_RANGE)int colorPosition) {String colorNmae = getRandomColorName(colorPosition);int resId = Color.parseColor("#8a8a8a");if (colorNmae.contains("1")) {resId = Color.parseColor("#8a8a8a");} else if (colorNmae.contains("2")) {resId = Color.parseColor("#f7b54e");} else if (colorNmae.contains("3")) {resId = Color.parseColor("#17c295");} else if (colorNmae.contains("4")) {resId = Color.parseColor("#4da9eb");} else if (colorNmae.contains("5")) {resId = Color.parseColor("#b38979");} else if (colorNmae.contains("6")) {resId = Color.parseColor("#568aad");} else if (colorNmae.contains("7")) {resId = Color.parseColor("#f2725e");} else {resId = Color.parseColor("#8a8a8a");}return resId;}/*** 获取color资源** @param colorPosition 唯一值,这里用string的hashcode* @return*/public static int getCircleColorBgId(@IntRange(from = RANDOM_COLOR_START_RANGE, to = RANDOM_COLOR_END_RANGE)int colorPosition) {String colorNmae = getRandomColorName(colorPosition);int resId = R.mipmap.random_color_one;if (colorNmae.contains("1")) {resId = R.mipmap.random_color_one;} else if (colorNmae.contains("2")) {resId = R.mipmap.random_color_two;} else if (colorNmae.contains("3")) {resId = R.mipmap.random_color_three;} else if (colorNmae.contains("4")) {resId = R.mipmap.random_color_four;} else if (colorNmae.contains("5")) {resId = R.mipmap.random_color_five;} else if (colorNmae.contains("6")) {resId = R.mipmap.random_color_six;} else if (colorNmae.contains("7")) {resId = R.mipmap.random_color_seven;} else {resId = R.mipmap.random_color_one;}return resId;}
}

ColorUtils的主要作用就是通过字符串的hashcode值,来生成一个随机的颜色值,当然相同字符串的hashcode值是相同的,这样就保证了每个文字对应一个相同的随机颜色.
ColorUtils中还提供了一个获取随机背景图片的方法,这个方法是干嘛用的呢?
这个就是为了第二种方案写的,如果不依赖Glide,不使用placeholder方法.怎么实现这种随机背景颜色上带有文字的默认头像呢,看一下布局文件,可能就懂了.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="horizontal"><TextView
            android:id="@+id/tv_user_photo"android:layout_width="48dp"android:layout_height="48dp"android:layout_centerVertical="true"android:layout_marginBottom="10dp"android:layout_marginLeft="16dp"android:layout_marginRight="16dp"android:layout_marginTop="10dp"android:gravity="center"android:textColor="#ffffff"android:textSize="20sp"android:visibility="visible"/><com.angent.defaultavatardemo.widget.CircleImageView
            android:id="@+id/ci_user_photo"android:layout_width="48dp"android:layout_height="48dp"android:layout_centerVertical="true"android:layout_marginBottom="10dp"android:layout_marginLeft="16dp"android:layout_marginRight="16dp"android:layout_marginTop="10dp"android:visibility="visible"/><TextView
            android:id="@+id/tv_user_name"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_centerVertical="true"android:layout_toRightOf="@+id/ci_user_photo"android:text="名字"android:textColor="#333333"android:textSize="16sp"/></RelativeLayout>

在CircleImageView下边有一个TextView,位置刚好和CircleImageView重合,并且在下层.再看一下代码中的写法

    @Overridepublic View getView(final int position, View convertView, ViewGroup parent) {...viewHolder.userNameTv.setText(bean.getUserName());// 设置随机颜色背景viewHolder.userPhotoTv.setBackgroundResource(ColorUtils.getCircleColorBgId(bean.getUserName().hashCode()));// 设置文字viewHolder.userPhotoTv.setText(bean.getUserName().substring(bean.getUserName().length() - 2));// 加载图像Glide.with(mContext).load(bean.getUserPhoto()).dontAnimate().into(viewHolder.userPhotoIv);return convertView;}

应该很简单,这种方案的思路就是,如果Glide加载图片成功了,就把地下的TextView遮住,如果没有加载成功,那么下层的TextView就作为默认头像显示.

应该还有其他更好的方案,这里就提供这两种.测试了一下两种方案的性能,基本没有差别.推荐第二种方案,显示时比较清晰

最后看一下效果图吧


源码地址

源码下载

Android默认头像那些事儿相关推荐

  1. Android圆形头像图Circle ImageView

    <Android圆形头像图Circle ImageView> 需要处理的原始图(pic): 使用CircleImageView处理后的图(作为头像): 现在很多的应用都有设置头像的功能,如 ...

  2. android 制作用户头像,android 切换头像功能实现

    接到一个新需求,用户可以自己跟换自己的头像 1.可以使用相机或是选择照片 2.剪切头像 3.保存头像到本地 实现步骤: 1.我们首先提供用户选择是相机还是相册: 使用alterDialog让用户选择, ...

  3. Slog42_支配vue框架初阶项目之博客网站-单页-默认头像的布局和定位

    ArthurSlog SLog-42 Year·1 Guangzhou·China Aug 19th 2018 GitHub 掘金主页 简书主页 segmentfault 从业之路不同 机缘也不同 人 ...

  4. 如何删除微软账户下的历史头像,及恢复默认头像

    每次修改微软头像时,总会保存历史头像,就像这样 如何删除? 打开此电脑,并在文件资源管理器中输入%appdata%\Microsoft\Windows\AccountPictures Enter后弹出 ...

  5. Android 默认Tab标签大小及间距修改

    一般来说,我都是用Android默认的Tab,但此时Android会根据你增加的Tab页面平均分配Tab标签,假如你只有两个Tab,那么长度将会很长,并且其高度略微过高,并不好看,网上解决这个问题有些 ...

  6. android 获取默认字体,Android默认字体

    Android默认字体 (2012-03-09 17:29:53) 标签: 杂谈 分类: APP 简言之三种: monospace:sans: serif. 并有四种表现形式:正常:斜体:粗体:粗斜体 ...

  7. Android 圆形头像的两种实现方式

    Android 圆形头像的两种实现方式 前言 这篇博客只是为了做一个记录而已,方便而后查询,核心代码都是直接采用鸿洋博客里面的代码的. 圆形头像在实际开发中实际很常见,一般来说,主要有两种实现方式: ...

  8. java图片头像代码_用Java和OpenCV生成Github默认头像

    前言 刚刚过完年,把这样那样的事情忙完,就赶紧把博客剩下的主要功能都先做完了,感觉一身轻松. 闲下来了就抽空看看Github上的项目,偶然间发现Github的默认头像很有特色,它并不像其它的网站一样使 ...

  9. 设置Android默认锁定屏幕旋转

    /*********************************************************************************** 设置Android默认锁定屏幕 ...

  10. Discuz!更换论坛系统默认头像方法

    Discuz!论坛的默认头像一方面不够个性化,另一方面对用户体验也不是最佳,所以很多站长更换论坛的默认头像,下面分享下更换的方法,适合一些小白站长: 代替UC目录下的3个图片,默认是uc_server ...

最新文章

  1. [USACO08NOV]lites
  2. Msdn 杂志 asp.net ajax 文章汇集
  3. 谷歌Analytics添加到您的SharePoint 2010网站的2种方法
  4. Go Language 开发环境搭建
  5. 【C#】详解C#委托
  6. php验证时区是否存在,php – 验证来自不同网站的时区名称?
  7. Spring框架功能整体介绍
  8. 【每日SQL打卡】​​​​​​​​​​​​​​​DAY 26丨餐馆营业额变化增长【难度中等】​
  9. 有这16个特征,说明你已达到很高的境界了
  10. 哈佛博士后入职街道办引关注,官方最新回应
  11. oc 经常用到弹出view的方法
  12. Excel 修改 【数据图表】 的 【数据源】 的范围 (VBA)
  13. python常用代码总结-python个人总结
  14. html 自动关机程序,Windows 自动关机/定时关机 命令 shuntdown
  15. Oracle PL/SQL基础
  16. 30 张快速学习 Java 的思维导图
  17. 常见bat命令(二)
  18. DWC PCIE学习笔记(一)-----PCIE PHY接口
  19. java流程图都有哪些,盘点国内都有哪些免费好用的流程图设计工具
  20. Newoupui-pak配置失败怎么处理?

热门文章

  1. ZOJ-3939 The Lucky Week
  2. 山东理工ACM[2108]一元二次方程Ⅲ
  3. 攻防世界Let_god_knows
  4. VMware虚拟机中Windows11无法连接网络
  5. 计算机取证volatility
  6. android.intent.action大全和用法收集
  7. Spring实战第五章idea复现
  8. linux输入文件后clustalw,ClustalW----多序列比对分析(一)
  9. 光伏运维将面临行业洗牌?
  10. [精华] RDMA技术原理分析、主流实现对比和解析