美文网首页
android随笔之为什么属性动画移动一个控件后,目标位置仍然能

android随笔之为什么属性动画移动一个控件后,目标位置仍然能

作者: android老菜鸟 | 来源:发表于2020-10-21 11:07 被阅读0次

如题,多的不说,少的不唠,直接入主题:

为什么属性动画移动一个控件后,目标位置仍然能响应用户事件?

也就是说,应用了属性动画之后,该View依然可以正确地接收到事件的分派。
那就要搞清楚ViewGroup它是怎么找到这个"偷跑"了的View的。
我们知道,调用View的translationXX方法之后,虽然在屏幕上的位置是变了,但是它的[left,top,right,bottom]是不会变的。

来捋一遍ViewGroup分派事件的大致流程:

当手指按下时,触摸事件会经过ViewGroup中的dispatchTouchEvent方法筛选符合条件(手指在边界范围内)的子View进行分派事件(如果未被onInterceptTouchEvent拦截的话)。
那么,如果某个子View刚好应用了translation属性动画,在ViewGroup筛选子View时,直接判断触摸点是否在[left,top,right,bottom]范围内,是肯定不行的。

那它是怎么判断的呢?

它会先调用子View的hasIdentityMatrix方法来判断这个View是否应用过位移、缩放、旋转之类的属性动画。
如果应用过的话,那接下来还会把触摸点映射到该子View的逆矩阵上(getInverseMatrix)。
判断处理后的触摸点,是否在该子View的边界范围内。
上面说到了"把触摸点映射到该子View的逆矩阵上",那它是怎么个映射法:
比如一个View它水平平移了200,那它所对应的逆矩阵就是水平平移了-200,
如果触摸点坐标是[500,500]的话,那么映射之后,就是[300,500],也就是反方向移动同样的距离了。

可以这样来理解:

如果一个View向右移动了一个拇指的距离,当手指在它的新位置上按下的时候,
(它最终还是要判断是否在原来的边界范围内的,那只能把触摸的坐标,给转回去,转回它应用变换之前的位置上),
那ViewGroup在检测到它应用了变换后,会把现在的触摸点,向左(刚刚是向右)移动一个拇指的距离(抵消),再来判断是否在该View的边界范围内。
那么为什么只有属性动画可以这样,补间动画就不行呢?
View在draw的时候,会检测是否设置了Animation(补间动画),
如果有的话,会获取这个动画当前的值(旋转或位移或缩放,透明度等),应用到canvas上,然后把东西draw出来。
比如设置了位移动画,当前值是向右移动了100,那么效果就等于这样:
Matrix matrix = new Matrix();
matrix.setTranslate(100, 0);
canvas.setMatrix(matrix);
它的作用只会在draw的时候有效。
虽然大家都是操作Matrix,但是Matrix的对象不一样(属性动画操作的Matrix,是View的mRenderNode所对应的Matrix),
所以在ViewGroup筛选的时候,应用属性动画的View会被正确找到,而补间动画的不行。
属性动画所影响的Matrix,是在View的mRenderNode中的stagingProperties里面的,这里的Matrix,每个View之间都是独立的,所以可以各自保存不同的变换状态。
而补间动画,它所操作的Matrix,其实是借用了它父容器的一个叫mChildTransformation的属性(里面有Matrix),通过getChildTransformation获得。
也就是说,一个ViewGroup中,无论它有几个子View都好,在这些子View播放补间动画的时候,都是共用同一个Transformation对象的(也就是共用一个Matrix),这个对象放在ViewGroup里面。
有同学可能会问:共用?不可能吧,那为什么可以同时播放好几个动画,而互相不受影响呢?
是的,在补间动画更新每一帧的时候,父容器的mChildTransformation里面的Matrix,都会被reset。

每次重置Matrix而不受影响的原因:

是因为这些补间动画,都是基于当前播放进度,来计算出绝对的动画值并应用的,保存旧动画值是没有意义的。
就拿位移动画TranslateAnimation来说,比如它要向右移动500,当前的播放进度是50%,那就是已经向右移动了250,在View更新帧的时候,就会把这个向右移动了250的Matrix应用到Canvas上,当下次更新帧时,比如进度是60%,那计算出来的偏移量就是300,这时候,已经不需要上一次的旧值250了,就算Matrix在应用前被重置了,也不影响最后的效果。

相关文章

  • android随笔之为什么属性动画移动一个控件后,目标位置仍然能

    如题,多的不说,少的不唠,直接入主题: 为什么属性动画移动一个控件后,目标位置仍然能响应用户事件? 也就是说,应用...

  • Android源码解析-- Animator动画

    Android在3.0版本中引入了新的动画实现:属性动画。我们一般称之为Animator。这种动画通过变更控件属性...

  • 补间动画,帧动画

    一、补间动画 1、概述:动画结束后不影响原控件属性 2、分类: 平移动画 TranslateAnimation: ...

  • 动画·Animation

    简介: android中的动画分为两种补间动画和帧动画 一、补间动画 通过移动控件的位置,改变透明度,控件的角度等...

  • iOS 动画入门

    iOS 动画入门 两个基础动画:移动和弹簧效果 1. 定义 移动:控件从一个位置移到另一个位置弹簧效果:控件到达终...

  • Android动画基础详析 | 属性动画基础及ValueAnim

    为什么要引入属性动画 逐帧动画主要是用来实现动画的,而补间动画才能实现控件的渐入渐出、移动、旋转和缩放效果;属性动...

  • 2.Tween Animation 补间动画

    资料链接 普通动画: 最大的特点是:并没有改变目标实际的属性(宽高/位置等)。例如:移动后,点击原来的位置出发点击...

  • 工作笔记

    ConstraintLayout 使用 相对位置属性(layout_constraint[自身控件位置]_[目标控...

  • 炫酷的MaterialDesign Ripple水波纹动画效果

    google在android 5.0上加入了触摸反馈动画(Ripple),设置成功后,点击控件的时候会从点击位置产...

  • Android属性动画

    写在前面 android属性动画可以作用在所有view上android中的属性动画是会改变空间的真实位置,即属性动...

网友评论

      本文标题:android随笔之为什么属性动画移动一个控件后,目标位置仍然能

      本文链接:https://www.haomeiwen.com/subject/srmkmktx.html