• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号
您的位置:首页 > 程序设计 >Android > Android 贝塞尔曲线实现QQ拖拽清除效果

Android 贝塞尔曲线实现QQ拖拽清除效果

作者:网友 字体:[增加 减小] 来源:互联网 时间:2017-05-26

网友通过本文主要向大家介绍了android 贝塞尔曲线,android 画贝塞尔曲线,android 贝塞尔,贝塞尔曲线,贝塞尔曲线工具等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com

Android 贝塞尔曲线实现QQ拖拽清除效果


纯属好奇心驱动写的一个学习性Demo,效果如下:
这里写图片描述vc23tNa1xNK7zPWyu7nm1PK1xFBhdGijrLb41eK49tbQvOTP8sTazeTH+rXE0Ke5+9X9ysfSu8z1sbTI+7b7x/rP36Os1tC85NXiuPZQYXRoysfTycG9zPWxtMj7tvvH+s/fus3Bvcz11rHP39fps8mho7+0z8LNvKO6PGJyIC8+DQo8aW1nIGFsdD0="这里写图片描述" src="http://www.bkjia.com/uploads/allimg/160407/0413013240-1.png" title="\" />
两个带圆弧的线就是由三点确认的一个贝塞尔曲线:
这里写图片描述
在Android已经有提供画贝塞尔曲线的接口,三个点传进去,效果就出来了。
贝塞尔曲线是用三个或多个点来确定的一条曲线,它在图形图像学中有相当重要的地位,Path中也提供了一些方法来给我们模拟低阶贝赛尔曲线。
本文的主要目的是学习贝塞尔曲线,看一下贝塞尔曲线的一下使用案例。
案例一:
这里写图片描述
案例二:
这里写图片描述
案例三:
这里写图片描述
案例四:
这里写图片描述
其实还有很多,还有QQ就是上面拖拽清除消息的气泡。看了之后你会好奇是怎么做的吧。

这里不讲背景,只讲贝塞尔曲线的一些效果,先从维基百科上盗图,看看不同数量的点上绘制贝塞尔曲线的效果。
两个点,绘制出来就是直线,也就是所谓的一阶贝塞尔曲线
这里写图片描述
三个点,二阶贝塞尔曲线:
这里写图片描述
四个点,三阶贝塞尔曲线:
这里写图片描述
五个点,四阶贝塞尔曲线:
这里写图片描述
六个点,五阶贝塞尔曲线:
这里写图片描述

大家看到上面的图,其实可以这么理解,这也是参考网友的理解。不管是一阶、二阶、还是六阶,他们都至少有两个点,也就是起点和终点。先用橡皮筋把这两个点连接好。而除了起点和终点之外的点都相当于对橡皮筋有吸引力的点,他们因为距离原因的不同,对橡皮筋产生不同程度的吸力,最终达到一个平衡状态,所以橡皮筋往非起始点有所偏移,如下图:
这里写图片描述

在Android中提供了绘制一阶、二阶、三阶的接口:
一阶接口:

public void lineTo(float x, float y)

二阶接口:

public void quadTo(float x1, float y1, float x2, float y2)

三阶接口:

public void cubicTo(float x1, float y1, float x2, float y2,
                        float x3, float y3)

关于最上面的QQ拖拽清除效果,就是用的二阶绘制的。

下面来简要讲解一下它的实现原理吧:

第一:那个99+消息是一个ImageView,它是根据OnTouch事件移动的,这个好理解。这是是通过在onTouch方法里面不断的setX()、setY()实现的。
第二:记录起始位置p1(x1,y1),记录手指拖拽位置p2(x2,y2),有了这两点我们就可以绘制直线了,但是我们这里绘制的是带有贝塞尔曲线的Path,所以重要工作是构造Path
第三:构造Path,如下图:
这里写图片描述
知道了上图两个黑点的坐标,并且知道绿色线的宽度Len,很好求出P1、P2、P3当中的点了,画个坐标系,用三角函数就求出来了。当然这个宽度Len是根据两个黑点之间的距离动态的去计算了,它与两个黑点之间的距离成反比。构造Path的步骤是:
p1-p3-p2之间:贝塞尔曲线
p2-p5之间:直线
p5-p3-p4之间:贝塞尔曲线
p4-p1之间:直线
构造了这样一个Path,然后用实心的画笔就画出效果来了。
当然,要完全达到要求还要加上逻辑控制了,代码如下:

package rander.com.bezier.bezier;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PorterDuff;
import android.graphics.Rect;
import android.graphics.drawable.AnimationDrawable;
import android.os.Handler;
import android.os.Looper;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.MotionEvent;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.Toast;

import rander.com.bezier.R;

/**
 * Created by Rander.C on 16-4-3.
 */
