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圆形头像个性名片”的内容,你了解清楚吗?希望对你有所帮助,任何问题可以给我留言,让我们下期再见吧。