android lollipop ViewGroup child 层次结构发生变化?
android lollipop ViewGroup child hierarchy changes?
我有一个 minSdk 为 15 的应用程序,我正在解决棒棒糖升级带来的所有错误。我们的软件非常复杂,它使用自定义 ViewGroups 动态创建视图,然后是明确调整大小并放置在组内的元素数组。我 运行 遇到一个问题,例如我将有一个 ViewGroup,第一个 child object 是一个按钮...此按钮的大小适合填充视图(不可点击).第二个 child 是一个包含单个视图的 FrameLayout。这个单一视图是一个视频 object。在 Android 的所有先前版本中,这工作得很好。 FrameLayout 位于按钮(作为背景)之上,视频位于 framelayout 内。您可以毫无问题地与视频互动。
棒棒糖中发生了一些变化 - 突然间,即使按钮显示为 0 索引元素,它也覆盖了 children 的其余部分...所以我无法访问下面的视频.如果我删除该按钮元素,视频将呈现并播放得很好......我可以毫无问题地与之互动。
我 运行 UI Automator Viewer 中的应用程序只是为了确保我确实按照我的预期设置了 UI(请记住整个视图动态呈现在运行时使用 image/video 资产和 xml 配置文件)。
我无法共享代码,因为这是专有软件,但我正在做一个小测试项目,看看我是否可以用静态 objects 手动重现问题。一旦我准备好 运行,我一定会更新这张票。现在,这是层次结构的屏幕截图:
https://goo.gl/photos/a8on9CJDnN66XYnV6
注意突出显示的object,这是自定义ViewGroup,下面的children就是我上面描述的。
有谁知道 Lollipop 中会影响事物排序的变化?我早些时候发现,如果你有一个禁用的 object 但没有分配给它的禁用状态可绘制对象 object 它会变得不可见,以前的版本只是使用其他状态可绘制对象之一..好吧有道理而且很容易修复,但是这个 object 不是不可见的......所以它一定是不同的东西。
任何方向将不胜感激。
~A
更新 -- 已修复
在@alanv 和@BladeCoder 的帮助下,我发现此功能是由于 Material 设计的新海拔功能。我能够通过首先检查设备使用的 android 版本来解决我的特定问题,如果是 lollipop,我只需将这个新的 属性 添加到按钮:
android:stateListAnimator="@null"
这可以防止我的显式 child 层次结构被 OS 覆盖。
好的,更新!我想出了如何解决这个问题,尽管我仍然不确定(即使在 grepcode 中倾倒了几个 类 之间的差异之后)棒棒糖中发生了什么变化导致其工作方式发生变化。
如果按钮已启用...并且您正在使用与 AbsoluteLayout 等效的东西放置它(我们创建了自己的 ViewGroup,称为显式布局,但它与 AbsoluteLayout 的功能几乎相同),它将始终位于堆栈中不是某种按钮的任何其他内容之上(至少这是我发现的......我没有测试所有可能的小部件)。
将纯粹用作背景图像的按钮设置为 enabled=false 可解决此问题。我知道,我们将按钮用作背景图像是没有意义的,但我们的代码使用它来创建动态元素,因此每个元素都有许多可能的状态和用途。
无论如何,不确定其他人是否会 运行 解决这个问题,但以防万一...在这里。
谢谢!
Lollipop 引入了 elevation 作为在 Z 轴上定位元素并根据它们的高度差异在它们之间投射阴影的方法。
启用按钮的默认高度为 2dp(当您按下它们时它会增加)。因此,您的按钮的高度高于 FrameLayout
(默认情况下为 0dp),因此它将绘制在它的顶部。
禁用按钮的高度为 0dp。这就是禁用按钮解决了您的问题的原因。
使用按钮作为背景看起来不是个好主意(为什么不在 FrameLayout
上设置自定义 Drawable
背景呢?)但是如果你真的需要它,你可以像你一样禁用按钮做了,只是为了确定,将其提升到 0dp。另一个解决方法是增加 FrameLayout 的高度,但如果它有背景,它可能会在 Lollipop 下投下很大的阴影,也许这不是您想要的。
我有一个 minSdk 为 15 的应用程序,我正在解决棒棒糖升级带来的所有错误。我们的软件非常复杂,它使用自定义 ViewGroups 动态创建视图,然后是明确调整大小并放置在组内的元素数组。我 运行 遇到一个问题,例如我将有一个 ViewGroup,第一个 child object 是一个按钮...此按钮的大小适合填充视图(不可点击).第二个 child 是一个包含单个视图的 FrameLayout。这个单一视图是一个视频 object。在 Android 的所有先前版本中,这工作得很好。 FrameLayout 位于按钮(作为背景)之上,视频位于 framelayout 内。您可以毫无问题地与视频互动。
棒棒糖中发生了一些变化 - 突然间,即使按钮显示为 0 索引元素,它也覆盖了 children 的其余部分...所以我无法访问下面的视频.如果我删除该按钮元素,视频将呈现并播放得很好......我可以毫无问题地与之互动。
我 运行 UI Automator Viewer 中的应用程序只是为了确保我确实按照我的预期设置了 UI(请记住整个视图动态呈现在运行时使用 image/video 资产和 xml 配置文件)。
我无法共享代码,因为这是专有软件,但我正在做一个小测试项目,看看我是否可以用静态 objects 手动重现问题。一旦我准备好 运行,我一定会更新这张票。现在,这是层次结构的屏幕截图:
https://goo.gl/photos/a8on9CJDnN66XYnV6
注意突出显示的object,这是自定义ViewGroup,下面的children就是我上面描述的。
有谁知道 Lollipop 中会影响事物排序的变化?我早些时候发现,如果你有一个禁用的 object 但没有分配给它的禁用状态可绘制对象 object 它会变得不可见,以前的版本只是使用其他状态可绘制对象之一..好吧有道理而且很容易修复,但是这个 object 不是不可见的......所以它一定是不同的东西。
任何方向将不胜感激。 ~A
更新 -- 已修复
在@alanv 和@BladeCoder 的帮助下,我发现此功能是由于 Material 设计的新海拔功能。我能够通过首先检查设备使用的 android 版本来解决我的特定问题,如果是 lollipop,我只需将这个新的 属性 添加到按钮:
android:stateListAnimator="@null"
这可以防止我的显式 child 层次结构被 OS 覆盖。
好的,更新!我想出了如何解决这个问题,尽管我仍然不确定(即使在 grepcode 中倾倒了几个 类 之间的差异之后)棒棒糖中发生了什么变化导致其工作方式发生变化。
如果按钮已启用...并且您正在使用与 AbsoluteLayout 等效的东西放置它(我们创建了自己的 ViewGroup,称为显式布局,但它与 AbsoluteLayout 的功能几乎相同),它将始终位于堆栈中不是某种按钮的任何其他内容之上(至少这是我发现的......我没有测试所有可能的小部件)。
将纯粹用作背景图像的按钮设置为 enabled=false 可解决此问题。我知道,我们将按钮用作背景图像是没有意义的,但我们的代码使用它来创建动态元素,因此每个元素都有许多可能的状态和用途。
无论如何,不确定其他人是否会 运行 解决这个问题,但以防万一...在这里。
谢谢!
Lollipop 引入了 elevation 作为在 Z 轴上定位元素并根据它们的高度差异在它们之间投射阴影的方法。
启用按钮的默认高度为 2dp(当您按下它们时它会增加)。因此,您的按钮的高度高于 FrameLayout
(默认情况下为 0dp),因此它将绘制在它的顶部。
禁用按钮的高度为 0dp。这就是禁用按钮解决了您的问题的原因。
使用按钮作为背景看起来不是个好主意(为什么不在 FrameLayout
上设置自定义 Drawable
背景呢?)但是如果你真的需要它,你可以像你一样禁用按钮做了,只是为了确定,将其提升到 0dp。另一个解决方法是增加 FrameLayout 的高度,但如果它有背景,它可能会在 Lollipop 下投下很大的阴影,也许这不是您想要的。