前些天看到网上有个仿qq气泡的效果看了看也不难 今天来自己实现一下

效果图

其实很简单就是一个绘制过程 用到了插补器 OvershootInterpolator

public class BubbleView extends View {private Paint mPaint;//画笔private int mMeasuredHeight;//控件高private int mMeasuredWidth;//控件宽private PointF mStaticPointF;//不动点的坐标private PointF mMovePointF;//移动点的坐标private double mLineK;//斜率private static final float RADIUS = 30; //初始化的半径大小private double mStaticRadius; //绘制时用到的半径//能够拖动的最大值private static final float MAX_DISTANCE = 300;private Path path;//是否超出过最大范围private boolean mIsOutOfRange = false;public BubbleView(Context context) {super(context);init();}public BubbleView(Context context, AttributeSet attrs) {super(context, attrs);init();}public BubbleView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);init();}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);mMeasuredHeight = getMeasuredHeight();mMeasuredWidth = getMeasuredWidth();mStaticPointF.set(mMeasuredWidth / 2, mMeasuredHeight / 2);mMovePointF.set(mMeasuredWidth / 2, mMeasuredHeight / 2);}private void init() {mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);mPaint.setColor(getResources().getColor(android.R.color.holo_red_light));mStaticPointF = new PointF(mMeasuredWidth / 2, mMeasuredHeight / 2);mMovePointF = new PointF(mMeasuredWidth / 2, mMeasuredHeight / 2);mStaticRadius = RADIUS;mStaticPointF = new PointF(mMeasuredWidth / 2, mMeasuredHeight / 2);mMovePointF = new PointF(mMeasuredWidth / 2, mMeasuredHeight / 2);path = new Path();}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);//重置pathpath.reset();if (!mIsOutOfRange) {canvas.drawCircle(mStaticPointF.x, mStaticPointF.y, (float) mStaticRadius, mPaint);float dx = mMovePointF.x - mStaticPointF.x;float dy = mMovePointF.y - mStaticPointF.y;if (dx != 0) {mLineK = dy / dx;}PointF[] staticPoints = GeometryUtil.getIntersectionPoints(mStaticPointF, (float)mStaticRadius, mLineK);PointF[] movePoints = GeometryUtil.getIntersectionPoints(mMovePointF, 30, mLineK);PointF controlPoint = GeometryUtil.getPointByPercent(mStaticPointF, mMovePointF, 0.5f);path.moveTo(staticPoints[0].x, staticPoints[0].y);path.lineTo(staticPoints[1].x, staticPoints[1].y);path.quadTo(controlPoint.x, controlPoint.y, movePoints[1].x, movePoints[1].y);path.lineTo(movePoints[0].x, movePoints[0].y);path.quadTo(controlPoint.x, controlPoint.y, staticPoints[0].x, staticPoints[0].y);canvas.drawPath(path, mPaint);path.close();}canvas.drawCircle(mMovePointF.x, mMovePointF.y, 30, mPaint);}/*** 根据两圆的距离 计算中心固定圆半径* @param distance 两圆的距离*/private void getStaticRadius(float distance) {mStaticRadius = RADIUS * (0.8 * (MAX_DISTANCE - distance) / MAX_DISTANCE + 0.2);}@Overridepublic boolean onTouchEvent(MotionEvent event) {float distance = GeometryUtil.getDistanceBetween2Points(mStaticPointF, mMovePointF);switch (event.getAction()) {case MotionEvent.ACTION_DOWN:case MotionEvent.ACTION_MOVE:float dx = event.getX();float dy = event.getY();mMovePointF.set(dx, dy);if (distance > MAX_DISTANCE) {distance = MAX_DISTANCE;mIsOutOfRange = true;} else {}getStaticRadius(distance);break;case MotionEvent.ACTION_UP:if (distance > MAX_DISTANCE) {} else {if (mIsOutOfRange) {mMovePointF.set(mStaticPointF);mIsOutOfRange = false;} else {mIsOutOfRange = false;ValueAnimator valueAnimator = ObjectAnimator.ofFloat(1);final PointF startPointF = new PointF(mMovePointF.x, mMovePointF.y);valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {@Overridepublic void onAnimationUpdate(ValueAnimator valueAnimator) {//获得动画执行的百分比float animatedFraction = valueAnimator.getAnimatedFraction();PointF pointByPercent = GeometryUtil.getPointByPercent(startPointF, mStaticPointF, animatedFraction);mMovePointF.set(pointByPercent);float distance = GeometryUtil.getDistanceBetween2Points(mStaticPointF, mMovePointF);getStaticRadius(distance);invalidate();}});valueAnimator.setDuration(500);//添加一个插补器 OvershootInterpolatorvalueAnimator.setInterpolator(new OvershootInterpolator(3));valueAnimator.start();}}break;}invalidate();return true;}}

github https://github.com/REIGE/BubbleView

仿qq气泡通知粘连效果相关推荐

  1. java 气泡聊天消息_Java Swing实现的仿QQ气泡消息聊天窗口效果

