Android仿QQ圆形头像个性名片
作者:cj_286 发布时间:2021-08-24 02:40:46
标签:Android,QQ,圆形头像,个性名片
先看看效果图:
中间的圆形头像和光环波形讲解请看:https://www.jb51.net/article/96508.htm
周围的气泡布局,因为布局RatioLayout是继承自ViewGroup,所以布局layout就可以根据自己的需求来布局其子view,view.layout(int l,int t,int r,int b);用于布局子view在父ViewGroup中的位置(相对于父容器),所以在RatioLayout中计算所有子view的left,top,right,bottom。那么头像的周围的气泡view是如何计算它的left,top,right,bottom的呢,这些气泡view是坐落在头像外围的圆环上,只要知道这个圆环的半径,然后再根据气泡的个数,计算每个气泡之间的角度,半径加角度就可以计算每个气泡坐落的位置。
/**
* 计算气泡的布局位置
* @param textViews
*/
private void calculateRatioFrame(List<BubbleView> 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的偏移量,
//int r = mMinSize / 6 / 2;//气泡半径
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;
}
}
计算好气泡的布局left, top, right,bottom,下面就开始布局这起气泡,布局中的代码就简单的多了
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
if(mImageView == null) return;
int width = mImageView.getMeasuredWidth();//计算圆形头像的宽
int height = mImageView.getMeasuredHeight();//计算圆形头像的高
//计算圆形头像的left, top, right,bottom
int left = mWidth / 2 - width / 2;
int top = mHeight / 2 - height / 2;
int right = mWidth / 2 + width / 2;
int bottom = mHeight / 2 + height / 2;
//开始布局
mImageView.layout(left,top,right,bottom);
//布局爱心动画
for (int i = 0; i < mLoveXinList.size(); i++) {
ImageView imageView = mLoveXinList.get(i);
left = mWidth / 2 + width / 4 - imageView.getMeasuredWidth() / 2;
bottom = mHeight / 2 + height / 3;
top = bottom - imageView.getMeasuredHeight();
right = left + imageView.getMeasuredWidth();
imageView.layout(left,top,right,bottom);
}
//布局所有气泡
for (int i = 0; i < mTextViews.size(); i++) {
TextView textView = mTextViews.get(i);
//RatioFrame ratioFrame = mRatioFrameList.get(i);//无动画时使用
//有动画的时候,执行期间left, top, right,bottom都在变
if(mCurrentRatioFrameList != null){
//ValueAnimator执行动画是所产生的所有气泡left, top, right,bottom
RatioFrame ratioFrame = mCurrentRatioFrameList.get(i);
textView.layout(ratioFrame.mLeft,ratioFrame.mTop,ratioFrame.mRight,ratioFrame.mBottom);
}
}
}


猜你喜欢
- CyclicBarrier是什么CyclicBarrier是Java并发包中提供的一种同步工具类,它可以让多个线程在某个屏障处等待,直到所有
- 一、内部类1.内部类的概念内部类是定义在类中的类。内部类把逻辑上相关的类放在一起。而有的内部类不会在其他地方用到,它没有类名,在定义的时候就
- 概述从今天开始, 小白我将带大家开启 Jave 数据结构 & 算法的新篇章.栈栈 (Stack) 是一种运算受限的线性表, 遵循先进
- C# 反射(Reflection)反射指程序可以访问、检测和修改它本身状态或行为的一种能力。程序集包含模块,而模块包含类型,类型又包含成员。
- 前言内存治理一直是每个开发者最关心的问题,我们在日常开发中会遇到各种各样的内存问题,比如OOM,内存泄露,内存抖动等等,这些问题都有以下共性
- 本文实例为大家分享了java使用influxDB数据库的具体代码,供大家参考,具体内容如下1.pom.xml中导入jar包依赖<!--
- 问题:最近在项目中遇到,不同客户机安装不同Office版本,在导出Excel时,发生错误。找不到Excel Com组件,错误信息如下。&nb
- 在Java5.0之前,只有synchronized(内置锁)和volatile. Java5.0后引入了显示锁ReentrantLock.R
- 目录前言实现思路实测前言需求 导出Excel:本身以为是一个简单得导出,但是每行得记录文件中有一列为图片url,需要下载所有记录行对应得图片
- Intellij Idea打包Java项目打开模块设置如下图所示,选中需要打包的模块,右键点击,即会出现如下图所示的内容,点击Open Mo
- 本例是利用C#中的性能计数器(PerformanceCounter)监控网络的状态。并能够直观的展现出来涉及到的知识点:Performanc
- Kotlin的控制流与其他语言一样,顺序,分支,循环顺序语句就不多说,分支有两种,if-else和when(类似于Java中的switch)
- 一、reservedcodecachesize参数介绍该参数是JvM虚拟机调优中调整内存大小的一个设置参数,值得大小设置直接影响到Code
- 最近做的一个小项目中有这样的需求:整个项目有一份config.json保存着项目的一些配置,是存储在本地文件的一个资源,并且应用中存在读写(
- starter起步依赖starter起步依赖是springboot一种非常重要的机制,它打包了某些场景下需要用到依赖,将其统一集成到star
- 题目一链表题——链表合并根据给定的两个升序链表合并为一个新的升序链表具体题目如下解法/** * Definition for singly-
- 参考链接IDEA 2020.2.3版本IntelliJ IDEA 2020.2.3永久激活码(亲测有效)IDEA 2019.3版本Intel
- 以下实例演示了如何使用 equals ()方法来判断数组是否相等:import java.util.Arrays; public class
- 下拉刷新在越来越多的App中使用,已经形成一种默认的用户习惯,遇到列表显示的内容时,用户已经开始习惯性的拉拉。在交互习惯上已经形成定性。之前
- 做个网站的安卓客户端,用户安装到自己手机上,如果我出了新版本怎么办呢?要有版本更新功能。 本来版本检测最好可以自动进行。但如果每次开启程序,