多看多学涨姿势,no zuo nuo die做暖男

1、概述

国际惯例,首先感谢一下开源作者。

这个项目主要是实现实现qq红点拖拽的效果 地址在https://github.com/chenupt/BezierDemo

主要效果

梳理主要知识点

【1】贝塞尔曲线的使用

【2】动态添加view

【3】判断点击事件是否在指定区域

2、项目知识点分析

【2.1】贝塞尔曲线的使用

常用的有2阶贝塞尔曲线

Path方法中

quadTo(float x1, float y1, float x2, float y2)可以用来绘制2阶贝塞尔曲线

其中quadTo的前两个参数为控制点的坐标,后两个参数为终点坐标,至于起点默认是画布的左上角。通常我们会使用moveTo移动到我们需要的起点,这里的p0就是起点,(x1,y1)就是中点P1,(x2,y2)就是末端点P2。p1称之为锚点

还有三阶贝塞尔曲线

同样是Path方法中

cubicTo(float x1, float y1, float x2, float y2, float x3, float y3) 用来绘制三阶贝塞尔曲线

与quadTo类似,前四个参数表示两个控制点,最后两个参数表示终点。其实,(x1,y1)就是P1,(x2,y2)是P2,(x3,y3)是P3。p2,p3称之为锚点

【在该项目中的使用】

项目中使用二阶贝塞尔曲线,由于实现拖拽效果实际是固定一个点,拖拽过程中为一个点,发生贝塞尔曲线实际上为这俩个圆之间的切线,如下图

可以看出p1-p2和p3-p4俩条线段会产生贝塞尔曲线,锚点在圆心连线上

作者在calcute方法中做了处理

// 根据角度算出四边形的四个点
        float offsetX = (float) (radius*Math.sin(Math.atan((y - startY) / (x - startX))));
        float offsetY = (float) (radius*Math.cos(Math.atan((y - startY) / (x - startX))));

        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.2、动态添加view】

这里牵涉到LayoutParams

LayoutParams继承于Android.View.ViewGroup.LayoutParams.

       LayoutParams相当于一个Layout的信息包,它封装了Layout的位置、高、宽等信息。假设在屏幕上一块区域是由一个Layout占领的,如果将一个View添加到一个Layout中,最好告诉Layout用户期望的布局方式,也就是将一个认可的layoutParams传递进去。

       但LayoutParams类也只是简单的描述了宽高,宽和高都可以设置成三种值:

       1,一个确定的值;

       2,FILL_PARENT,即填满(和父容器一样大小);

       3,WRAP_CONTENT,即包裹住组件就好。

作者动态添加了俩个imageview,一个是表示消息的imageview一个是移除红点之后的气泡效果

在Init方法中

LayoutParams params = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
exploredImageView = new ImageView(getContext());
exploredImageView.setLayoutParams(params);
exploredImageView.setImageResource(R.drawable.tip_anim);
exploredImageView.setVisibility(View.INVISIBLE);
 tipImageView = new ImageView(getContext());
tipImageView.setLayoutParams(params);
tipImageView.setImageResource(R.drawable.skin_tips_newmessage_ninetynine);
 addView(tipImageView);
addView(exploredImageView);

通过LayoutParams + addView完成动态添加控件,其实有时候xml无法满足时我们也可以通过动态控制view的方式来解决问题,建议还是熟悉一下代码写常用布局。

这里补充一下:

exploredImageView使用的是帧动画AnimationDrawable,这样可以模拟出连续的效果,使用也很简单,在drable文件夹中定义几个帧动画

<?xml version="1.0" encoding="utf-8"?>
<animation-list
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:oneshot="true">
    <item android:drawable="@drawable/idp" android:duration="300"/>
    <item android:drawable="@drawable/idq" android:duration="300"/>
    <item android:drawable="@drawable/idr" android:duration="300"/>
    <item android:drawable="@drawable/ids" android:duration="300"/>
    <item android:drawable="@drawable/idt" android:duration="300"/>
    <item android:drawable="@android:color/transparent" android:duration="300"/>
</animation-list>

这样可以模拟出消息移除后气泡爆炸的效果

【2.3、判断点击事件是否在指定区域】

主要是使用到

View.getLocationInWindow(int[] location)

一个控件在其父窗口中的坐标位置

View.getLocationOnScreen(int[] location)

一个控件在其整个屏幕上的坐标位置

他们使用的模式都一样先new一个Rect

该项目中需要判断点击事件是否是在红色消息图片上

 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;
            }

