文档章节

手机QQ5.0红点拖拽消除的实现

chenupt
 chenupt
发布于 2015/01/12 10:15
字数 952
阅读 95
收藏 2

新版手机QQ5.+上新增了一种“一键退朝”的功能,即在页面上的红点可进行拖拽消除。在[知乎](http://www.zhihu.com/question/26382740)上可参考红点的设计过程。按照设计思路在Android上模仿手Q实现下拖拽的过程。

代码地址:https://github.com/chenupt/BezierDemo


效果图:




整体的思路,封装好一个view。在界面上找到四个点,即框出手势拖动点与红点之间的范围,利用贝塞尔曲线修饰边框,计算红点和手势拖动点间的距离,判断红点的消除与回弹。
借用下设计图:


首先确定以红点为坐标原点,在坐标上所要计算的就是p1, p2, p3, p4四个点,其中..为贝塞尔曲线,在p1p2和p3p4之间需要绘制半径为R和r的圆。


接下来需要的就是在拖动过程中计算(0,0)和(x0, y0)两点间的距离,通过距离控制贝塞尔曲线的弧度和圆的大小,实现模拟现实生活中弹性效果。

在代码中通过Path来控制p1, p2, p3, p4四个点所围成的范围,并填充相应地色值:

1.确定四个点,这里简单地将两个圆起始半径设置相等

        float x1 = startX - offsetX;
        float y1 = startY + offsetY;

        float x2 = x - offsetX;
        float y2 = y + offsetY;

        float x3 = x + offsetX;
        float y3 = y - offsetY;

        float x4 = startX + offsetX;
        float y4 = startY - offsetY;

        path.reset();
        path.moveTo(x1, y1);
        path.quadTo(anchorX, anchorY, x2, y2);
        path.lineTo(x3, y3);
        path.quadTo(anchorX, anchorY, x4, y4);
        path.lineTo(x1, y1);

2.填充范围和绘制圆形:

canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.MULTIPLY);
canvas.drawPath(path, paint);
canvas.drawCircle(startX, startY, radius, paint);
canvas.drawCircle(x, y, radius, paint);

3.在调用super.onDraw(canvas);方法绘制在canvas层上面的消息点图标imageView
通过在代码中的onTouchEvent方法进行控制触摸点的相应位置,实现拖动的效果。

@Override
    public boolean onTouchEvent(MotionEvent event) {
        if(event.getAction() == MotionEvent.ACTION_DOWN){
            // 判断触摸点是否在tipImageView中
            Rect rect = new Rect();
            int[] location = new int[2];
            tipImageView.getDrawingRect(rect);
            tipImageView.getLocationOnScreen(location);
            rect.left = location[0];
            rect.top = location[1];
            rect.right = rect.right + location[0];
            rect.bottom = rect.bottom + location[1];
            if (rect.contains((int)event.getRawX(), (int)event.getRawY())){
                isTouch = true;
            }
        }else if(event.getAction() == MotionEvent.ACTION_UP || event.getAction() == MotionEvent.ACTION_CANCEL){
            isTouch = false;
            tipImageView.setX(startX - tipImageView.getWidth()/2);
            tipImageView.setY(startY - tipImageView.getHeight()/2);
        }
        invalidate();
        if(isAnimStart){
            return super.onTouchEvent(event);
        }
        anchorX =  (event.getX() + startX)/2;
        anchorY =  (event.getY() + startY)/2;
        x =  event.getX();
        y =  event.getY();
        return true;
    }

4.拖动过程中计算两个圆心之间的距离,通过圆心间的距离调整圆心为(0, 0)圆的半径大小

float distance = (float) Math.sqrt(Math.pow(y-startY, 2) + Math.pow(x-startX, 2));
radius = -distance/15+DEFAULT_RADIUS;

用新的半径去绘制(0, 0)的圆,这样随着距离的增加,圆相应变小就给人如同快要沾不住黏黏的感觉。

5.距离超过设定的最大范围,则设置为红点挣脱状态,如果手指抬起,则开始播放相应爆炸动画。

exploredImageView.setVisibility(View.VISIBLE);
exploredImageView.setImageResource(R.drawable.tip_anim);
((AnimationDrawable) exploredImageView.getDrawable()).stop();
((AnimationDrawable) exploredImageView.getDrawable()).start();


6.在Activity布局中引用相应封装好的view即可。

<github.chenupt.bezier.BezierView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@android:color/transparent" />



