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

新版手机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

Email:[email protected]

时间: 2024-08-25 19:47:13

手机QQ5.0红点拖拽消除的实现的相关文章

高仿手机QQ5.0界面框架

这次的手机QQ更新从客观的角度来说,还是很好的,更加简约,控件也自定义了,界面也有了大的改动,但是最主要的框架还是它的左右滑动机制.让我们先来看看它的效果. 可以看到它是从左到右的一个滑动方法菜单的方式,最主要的就是这个控件类的实现吧.其他的感觉都没什么太大的问题,下面我就来看看这种效果应该怎么来实现. 第一拿到东西先分析这个效果是怎么出来的.我仔细的看了一下主要应该注意这几点. 1:菜单的出现有个放大效果而且伴随着一个apha的效果 2:主要的内容面板上面就是一个缩放的动画 3:可以看到这个菜

iPhone手机解锁效果&amp;&amp;自定义滚动条&amp;&amp;拖拽--Clone&amp;&amp;窗口拖拽(改变大小/最小化/最大化/还原/关闭)

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-

ViewDragHelper实现QQ5.0侧滑并处理与ViewPager的滑动冲突

QQ5.0的侧滑效果有多种实现方式, 如http://blog.csdn.net/lmj623565791/article/details/39257409   就是利用HorizontalScrollView实现的,简单实用; 如http://blog.csdn.net/manoel/article/details/39013095/   通过改造SlidingMenu实现,没有改变原有SlidingMenu功能,屏幕边缘侧滑也可以.... 相对来说ViewDragHelper实现方式最为复杂

android ListView和GridView拖拽移位实现代码

关于ListView拖拽移动位置,想必大家并不陌生,比较不错的软件都用到如此功能了.如:搜狐,网易,百度等,但是相比来说还是百度的用户体验较好,不偏心了,下面看几个示例:             首先说一下:拖拽ListView的item就不应该可以任意移动,只应该在ListView所在的范围内,而网易的你看看我都可以移动到状态栏了,虽然你做了处理,但是用户体验我个人感觉不好,在看看百度的,不仅控制了移动范围,更不错的百度的移动起来会时时的换位,看起来相当的形象,所以我认为这样相当的棒.说明一点

(转)ViewDragHelper实现QQ5.0侧滑并处理与ViewPager的滑动冲突

最近在做项目,涉及到类似QQ的页面的滑动.但是却遇到了侧滑和ViewPager冲突的问题,头疼了很长时间,最后在网上发现了这篇博客,转载过来供自己学习参考(写这篇博客的原创作者,因为我发现这篇博客的地方也是别人转载的,所以具体是有哪位大牛完成的我也不得而知.转载文章不能标出原创作者和出处,请见谅) QQ5.0的侧滑效果有多种实现方式, 如http://blog.csdn.net/lmj623565791/article/details/39257409 就是利用HorizontalScrollV

android ListView和GridView拖拽移位具体实现及拓展

关于ListView拖拽移动位置,想必大家并不陌生,比较不错的软件都用到如此功能了.如:搜狐,网易,百度等,但是相比来说还是百度的用户体验较好,不偏心了,下面看几个示例:              首先说一下:拖拽ListView的item就不应该可以任意移动,只应该在 ListView所在的范围内,而网易的你看看我都可以移动到状态栏了,虽然你做了处理,但是用户体验我个人感觉不好,在看看百度的,不仅控制了移动范 围,更不错的百度的移动起来会时时的换位,看起来相当的形象,所以我认为这样相当的棒.

android可拖拽item的ListView--DragListVie

本博客原创,转载请标明 原文出处:http://blog.csdn.net/sql26/article/details/52252644 1.概述 在android项目开发中,需求对ListView中的商品item进行拖拽重新排序,网上看了一些帖子做的效果不错,就是代码不开源只写了思路,要么代码没注释,还不如自己写一个.. 2.效果图: 3.原理: 1.在touch事件里面通过ListView的pointToPosition(x, y)方法拿到当前点击的item的position: 2.根据当前

css 可拖拽列表

<!DOCTYPE HTML> <html><head> <meta charset="UTF-8"> <title>div横向拖拽排序</title> <script src="http://libs.baidu.com/jquery/1.9.0/jquery.js"></script> <style type="text/css"> b

D3js-实现图形拖拽及双击恢复

参考网站:饼状图的拖拽 效果:鼠标可拖拽图形,双击图形可恢复到拖拽前的位置. 图片效果: ·1.原图: 2.拖拽后的图形: 完整源码: <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <% String path = request.getContextPath(); String basePath = request.getScheme(