    下面讲讲聊天窗口的上半部分聊天消息显示区域的具体实现,尤其是气泡的绘制.图文的混排实现. 先讲讲气泡的实现思路.开始我想过很多气泡的实现方法,在研究了JTextPane的文档类及其内容插入删除排版后, ...

  2. Android仿QQ消息拖拽效果(二)

    前言 本文参考辉哥贝塞尔曲线 - QQ消息汽包拖拽,前面我们使用二阶贝塞尔曲线绘制了拖拽圆点效果Android仿QQ消息拖拽效果(一)(二阶贝塞尔曲线使用),这里我们在此基础之上实现仿QQ消息拖拽爆炸 ...

  3. 自定义View | 仿QQ运动步数进度效果

    项目GitHub地址 思路 固定不动的蓝色大圆弧 动画变动的红色小圆弧 中间的步数文字显示 相关的自定义属性 比如固定不动的大圆弧, 我们不能写死他的蓝色颜色属性, 要提供一个颜色的自定义属性给用户自 ...

  4. 自定义View之仿QQ运动步数进度效果

    前言 今天接着上一篇来写关于自定义View方面的东西,我是近期在学习整理这方面的知识点,所以把相关的笔记都放到这个Android自定义View的专栏里了,方便自己下次忘记的时候能回来翻翻,今天的内容是 ...

  5. android开发之仿QQ拖拽界面效果(侧滑面板)

    仿QQ拖拽界面效果(侧滑面板),我们一般继承Layout,不会直接去继承ViewGroup,而是继承FrameLayout,为什么五大布局我们偏偏只继承FrameLayout呢? 第一,FrameLa ...

  6. qq秀源码 php,JavaScript_js实现仿QQ秀换装效果的方法,本文实例讲述了js实现仿QQ秀换 - phpStudy...

    js实现仿QQ秀换装效果的方法 本文实例讲述了js实现仿QQ秀换装效果的方法.分享给大家供大家参考.具体实现方法如下: 仿QQ秀换装效果 #cs img{cursor:hand} var obj=ev ...

  7. iOS之仿QQ点赞按钮粒子效果的实现

    效果展示 具体流程 一.封装YDWLikeButton 新建一个YDWLikeButton继承于UIButton,然后声明一个属性: @property (nonatomic, strong) CAE ...

  8. Android自定义View之仿QQ运动步数进度效果

    文章目录 前言 先看效果图 ![在这里插入图片描述](https://img-blog.csdnimg.cn/6e4ddec17933496ea4830fa08d8ffbe5.png?x-oss-pr ...

  9. android 自定义view实现仿QQ运动步数进度效果

    最近公司在策划一个新的项目,原型还没出来,再说这公司人都要走没了,估计又要找工作了,所以必须要学习,争取每个写个关于自定义view方面的,这样几个月积累下来,也能学习到东西,今天就带来简单的效果,就是 ...

最新文章

  1. Ibatis in action 电子书
  2. SM$TS_USED,SM$TS_FREE,SM$TS_AVAIL
  3. 这应该是你见过的最全前端下载总结
  4. [原]JS ajax类的三种封装形式及简单对比
  5. Linux文件系统保存在哪里,文件系统保存在磁盘的()
  6. 第29天:控制进度,控制进度知识点,敏捷中控制进度知识点
  7. java并行流 阻塞主线程_多线程入门案例与java8的并行流
  8. cf1552F. Telepanting
  9. 2022年中国开源软件产业研究报告
  10. JAVA中的MDC类_CMake - 用/ MT而不是/ MD编译
  11. Deeper Network将于明日启动DPR/USDC流动性质押第三季
  12. 凤凰系统基于android x x86,凤凰系统X86|Phoenix OS X86 V3.0.8.529官方版
  13. 第四届CSTQB®国际软件测试高峰论坛
  14. ubuntu使用双模机械师K7机械键盘遇到的问题
  15. iOS load和initialize方法详解
  16. Flex to Excel or Excel to Flex
  17. mac m1 esc键失灵
  18. PyTorch深度学习入门笔记(五)Transforms的使用
  19. 贝叶斯网络、拉普拉斯平滑
  20. 相约,一朵春天的微笑

热门文章

  1. 预产期计算器在线计算生男生女计算机,预产期计算器生男生女,太准了
  2. 文墨绘学二十种心里调节措施
  3. 11.JavaScript分支语句if、else、elseif、三目运算符
  4. Flutter CustomScrollView使用介绍
  5. 【Python】**kwargs
  6. 鸿蒙和IPADOS,ios13和iPadOS来了,再加上华为鸿蒙OS和方舟编译器,你宠谁?
  7. 利用go执行nmap命令
  8. 我大学是如何赚零花钱的
  9. 首先下载安装data.table包_自从用了这个表情包制作工具,斗图再也没输过
  10. 当孩子的语言伤害了家人以后,家长怎么做?——与九迁谈亲情,友情的对话...