最开始设想的view在类似于红点范围的一个控件,但是这样实现就达不到拖动到父类控件的范围之外,比如拖动红点超过页签布局范围时,红点则无法绘制。因此在QQ的消息列表中是将其设置相应全屏的一个view。背景为截图的上个背景,这样在最上一层实则只有红点的控件。这样就能相应地拖动红点到屏幕的各个位置。所以才会在红点列表爆照动画结束之前页签是不可点击,并且拖动红点的时候列表数据没有刷新。

也许是还有更好地实现方式,欢迎大家进行交流。


代码地址:https://github.com/chenupt/BezierDemo

QQ: 753785666

微博: chenupt

Email:chenupt@gmail.com


© 著作权归作者所有

chenupt
粉丝 1
博文 1
码字总数 952
作品 0
南京
私信 提问
可拖拽的红点--DraggableFlagView

可拖拽的红点,(仿新版QQ,tab下面拖拽标记为已读的效果),拖拽一定的距离可以消失回调。 实现原理: 当根据touch事件的移动,不断调用onDraw()方法进行刷新绘制。 *注意:这里原来的小红点...

咕噜不爱猫
2014/12/25
3K
1
Android 仿QQ界面中未读消息如何实现?

QQ5.0以后支持未读消息数拖拽,就是在未读消息边出现一个小红点有数字,然后可以全屏幕拖拽,拖拽到一定程度可以认为已读,请问这个全屏拖拽如何实现?我重写控件可以实现拖拽,但是在ListView中超...

Lohanry
2014/10/21
6.3K
2
Android 拖拽控件--DragIndicatorView

带拖拽效果的红点提示控件 DragIndicatorView。 可以通过拖拽消失的小红点提示 DragIndicatorView扩展自TextView 可当成普通TextView使用 手动触发红点消失: mDragIndicatorView.dismissVie...

siwangqishiq
2016/04/07
912
0
前端日刊君来也

每天努力的日刊君 - 2017.11.22 The Next Day is Always a New Day 拖拽粘性小红球 Canvas 实现 web图像常见的应用策略与技巧 70%以上业务由H5开发,手机QQ Hybrid 的架构如何优化演进? 来自...

前端新视野
2017/11/23
0
0
canvas图形编辑器

原文地址:http://jeffzhong.space/2017/11/02/drawboard/ 使用canvas进行开发项目,我们离不开各种线段,曲线,图形,但每次都必须用代码一步一步去实现,显得非常麻烦。有没有一种类似于P...

Jeff.Zhong
2017/11/06
0
0

没有更多内容

加载失败,请刷新页面

加载更多

如何编写高质量的 JS 函数(1) -- 敲山震虎篇

本文首发于 vivo互联网技术 微信公众号 链接:https://mp.weixin.qq.com/s/7lCK9cHmunvYlbm7Xi7JxQ 作者:杨昆 一千个读者,有一千个哈姆雷特。 此系列文章将会从函数的执行机制、鲁棒性、函...

vivo互联网技术
56分钟前
5
0
学会这5个Excel技巧,让你拒绝加班

在网上,随处都可以看到Excel技巧,估计已看腻了吧?但下面5个Excel技巧会让你相见恨晚。关键的是它们个个还很实用 图一 技巧1:快速删除边框 有时当我们处理数据需要去掉边框,按Ctrl+Shif...

干货趣分享
今天
11
0
JS基础-该如何理解原型、原型链?

JS的原型、原型链一直是比较难理解的内容,不少初学者甚至有一定经验的老鸟都不一定能完全说清楚,更多的"很可能"是一知半解,而这部分内容又是JS的核心内容,想要技术进阶的话肯定不能对这个...

OBKoro1
今天
10
0
高防CDN的出现是为了解决网站的哪些问题?

高防CDN是为了更好的服务网络而出现的,是通过高防DNS来实现的。高防CDN是通过智能化的系统判断来路,再反馈给用户,可以减轻用户使用过程的复杂程度。通过智能DNS解析,能让网站访问者连接到...

云漫网络Ruan
今天
15
0
OSChina 周一乱弹 —— 熟悉的味道,难道这就是恋爱的感觉

Osc乱弹歌单(2019)请戳(这里) 【今日歌曲】 @xiaoshiyue :好久没分享歌了分享张碧晨的单曲《今后我与自己流浪》 《今后我与自己流浪》- 张碧晨 手机党少年们想听歌,请使劲儿戳(这里)...

小小编辑
今天
3.3K
25

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部