控件平移动画之后,点击事件没有移动,必须点原来的位置

原文地址:http://blog.csdn.net/seker_xinjian/article/details/7236945
底部有源码下载地址,不过需要收费,需要免费的可以留言给我。

在开发Android应用过程中,我曾遇到过下面的问题:

假设有一个View,它在做一系列复杂的、组合的Tween动画(平移动画、旋转动画、缩放动画、Alpha动画)。在动画的过程中,用户会去点击这个View。如何去判断这个View被点击中了没有呢?

为此,我曾专门在CSDN上发布了一条悬赏100分的技术贴:
http://topic.csdn.net/u/20111125/14/79debf30-c6ea-4945-ab1b-456e17259a2c.html
以求得其解。然而,终究没有得到相应的答案。最终,得益于从前的两位同事,找到了解决方案,特书此文,以供路人指教。

一、动画的原理
很多人看到我的帖子的时候,不懂我在说些什么,不知道问题点在哪里。他们可能觉得点击事件只要注册了“事件监听器”不久OK了么?

事实上不是这样子的。正如我在上述的技术贴中提到的:

View做在做动画的时候,它并没有真正的移动它的位置。而是根据动画时间的插值,计算出一个Matrix,然后不停的invalidate,在onDraw中的Canvas上使用这个计算出来的Matrix去draw这个View的内容。
换句话说,View在做动画的时候,它的位置根本没有变化,只是画它的时候进行了Matrix处理,使得它看起来变化了。那么,动画中的View点击事件的判断区域,应该是它“看起来”的那片区域,而不是它layout的那片区域。

我相信很多人还是不明白。所以特地找到了一个大牛人写的另外一个博文《Android 动画框架详解》,供大家搞明白Android中的动画原理。明白了Android补间动画的原理之后,然后再读下去。
http://www.ibm.com/developerworks/cn/opensource/os-cn-android-anmt1/index.html

二、问题重述
比方说:一个矩形的View,它的的layout区域是(l,t,r,b),自然它的点击事件的判断区域也就是(l,t,r,b)

当它做一个动画(平移动画、旋转动画、缩放动画)时,它的的layout区域依然是(l,t,r,b),但是它的显示区域却可是另外一片区域,比如是下图(红色区域):

 这时候如果还是以(l,t,r,b)区域来点击事件,自然就不可能正确了。

三、问题分析
《Android 动画框架详解》所讲的最核心的一点就是:Android 动画就是通过 ParentView 来不断调整 ChildView 的画布坐标系来实现的。
严格来讲,上述的“Android 动画”应该限为:补间动画的1)、平移动画,2)、旋转动画,3)、缩放动画。

动画的产生过程涉及到两个重要的类型,Animation 和 Transformation,这两个类是实现动画的主要的类。

Animation 中主要定义了动画的一些属性比如开始时间、持续时间、是否重复播放等。这个类主要有两个重要的函数:getTransformation 和 applyTransformation,在 getTransformation 中 Animation 会根据动画的属性来产生一系列的差值点,然后将这些差值点传给 applyTransformation,这个函数将根据这些点来生成不同的 Transformation。

Transformation 中包含一个矩阵和 alpha 值,矩阵是用来做平移、旋转和缩放动画的,而 alpha 值是用来做 alpha 动画的(简单理解的话,alpha 动画相当于不断变换透明度或颜色来实现动画)。这正好对应着Transformation.TYPE_ALPHA和Transformation.TYPE_MATRIX这两种类型。

四、解决方案
到此,可以看到如果一个View如果在做补间动画中的平移、旋转、缩放动画,那么它的点击事件一定要进行的矩阵处理。

具体做法就是:
    1、在ParentView中重写onTouchEvent(MotionEvent event),拦截点击点击事件的x、y坐标。注意(x,y)是相对于ParentView坐标系的。
    2、根据(x,y)坐标算得“点击”点相对于View坐标系的坐标点(x - view.getLeft(), y - view.getTop())。
    3、获得View的动画的时间,从而获得Transformation,进而获得Matrix。然后求的Matrix的逆矩阵Matrix'。
    4、使用Matrix'将坐标点(x - view.getLeft(), y - view.getTop())求对应的映射坐标(x',y')。
    5、(x',y')再还原成ParentView坐标系中的点(x' + view.getLeft(), y' + view.getTop())。
    6、使用View.getHitRect(rect),获得“点击判断矩形”,再Rect.contains(int x, int y)判断改点是否在View的区域范围内。

五、代码
为了解决这个问题,我曾写过一段测试代码,也上传到CSDN上来了。因为是自己原创,为了告慰为此而阵亡的脑细胞,因而该资源不是免费的。
下载地址:http://download.csdn.net/detail/seker_xinjian/4047390

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,590评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,808评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,151评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,779评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,773评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,656评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,022评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,678评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,038评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,756评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,411评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,005评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,973评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,053评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,495评论 2 343

推荐阅读更多精彩内容