public class QQDragtoClearView extends FrameLayout {
    /**
     * 最大拖拽长度
     */
    private final int DRAG_MAX_LEN = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 100, getResources().getDisplayMetrics());
    /**
     * 默认的红点半径大小
     */
    private final int DEFAULT_RADIUS = 40;
    /**
     * 消息数量背景,QQ里面起始用的就是一个图片,而不是在红色背景上画一个数量
     */
    private ImageView mIvMsgCountBg;
    /**
     * 拖拽清除的时候的动画视图
     */
    private ImageView mIvClearAnim;

    /**
     * 手触摸的x,y坐标
     */
    private float mTouchX;
    private float mTouchY;
    /**
     * 初始的x,y坐标,默认安放的位置
     */
    private float mStartX = 300;
    private float mStartY = 300;
    /**
     * 手触摸的坐标和初始点坐标的中间位置
     * mCenterX = (mTouchX + mStartX)/2
     * mCenterY = (mTouchY + mStartY )/2
     * 这个是用来画贝塞尔曲线的一个中转点
     */
    private float mCenterX;
    private float mCenterY;
    private static final int TOUCH_SLOP = 10;

    /**
     * 画贝塞尔曲线的画笔
     */
    private Paint mPaint;
    /**
     * 画贝塞尔曲线的Path
     */
    private Path mPath;

    /**
     * 是否被点中了
     */
    private boolean isTouch;

    /**
     * 默认的半径大小
     */
    private int mRaduis = DEFAULT_RADIUS;

    /**
     * 判断贝塞尔曲线是否断掉了
     */
    private boolean isBroken = false;

    public QQDragtoClearView(Context context) {
        this(context, null);
    }

    public QQDragtoClearView(Context context, AttributeSet attrs) {
        this(context, attrs, -1);
    }

    public QQDragtoClearView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    /**
     * 初始化
     */
    private void init() {
        mPath = new Path();

        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setStyle(Paint.Style.FILL_AND_STROKE);
        mPaint.setStrokeWidth(2);
        mPaint.setColor(Color.RED);

        FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(60, 60);
        mIvClearAnim = new ImageView(getContext());
        mIvClearAnim.setLayoutParams(params);
        mIvClearAnim.setImageResource(R.drawable.tip_anim);
        mIvClearAnim.setVisibility(INVISIBLE);

        mIvMsgCountBg = new ImageView(getContext());
        mIvMsgCountBg.setLayoutParams(params);
        mIvMsgCountBg.setImageResource(R.drawable.skin_tips_newmessage_ninetynine);
        mIvMsgCountBg.setVisibility(VISIBLE);

        addView(mIvClearAnim);
        addView(mIvMsgCountBg);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        mTouchX = (int) event.getX();
        mTouchY = (int) event.getY();
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                //ACTION_DOWN的作用就是判断触摸的点
                Rect rect = new Rect();
                int[] location = new int[2];
                mIvMsgCountBg.getDrawingRect(rect);
                mIvMsgCountBg.getLocationOnScreen(location);
                rect.left = location[0];
                rect.top = location[1];
                rect.right = rect.right + location[0];
                rect.bottom = rect.bottom + location[1];
                if (r



 
分享到:QQ空间新浪微博腾讯微博微信百度贴吧QQ好友复制网址打印

您可能想查找下面的文章:

  • Android 贝塞尔曲线实现QQ拖拽清除效果
  • Android 自定义View高级特效,神奇的贝塞尔曲线

相关文章

  • 2017-05-26android:省市二级联动下拉框
  • 2017-05-26linux 破解版 confluence
  • 2017-05-26安居客Android项目架构演进,android架构演进
  • 2017-05-224.4.1 ContentProvider初探
  • 2017-05-228.3.1 三个绘图工具类详解
  • 2017-05-26ViewPager实现滑动翻页效果,viewpager滑动翻页
  • 2017-05-26Android客户端性能优化(魅族资深工程师毫无保留奉献)
  • 2017-05-26Android studio 下的SDK Manager只显示已安装包的情况,androidsdk
  • 2017-05-26Gradle Android客户端程序打包,gradleandroid
  • 2017-05-26Android之TextView,androidtextview

文章分类

  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号

最近更新的内容

    • Android Studio混淆打包错误
    • android学习第一天(android的介绍和基础):,android第一天
    • android:从另外一个activity中返回数据
    • 2.4.3 Date & Time组件(下)
    • Android Studio Ndk 编程
    • 安卓GreenDao框架一些进阶用法整理,安卓greendao
    • Atitit.反编译apk android源码以及防止反编译apk,atititapk
    • Android Studio 之 注释模板,androidstudio
    • 安卓应用程序的签名
    • Android自定义控件系列案例【四】

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有