Android默认头像那些事儿
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默认头像那些事儿相关推荐
- Android圆形头像图Circle ImageView
<Android圆形头像图Circle ImageView> 需要处理的原始图(pic): 使用CircleImageView处理后的图(作为头像): 现在很多的应用都有设置头像的功能,如 ...
- android 制作用户头像,android 切换头像功能实现
接到一个新需求,用户可以自己跟换自己的头像 1.可以使用相机或是选择照片 2.剪切头像 3.保存头像到本地 实现步骤: 1.我们首先提供用户选择是相机还是相册: 使用alterDialog让用户选择, ...
- Slog42_支配vue框架初阶项目之博客网站-单页-默认头像的布局和定位
ArthurSlog SLog-42 Year·1 Guangzhou·China Aug 19th 2018 GitHub 掘金主页 简书主页 segmentfault 从业之路不同 机缘也不同 人 ...
- 如何删除微软账户下的历史头像,及恢复默认头像
每次修改微软头像时,总会保存历史头像,就像这样 如何删除? 打开此电脑,并在文件资源管理器中输入%appdata%\Microsoft\Windows\AccountPictures Enter后弹出 ...
- Android 默认Tab标签大小及间距修改
一般来说,我都是用Android默认的Tab,但此时Android会根据你增加的Tab页面平均分配Tab标签,假如你只有两个Tab,那么长度将会很长,并且其高度略微过高,并不好看,网上解决这个问题有些 ...
- android 获取默认字体,Android默认字体
Android默认字体 (2012-03-09 17:29:53) 标签: 杂谈 分类: APP 简言之三种: monospace:sans: serif. 并有四种表现形式:正常:斜体:粗体:粗斜体 ...
- Android 圆形头像的两种实现方式
Android 圆形头像的两种实现方式 前言 这篇博客只是为了做一个记录而已,方便而后查询,核心代码都是直接采用鸿洋博客里面的代码的. 圆形头像在实际开发中实际很常见,一般来说,主要有两种实现方式: ...
- java图片头像代码_用Java和OpenCV生成Github默认头像
前言 刚刚过完年,把这样那样的事情忙完,就赶紧把博客剩下的主要功能都先做完了,感觉一身轻松. 闲下来了就抽空看看Github上的项目,偶然间发现Github的默认头像很有特色,它并不像其它的网站一样使 ...
- 设置Android默认锁定屏幕旋转
/*********************************************************************************** 设置Android默认锁定屏幕 ...
- Discuz!更换论坛系统默认头像方法
Discuz!论坛的默认头像一方面不够个性化,另一方面对用户体验也不是最佳,所以很多站长更换论坛的默认头像,下面分享下更换的方法,适合一些小白站长: 代替UC目录下的3个图片,默认是uc_server ...
最新文章
- [USACO08NOV]lites
- Msdn 杂志 asp.net ajax 文章汇集
- 谷歌Analytics添加到您的SharePoint 2010网站的2种方法
- Go Language 开发环境搭建
- 【C#】详解C#委托
- php验证时区是否存在,php – 验证来自不同网站的时区名称?
- Spring框架功能整体介绍
- 【每日SQL打卡】​​​​​​​​​​​​​​​DAY 26丨餐馆营业额变化增长【难度中等】​
- 有这16个特征,说明你已达到很高的境界了
- 哈佛博士后入职街道办引关注,官方最新回应
- oc 经常用到弹出view的方法
- Excel 修改 【数据图表】 的 【数据源】 的范围 (VBA)
- python常用代码总结-python个人总结
- html 自动关机程序,Windows 自动关机/定时关机 命令 shuntdown
- Oracle PL/SQL基础
- 30 张快速学习 Java 的思维导图
- 常见bat命令(二)
- DWC PCIE学习笔记(一)-----PCIE PHY接口
- java流程图都有哪些,盘点国内都有哪些免费好用的流程图设计工具
- Newoupui-pak配置失败怎么处理?
热门文章
- ZOJ-3939 The Lucky Week
- 山东理工ACM[2108]一元二次方程Ⅲ
- 攻防世界Let_god_knows
- VMware虚拟机中Windows11无法连接网络
- 计算机取证volatility
- android.intent.action大全和用法收集
- Spring实战第五章idea复现
- linux输入文件后clustalw,ClustalW----多序列比对分析(一)
- 光伏运维将面临行业洗牌?
- [精华] RDMA技术原理分析、主流实现对比和解析