BezierDemo开源项目的学习的更多相关文章

  1. Android 开源项目及其学习

    Android 系统研究:http://blog.csdn.net/luoshengyang/article/details/8923485 Android 腾讯技术人员博客 http://hukai ...

  2. 开源项目live555学习心得

      推荐:伊朗美女找丈夫比找工作难女人婚前一定要看清三件事 × 登录注册   疯狂少男-IT技术的博客 http://blog.sina.com.cn/crazyboyzhaolei [订阅][手机订 ...

  3. 一个toolkit或者一个开源项目如何学习它并使用它

    一个toolkit或者一个开源项目如何学习它并使用它 一般一个流行的toolkit和开源项目,一般都会被广泛地被应用: 那么,我们如何学习它,如何应用它在自己的业务场景中呢? 答案就是:学习源码并借鉴 ...

  4. iOS及Mac开源项目和学习资料【超级全面】

    UI 下拉刷新 EGOTableViewPullRefresh – 最早的下拉刷新控件. SVPullToRefresh – 下拉刷新控件. MJRefresh – 仅需一行代码就可以为UITable ...

  5. iOS开发--iOS及Mac开源项目和学习资料

    文/零距离仰望星空(简书作者)原文链接:http://www.jianshu.com/p/f6cdbc8192ba著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”. 原文出处:codecl ...

  6. 开源项目AndroidReview学习小结(1)

    多看多学涨姿势 最近学习了一个开源项目,感觉收获颇多,这里做下简要的记录,首先感谢作者的开源.先看个大概图 感觉框架非常简单,界面也很一般,不过底层的处理的一些处理还是有很多可圈可点之处,代码的处理一 ...

  7. 开源项目AndroidReview学习小结(2)

    读书破万卷下笔如有神 作为入门级的android码农的我,还是需要多多研读开源代码 下面继续接着上一篇的分析,这一篇主要介绍第一个tab,ReviewFragment的分析,界面看起来简单,背后的逻辑 ...

  8. Android开源项目SlidingMenu学习(二)

    前一篇SlidingMenu学习(一)文章中了解了导入SlidingMenu到我们项目经常出现的问题,下面我们正式学习. 先看一个效果: 看到两幅图片的差别了吗,左边的一栏时可以滑动的,可以隐藏掉,现 ...

  9. 分享海量 iOS 及 Mac 开源项目和学习资料

    UI 下拉刷新 EGOTableViewPullRefresh - 最早的下拉刷新控件. SVPullToRefresh - 下拉刷新控件. MJRefresh - 仅需一行代码就可以为UITable ...

随机推荐

  1. springMVC源码分析--AbstractHandlerMapping(二)

    上一篇博客springMVC源码分析--HandlerMapping(一)中我们简单的介绍了HandlerMapping,接下来我们介绍一下它的抽象实现类AbstractHandlerMapping

  2. Python 3.3.3 使用requests模拟登录网站

    在模拟登录上,requests确实比python标准库中的相关模块更加简洁. 假设你需要去爬一组页面(targetUrls),而这些页面要登录才能进行访问.那么requests能够提供一种相当简单的语 ...

  3. Hive-ORC文件存储格式(续)

    本文在Hive-ORC文件存储格式的理论基础上,进一步分析一个实际的Hive ORC表中的数据存储形式. 一.表结构 库名+表名:fileformat.test_orc 字段 类型 category_ ...

  4. linux源码编译安装OpenCV

    为了尽可能保证OpenCV的特性,使用OpenCV源码编译安装在linux上.先从安装其依赖项开始,以ubuntu 14.04.X为例讲解在Linux上源码编译安装OpenCV,其他linux版本可以 ...

  5. SQLite Insert 语句(http://www.w3cschool.cc/sqlite/sqlite-insert.html)

    SQLite Insert 语句 SQLite 的 INSERT INTO 语句用于向数据库的某个表中添加新的数据行. 语法 INSERT INTO 语句有两种基本语法,如下所示: INSERT IN ...

  6. 剑指offer面试题3 二维数组中的查找(c)

    剑指offer面试题三:

  7. Android开发学习之路--RxAndroid之操作符

      学习了RxAndroid的一些基本知识,上篇文章也试过了RxAndroid的map操作符,接着来学习更多的操作符的功能吧.   操作符就是为了解决对Observable对象的变换的问题,操作符用于 ...

  8. Linux2.6 --系统调用处理程序

          用户空间的程序无法直接执行内核代码.它们不能直接调用内核空间中的函数,因为内核驻留在受保护的地址空间上.如果进程可以直接在内核的地址空间上读写的话,系统的安全性和稳定性将不复存在.     ...

  9. ceil和floor函数的编程实践

    ceil()向上取整 floor向下取整 题目 在最近几场魔兽争霸赛中,赫柏对自己的表现都不满意. 为了尽快提升战力,赫柏来到了雷鸣交易行并找到了幻兽师格丽,打算让格丽为自己的七阶幻兽升星. 经过漫长 ...

  10. Android中JNI编程详解

    前几天在参加腾讯模拟考的时候,腾讯出了一道关于JNI的题,具体如下: JNI本身是一个非常复杂的知识,但是其实对于腾讯的这道题而言,如果你懂JNI,那么你可能会觉得这道题非常简单,就相当于C语言中的h ...