仿QQ消息拖拽,让你的View动起来

前言

​ 玩过QQ的人应该都不会对QQ消息的小红点陌生吧。在我们的实际应用开发中有时候也是会遇到这种消息拖拽消失的需求。这时我们要么自己造轮子,要么去Google找轮子。而我们在网上找的轮子呢,大部分都是自定义View然后这个View支持拖动,是一个死的轮子。

​ 而今天,我们就是要改变现状,让我们的轮子转起来,写一个工具类,只要用这个工具类那么你的所有的View就都可以动起来,进行拖拽。而不是写死在View内部。有没有觉得很帅?!快鼓掌


效果图

挽起袖子,撸起来!


第一步 让点动起来

​ 在这里我们实现的功能非常简单,就是我们自定义view,在这个View中当我们按下手指的时候,会画两个红点,这两个红点最开始是重合的,当我们移动手指的时候,一个红点随着我们的手指移动,而另一个红点,则随着我们手指移动的距离越远半径而变得越来越小,知道这个半径等于0,不再画这个红点为止。

​ 这一步应该是比较容易的,就不写代码了,了解了思路是最重要的,如果你看到这里就懵逼了,那么我不建议你往下看了,这可能对你来说比较难了,我建议你去看一点自定义View的基础之后再来看本文章。

第二步 添加贝塞尔曲线

​ 我们看QQ消息的拖拽,控件与红色圆点之间并不是空白的,而是有填充的,而且不是直线填充,是有两条曲线的,给人非常舒服的感觉,没错,这两条曲线就是贝塞尔曲线

​ 对于普通的二阶贝塞尔曲线还是比较容易理解的,当然对于高阶我自己有时候也是懵逼的 =.=

​ 这里有一个比较好的贝塞尔曲线的游戏,可以去玩一玩

​ 如果要加入这两个曲线那么就需要找到二阶贝塞尔曲线的控制点和起始点,起始点就是两个圆的切线位置,控制点我们去黄金分割点。

贝塞尔分析

这个分析过程我们主要是求四个蓝色的起始点,会用到部分三角函数的知识,但是这应该都是初中的内容,我相信对各位都不是问题。
而控制点就更简单了,说就是dx和dy的黄金分割点0.618

Path bezier = new Path();

    float dx = mDragPoint.x - mFixedPoint.x;
    float dy = mDragPoint.y - mFixedPoint.y;
    float tanA = dy/dx;
    double A = Math.atan(tanA);

    float p1x = (float) (mFixedPoint.x + Math.sin(A)*mFixedRadius);
    float p1y = (float) (mFixedPoint.y - Math.cos(A)*mFixedRadius);

    float p2x = (float) (mDragPoint.x + Math.sin(A)*mDragRadius);
    float p2y = (float) (mDragPoint.y - Math.cos(A)*mDragRadius);

    float p3x = (float) (mDragPoint.x - Math.sin(A)*mDragRadius);
    float p3y = (float) (mDragPoint.y + Math.cos(A)*mDragRadius);

    float p4x = (float) (mFixedPoint.x - Math.sin(A)*mFixedRadius);
    float p4y = (float) (mFixedPoint.y + Math.cos(A)*mFixedRadius);

    float controlX = mFixedPoint.x + (mDragPoint.x-mFixedPoint.x)*GOLD_POINT;
    float controlY = mFixedPoint.y + (mDragPoint.y-mFixedPoint.y)*GOLD_POINT;

    bezier.moveTo(p1x,p1y);
    bezier.quadTo(controlX,controlY,p2x,p2y);
    bezier.lineTo(p3x,p3y);
    bezier.quadTo(controlX,controlY,p4x,p4y);
    bezier.close();

这是贝塞尔曲线的主要代码,应该也不难。

这个时候我们再把我们的程序运行起来,是不是有点样子了?这时候我们的工作已经做了一大半了 。

第三步 绑定View,实现轮子

​ 到目前位置,我们的程序还是和网上的轮子都差不多,写在自定义View里面。

​ 我们在BubbleView中添加一个静态的attach方法,将需要拖动的View传进去,然后把刚才重写的OnTouch给删了,是的你没看错,就是删了

​ 我们要做的第一件事就是在我们点击这个View的时候让这个View消失,是的你没看错,就是让它消失。此功能简单否?简单也!设置setVisibility(View.INVISIBLE)

​ 我们再分析一下其他功能,我们是要我们的View随便拖动,而不仅仅是在我们setContent的这个ViewGroup中,那么我就不能单纯的在我们设置的父布局中进行移动了,如果只是在设置的根布局中,局限性就很大了。
有没有好办法?,答案是肯定的,当然有,没有这个轮子不就毁了?
那是什么呢,就是我们大名鼎鼎的WindowManager,不用怕就是它,加在WindowManager上就可以让我们的视图随便拖动了,只要是你拖到的地方都行。

​ 所有的窗口行的应用都是用到了WindowManager,有兴趣的可以去研究一下

​ 我们在刚才点击这个View手指按下的时候已经让这个View不可见了,那么我们不要去操作他,而是去操作它的镜像,没错镜像。

public static Bitmap getBitmapByView(View view){
    view.buildDrawingCache();
    Bitmap bitmap = view.getDrawingCache();
    return  bitmap;
}

代码非常简单,那么手机的截屏你是不是也知道怎么弄了?写一个轮子试试吧!

同时,我们添加一个刚才我们写BubbleView。并将我们获得的这个镜像传递进去,是不是有思路了。对,就是让我们传入的这个bitmap随着刚才手指移动而移动,从而实现了我们View镜像的移动,对于用户来说我们的View就变得可拖动起来了。

这里我们定义两个监听接口,一个是用来监听拖动距离超出最大距离视图爆炸和小于最大最距离的时候,视图回弹。另一个是对视图消失的回调。

这里主要的思路,如果你的思路清楚了,那么一切都不是问题。

思想>CODING

当然这里面还是有许多的细节问题。但是大的思路明确了,小细节就是慢慢调了。比如,状态栏透明等小问题,还有状态栏的高度的加减问题,回弹动画,爆炸动画等。不过我相信这些都是小事了。

轮子

​ 当然,肯定有人会直接想要轮子的,来给你个轮子

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,716评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,558评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,431评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,127评论 0 209
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,511评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,692评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,915评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,664评论 0 202
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,412评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,616评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,105评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,424评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,098评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,096评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,869评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,748评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,641评论 2 271

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 170,569评论 25 707
  • 初春,乍暖还寒。生活区的桃花仿佛一夜之间都开了,在不经意间瞥见,意外的惊喜。 花瓶中…阳光下… 一个似浓妆艳抹,一...
    岚小汐阅读 379评论 2 1
  • 有些女孩天生豪迈至极,跟身边的异性勾肩搭背处成哥们,离结义就差滴血。跟同性处起来就像蕾丝,能温柔安抚受伤的闺蜜,也...
    小二麦阅读 364评论 0 1
  • 昨天是腊月初八。在我的记忆里,腊月初八是要吃腊八粥的。到现在我都不知道为什么要吃腊八粥,我一向对传统,对节日不是很...
    薇薇安的30天阅读 221评论 1 1
  • 找出文章重要的单字,五作者达成共识。这对于深层次阅读显得尤为重要。在我看来,这是决定了读者是否对一本书喜欢的关...
    Holly兔小妖阅读 253评论 0 0