前些天看到网上有个仿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. ubuntu 在firefox,网页听不了音乐
  2. xlsxwriter写行合并_使用xlsxwriter将pandas数据框写入excel并包含“write-rich”字符串格式...
  3. oracle安装及使用常见错误
  4. 编译其他mysql客户程_mysql编译模块
  5. thinking-in-java(20)注解
  6. bootstrap基础学习十篇
  7. 2038: [2009国家集训队]小Z的袜子(hose)
  8. 从月薪2300女工到年薪70万谷歌程序员:人生,永远不要给自己设限
  9. “夺笋呐”!会员隐私随便看 诈骗就当没看见,中国最大婚恋网站紧急回应
  10. spring集成web
  11. [翻译]CryEngine3中光照的美术提示
  12. c语言不用的行参警告,如何在C语言中禁止“未使用的参数”警告?
  13. 改善程序与设计的55个具体做法 day5
  14. C语言十六进制大小端转换,大小端转换(一篇文章了解所有情况下的大小端转换方法)...
  15. C盘没W ndows64,win10如何深度清理c盘
  16. 前端面试谈:项目经历的 STAR 法则
  17. 免费高清可商用图片素材站推荐
  18. 网页打开慢的原因及分析
  19. cocos2dx游戏中添加背景音乐、音效
  20. 我的创作纪念日(3周年)

热门文章

  1. scss文件转css文件
  2. 在线教育“水逆”,猿辅导、作业帮们如何“捞偏门”
  3. AI或PS导出cmyk模式的JPEG或jpg图转rgb模式的图jpeg或jpg然后压缩图片
  4. tick_init();
  5. form表单的onsubmit事件中调用方法时为什么前面加return
  6. java数据结构YZP专栏-----链表
  7. 网络变压器原理:网络、频谱、阻抗分析仪检测网络变压器等电子元器件阻抗的方法
  8. 语言C++之简单C++语言介绍
  9. vivo手机总是发烫,教你这样设置,瞬间降温
  10. java毕业生设计众筹平台网站计算机源码+系统+mysql+调试部署+lw