系列文章目录
文章目录
前言
这系列的文章主要是基于扔物线的HenCoderPlus课程的源码来分析学习。
- 扔物线课程源码:AvatarView.java
- Android官方文档:自定义绘制
创建绘制对象
我们需要创建一个画笔🖌Paint
来绘制我们的头像的边框,也需要提前加载我们的头像到内存(Bitmap)中。
public class AvatarView extends View {
// 头像的宽度
private static final float WIDTH = Utils.dp2px(300);
// 头像距离画布边界的填充量
private static final float PADDING = Utils.dp2px(50);
// 头像边框的宽度
private static final float EDGE_WIDTH = Utils.dp2px(10);
// 抗锯齿
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
// 头像的Bitmap
Bitmap bitmap;
public AvatarView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
{
// 代码详见下一章介绍
bitmap = getAvatar((int) WIDTH);
}
}
加载头像
为避免出现
java.lang.OutOfMemory
异常,请先检查位图的尺寸,然后再对其进行解码,除非您绝对信任该来源可为您提供大小可预测的图片数据,以轻松适应可用的内存。——引用自Android官方文档:高效加载大型位图
下述源码的分析请见官方的说明:将按比例缩小的版本加载到内存中。
/**
* 获取头像
*
* @param width 按照width读取图片
*/
Bitmap getAvatar(int width) {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
// 这是一个耗时操作,在配置了options.inJustDecodeBounds = true后,仅会从资源中解析出来图片的宽高。
BitmapFactory.decodeResource(getResources(), R.drawable.avatar_rengwuxian, options);
// 开始读取Bitmap
options.inJustDecodeBounds = false;
options.inDensity = options.outWidth;
options.inTargetDensity = width;
return BitmapFactory.decodeResource(getResources(), R.drawable.avatar_rengwuxian, options);
}
自定义绘制内容
先上一下我们绘制圆形头像的效果图。
绘制头像边框
public class AvatarView extends View {
// 头像的宽度
private static final float WIDTH = Utils.dp2px(300);
// 头像距离画布边界的填充量
private static final float PADDING = Utils.dp2px(50);
// 头像边框的宽度
private static final float EDGE_WIDTH = Utils.dp2px(10);
// 头像边框的点坐标
private final float BORDER_UPPER = PADDING;
private final float BORDER_LOWER = PADDING + WIDTH;
// 头像圆底的点坐标
private final float UPPER = BORDER_UPPER + EDGE_WIDTH;
private final float LOWER = BORDER_LOWER - EDGE_WIDTH;
// 抗锯齿
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
public AvatarView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onDraw(Canvas canvas) {
super