BezierDemo开源项目的学习
多看多学涨姿势,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开源项目的学习的更多相关文章
- Android 开源项目及其学习
Android 系统研究:http://blog.csdn.net/luoshengyang/article/details/8923485 Android 腾讯技术人员博客 http://hukai ...
- 开源项目live555学习心得
推荐:伊朗美女找丈夫比找工作难女人婚前一定要看清三件事 × 登录注册 疯狂少男-IT技术的博客 http://blog.sina.com.cn/crazyboyzhaolei [订阅][手机订 ...
- 一个toolkit或者一个开源项目如何学习它并使用它
一个toolkit或者一个开源项目如何学习它并使用它 一般一个流行的toolkit和开源项目,一般都会被广泛地被应用: 那么,我们如何学习它,如何应用它在自己的业务场景中呢? 答案就是:学习源码并借鉴 ...
- iOS及Mac开源项目和学习资料【超级全面】
UI 下拉刷新 EGOTableViewPullRefresh – 最早的下拉刷新控件. SVPullToRefresh – 下拉刷新控件. MJRefresh – 仅需一行代码就可以为UITable ...
- iOS开发--iOS及Mac开源项目和学习资料
文/零距离仰望星空(简书作者)原文链接:http://www.jianshu.com/p/f6cdbc8192ba著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”. 原文出处:codecl ...
- 开源项目AndroidReview学习小结(1)
多看多学涨姿势 最近学习了一个开源项目,感觉收获颇多,这里做下简要的记录,首先感谢作者的开源.先看个大概图 感觉框架非常简单,界面也很一般,不过底层的处理的一些处理还是有很多可圈可点之处,代码的处理一 ...
- 开源项目AndroidReview学习小结(2)
读书破万卷下笔如有神 作为入门级的android码农的我,还是需要多多研读开源代码 下面继续接着上一篇的分析,这一篇主要介绍第一个tab,ReviewFragment的分析,界面看起来简单,背后的逻辑 ...
- Android开源项目SlidingMenu学习(二)
前一篇SlidingMenu学习(一)文章中了解了导入SlidingMenu到我们项目经常出现的问题,下面我们正式学习. 先看一个效果: 看到两幅图片的差别了吗,左边的一栏时可以滑动的,可以隐藏掉,现 ...
- 分享海量 iOS 及 Mac 开源项目和学习资料
UI 下拉刷新 EGOTableViewPullRefresh - 最早的下拉刷新控件. SVPullToRefresh - 下拉刷新控件. MJRefresh - 仅需一行代码就可以为UITable ...
随机推荐
- Android输入事件详解
输入事件 在 Android 系统中,从用户与应用的交互中截获事件的方法不止一种.如考虑截获用户界面内的事件,则可从用户与之交互的特定视图对象中捕获事件. 为此,View 类提供了多种方法. 在您将用 ...
- PHP学习(1)——我为什么要学PHP
PHP简介 PHP是一种服务器端的脚本语言,特别适合做web开发.高效.灵活.实用是PHP的特点.PHP最开始是Personal Home Page的缩写,后来正式更名为了"PHP:Hype ...
- activiti源码编译
个小时,大家安装的时候一定要耐心. 最终编译之后的效果部分如下图所示: 因为我这里有些xml文件没有去除验证,所以有红色的警告,不过也不影响使用. 下面看一下下载之后文件的变化如下图所示: 我们导入主 ...
- 协议系列之IP协议
1.协议 协议(protocol)的定义:为计算机网络中进行数据交换而建立的规则.标准或约定的集合.两个终端相互通信时双方达成的一种约定,规定了一套通信规则,双方通信必须遵守这些规则.这些规则规定了分 ...
- HDFS的读数据过程分析
我们继续在 FileSystem 类分析,读数据使用的是 open(-)方法,我们可以看到源码 FSDataInputStream in = fileSystem.open(new Path(&quo ...
- FFmpeg的HEVC解码器源代码简单分析:环路滤波(Loop Filter)
===================================================== HEVC源代码分析文章列表: [解码 -libavcodec HEVC 解码器] FFmpe ...
- SSO 基于Cookie+fliter实现单点登录 实例解析(一)
接上文,SSO的理论讲解,接下来实践实践! 1.使用Cookie解决单点登录 技术点: 1.设置Cookie的路径为setPath("/").即Tomcat的目录下都有效 2.设置 ...
- 从嵌入式linux到android应用开发
时间过得很快,转眼之间已经到新公司一个月了.虽然学到了一些移动开发的知识,但是觉得离我的目标还很远,完全没能达到我想要的水平.以前产品都是自己主导的,需要完成什么,计划什么也是自己主导,现在得从头 ...
- iOS中的两种搜索方式UISearchDisplayController和UISearchController
大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请多提意见,如果觉得不错请多多支持点赞.谢谢! hopy ;) 以前iOS的搜索一般都使用UISearchDisplayCon ...
- scala学习笔记4(apply方法)
class ApplyTest{ def apply() = "This apply is in class" def test{ println("test" ...