Android仿QQ圆形头像个性名片

一、引言
在移动应用开发中,用户界面(UI)设计是吸引用户和提升用户体验的关键因素之一,圆形头像作为一种简洁且具有视觉吸引力的设计元素,被广泛应用于各类社交应用中,如QQ,本文将详细介绍如何在Android平台上实现仿QQ的圆形头像个性名片,包括圆形头像的绘制、光环波形的设计以及气泡布局的定制。
二、圆形头像的实现
使用BitmapShader类
在Android中,可以使用BitmapShader类来创建圆形图片。BitmapShader允许我们将位图应用于画笔,然后通过设置Shader的模式为SHADER_TYPE_CIRCLE(即Shader.TileMode.CLAMP),可以将位图的边缘平滑地扩展到圆形,我们需要使用Paint对象来绘制这个圆形图片,并确保Paint的抗锯齿属性开启。
示例代码:

public class CircleClipView extends ImageView {
private Paint backgroundPaint = null;
private Paint maskPaint = null;
private int backgroundColor = 1;
public CircleClipView(Context context) {
super(context);
init();
}
public CircleClipView(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.circleview);
backgroundColor = a.getColor(R.styleable.circleview_backgroundcolor, Color.WHITE);
a.recycle();
init();
}
private void init() {
maskPaint = new Paint();
PorterDuffXfermode porterDuffXfermode = new PorterDuffXfermode(PorterDuff.Mode.SRC_IN);
maskPaint.setXfermode(porterDuffXfermode);
maskPaint.setColor(Color.TRANSPARENT);
maskPaint.setAntiAlias(true);
backgroundPaint = new Paint();
backgroundPaint.setColor(backgroundColor);
backgroundPaint.setAntiAlias(true);
}
private Bitmap getMask() {
Bitmap b = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(b);
RectF rectF = new RectF(0, 0, getWidth(), getHeight());
canvas.drawRect(rectF, backgroundPaint);
canvas.drawOval(rectF, maskPaint);
return b;
}
@Override
protected void onDraw(Canvas canvas) {
Bitmap sourceBitmap = scaleDrawable(getDrawable());
if (sourceBitmap != null) canvas.drawBitmap(sourceBitmap, 0, 0, null);
canvas.drawBitmap(getMask(), 0, 0, null);
}
private Bitmap scaleDrawable(Drawable drawable) {
Bitmap b = ((BitmapDrawable) drawable).getBitmap();
Matrix matrix = new Matrix();
float scaleWidth = ((float) getWidth()) / b.getWidth();
float scaleHeight = ((float) getHeight()) / b.getHeight();
matrix.postScale(scaleWidth, scaleHeight);
Bitmap bitmap = Bitmap.createBitmap(b, 0, 0, b.getWidth(), b.getHeight(), matrix, true);
return bitmap;
}
}
2. 自定义ViewGroup实现气泡布局
为了实现类似QQ的个性名片效果,我们可以自定义一个RatioLayout继承自ViewGroup,它允许开发者根据特定的比例关系来布局子视图,在计算每个气泡的位置时,需要知道圆环的半径,然后根据气泡的总数计算它们之间的角度间隔,如果有12个气泡,那么每个气泡之间相差30°,利用三角函数计算出每个气泡相对于圆心的坐标,然后调用view.layout()方法设置它们的位置。
示例代码:
private void calculateRatioFrame(List<TextView> textViews) {
if (textViews.size() == 0) return;
mRatioFrameList.clear();
double angle = 0; // 记录每个气泡的角度,正上方的为0°
double grad = Math.PI * 2 / textViews.size(); // 梯度,每个TextView之间的角度 (Math.PI 是数学中的90°)
double rightAngle = Math.PI / 2; // 一圈为360°,一共四个方向,每个方向90°,我们按照小于等于90°来计算,然后再放到相应的方向上
// cx,cy是容器的中心点,也是圆形头像的中心点,计算气泡的位置就是已cx,cy为基准来计算的
int cx = mWidth / 2; // 容器中心x坐标
int cy = mHeight / 2; // 容器中心y坐标
int radius = mMinSize / 2 / 2 / 2 + mMinSize / 2 / 2; // 动态气泡的组成圆的半径
int left = 0;
int top = 0;
int right = 0;
int bottom = 0;
int a = 0, b = 0; // a是基于cx的偏移量,b是基于cy的偏移量,
for (int i = 0; i < textViews.size(); i++) {
int r = textViews.get(i).getMeasuredWidth() / 2; // 计算得来 //固定死的mMinSize / 6 / 2; //气泡半径
if (angle >= 0 && angle < rightAngle) { // 0 90度是计算偏移量
// 保持角度在 0 90
a = (int) (radius * Math.sin(Math.abs(angle % rightAngle)));
b = (int) (radius * Math.cos(Math.abs(angle % rightAngle)));
left = cx + a r; // cx + a为气泡的中心点,要想得到left,还需减去半径r
top = cy b r;
right = left + 2 * r;
bottom = top + 2 * r;
} else if (angle >= rightAngle && angle < rightAngle * 2) { // 90 180
a = (int) (radius * Math.sin(Math.abs(angle % rightAngle)));
b = (int) (radius * Math.cos(Math.abs(angle % rightAngle)));
left = cx + b r;
top = cy + a r;
right = left + 2 * r;
bottom = top + 2 * r;
} else if (angle >= rightAngle * 2 && angle < rightAngle * 3) { // 180 270
a = (int) (radius * Math.sin(Math.abs(angle % rightAngle)));
b = (int) (radius * Math.cos(Math.abs(angle % rightAngle)));
left = cx a r;
top = cy + b r;
right = left + 2 * r;
bottom = top + 2 * r;
} else if (angle >= rightAngle * 3 && angle < rightAngle * 4) { //270 360
a = (int) (radius * Math.sin(Math.abs(angle % rightAngle)));
b = (int) (radius * Math.cos(Math.abs(angle % rightAngle)));
left = cx b r;
top = cy a r;
right = left + 2 * r;
bottom = top + 2 * r;
}
// 将计算好的left, top, right,bottom,angle保存起来
mRatioFrameList.add(new RatioFrame(left, top, right, bottom, angle));
// 角度再加一个梯度值
angle += grad;
}
}
三、光环波形设计
光环波形通常涉及到自定义视图和动画效果,我们可以创建一个自定义的View,在其onDraw()方法中绘制光环,可以使用Path对象描绘波形路径,然后利用Paint的setShader()方法结合LinearGradient或RadialGradient来实现颜色过渡效果,为了创建动态的光环波形,可以使用ValueAnimator或ObjectAnimator来改变Path的形状参数,从而实现波形的流动效果。

四、归纳与展望
通过上述步骤,我们可以在Android应用中实现一个仿QQ风格的圆形头像个性名片,这不仅提升了应用的视觉效果,也增强了用户的交互体验,随着技术的发展和用户需求的变化,我们可以进一步优化这一功能,例如增加更多的个性化选项、支持更复杂的动画效果等。
小伙伴们,上文介绍了“Android仿QQ圆形头像个性名片”的内容,你了解清楚吗?希望对你有所帮助,任何问题可以给我留言,让我们下期再见吧。












