自定义圆形ImageView(圆形头像 可指定大小)

最近在仿手Q的UI,这里面经常要用到的就是圆形头像,看到 在android中画圆形图片的几种办法 这篇文章,了解了制作这种头像的原理.不过里面提供的方法还有一个不足的地方就是不能根据实际需求改变图片的大小,也就是说提供的原图是大尺寸的,转换之后的图片也是大尺寸的,这显然不符合我们实际项目中的需求.于是我对里面介绍的第一种方法做了一番改进,使其能直接在XML中指定图片的大小.

##大体步骤

  1. 将原图居中裁剪成正方形
  2. 根据指定的宽度对正方形进行缩放
  3. 裁剪成圆形

##效果

##代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
package com.demos.tencent_qq_ui.CustomerView;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.widget.ImageView;
/**
* Created by mummyding on 15-8-7.
*/
public class AvatarImageView extends ImageView {
private Paint paint = new Paint();
public AvatarImageView(Context context) {
super(context);
}
public AvatarImageView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public AvatarImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
//将头像按比例缩放
private Bitmap scaleBitmap(Bitmap bitmap){
int width = getWidth();
//一定要强转成float 不然有可能因为精度不够 出现 scale为0 的错误
float scale = (float)width/(float)bitmap.getWidth();
Matrix matrix = new Matrix();
matrix.postScale(scale, scale);
return Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
}
//将原始图像裁剪成正方形
private Bitmap dealRawBitmap(Bitmap bitmap){
int width = bitmap.getWidth();
int height = bitmap.getHeight();
//获取宽度
int minWidth = width > height ? height:width ;
//计算正方形的范围
int leftTopX = (width - minWidth)/2;
int leftTopY = (height - minWidth)/2;
//裁剪成正方形
Bitmap newBitmap = Bitmap.createBitmap(bitmap,leftTopX,leftTopY,minWidth,minWidth,null,false);
return scaleBitmap(newBitmap);
}
@Override
protected void onDraw(Canvas canvas) {
Drawable drawable = getDrawable();
if (null != drawable) {
Bitmap rawBitmap =((BitmapDrawable)drawable).getBitmap();
//处理Bitmap 转成正方形
Bitmap newBitmap = dealRawBitmap(rawBitmap);
//将newBitmap 转换成圆形
Bitmap circleBitmap = toRoundCorner(newBitmap, 14);
final Rect rect = new Rect(0, 0, circleBitmap.getWidth(), circleBitmap.getHeight());
paint.reset();
//绘制到画布上
canvas.drawBitmap(circleBitmap, rect, rect, paint);
} else {
super.onDraw(canvas);
}
}
private Bitmap toRoundCorner(Bitmap bitmap, int pixels) {
//指定为 ARGB_4444 可以减小图片大小
Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_4444);
Canvas canvas = new Canvas(output);
final int color = 0xff424242;
final Rect rect = new Rect(0, 0,bitmap.getWidth(), bitmap.getHeight());
paint.setAntiAlias(true);
canvas.drawARGB(0, 0, 0, 0);
paint.setColor(color);
int x = bitmap.getWidth();
canvas.drawCircle(x / 2, x / 2, x / 2, paint);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
canvas.drawBitmap(bitmap, rect, rect, paint);
return output;
}
}

然后就可以直接像其他View一样直接在XML中使用了.例如

1
2
3
4
5
6
<com.demos.tencent_qq_ui.CustomerView.AvatarImageView
android:layout_width="96dip" <!--可自行指定大小-->
android:layout_height="96dip"
android:layout_centerHorizontal="true"
android:src="@drawable/avatar" <!--这里放图片-->
/>

这样,在界面上显示的图像就是圆形的了. 不过我这里还有一个不足的地方是没有检查原图片的大小,如果你放一张高清的图片,那就很可能crash 掉.对于这点,我目前的解决方法就是 Google 官方教程里的 Loading
Large Bitmaps Efficiently
但它的原理就是先不不把图片加载进来,而是先根据原图的大小计算缩放值,然后在根据缩放值读取图片(算是在读取的时候进行压缩吧….).但是这个方法需要提供视图ID,也就是说要给AvatarImageView 指定一个ID,然后一个AvatarImageView 要对应一个视图(我是这么理解的) 这样的话AvatarImageView就无法重用了.当项目中多处要用到这个的话就会很麻烦.
为此我在stackoverflow提了一个问,但是目前还没有人回答T_T How
to make bitmap(set in src) compress?

【转载请注明出处】
Author: MummyDing

Contents
|