【问题标题】:Orientation change: children of LinearLayout can't have @+id/something方向改变:LinearLayout 的子级不能有@+id/something
【发布时间】:2013-05-28 21:28:58
【问题描述】:

来自Android Google group的交叉发帖

我今天早些时候遇到了这个问题: https://code.google.com/p/android/issues/detail?id=55106

问题是:

  • LinearLayout 有子级
  • 每个孩子都是从同一个 XML 布局文件中扩展而来的
  • 一个子元素具有一些 ID 的嵌套元素。
    • ID 用于调用 findViewById(ID) 设置一些值
  • 一切都在启动时正确显示,但在方向改变后 LinearLayout 的每个子项都显示最后一个数据项的值
  • 从子 XML 布局文件中删除 ID 后,一切都会开始正常工作

该错误附有演示该问题的示例项目。

只是想问是否有人遇到过同样的问题并知道解决方法?

提前谢谢你。


编辑:

LinearLayout 的情况非常不稳定。我终于完成了这个项目 - 请参阅第二个附加项目 https://code.google.com/p/android/issues/detail?id=55106

如果您转到 item_main.xml 并将 android:textIsSelectable 从 false 更改为 true,则会出现错误。 保留 android:textIsSelectable="true",但删除 android:id="@+id/text" - 错误再次消失

我尝试使用此 LinearLayout 的主要原因是因为我想遵循您的布局动画示例。 http://developer.android.com/training/animation/layout.html

但是,LinearLayout 和方向变化的情况似乎很不稳定,我需要回到工作中的 ListView+Adapter 方法,并弄清楚在向适配器添加项目和重新验证列表时如何做类似的布局动画。

【问题讨论】:

  • stackoverflow.com/questions/14263665/…。您的问题很可能与保存和恢复活动状态有关。考虑实现 onSaveInstanceState() 和 onRestoreInstanceState()
  • 看来不是这样。我正在处理的更大的项目实现了 onSaveInstanceState()。根据我对片段的发现,它看起来像一个框架错误。 code.google.com/p/android/issues/detail?id=55106 此外,我还发现,如果我从 Google 获取基于活动的布局动画示例并将 TextView 的 ID 从 @android:id/text1 更改为 @+id/text1,它们的示例也会停止工作。 LinearLayout、textIsSelectable 和 id 组合起来真的很不稳定。

标签: android


【解决方案1】:

另一种解决方法是在 onSaveInstanceState 方法中从 LinearLayout 中删除所有视图。

@Override
protected void onSaveInstanceState(Bundle outState) {
    LinearLayout linearLayout = (LinearLayout) findViewById(R.id.yourLinearLayoutId);
    linearLayout.removeAllViews();
    super.onSaveInstanceState(outState);
}

【讨论】:

  • 这似乎是问题所在,但不幸的是,在保存状态之前清除视图对我不起作用(不知道为什么!?)。不过,我确实从中得到了提示,并在调用 super 之后在 onViewStateRestored() 方法中构建我的线性布局子级。无论如何,这对我有用,不是最好的解决方案。在我的例子中,这个问题只发生在 Switch 组件上,在我的膨胀视图中不会发生在其他任何事情上。好奇。
【解决方案2】:

您是否有任何特殊原因为什么要膨胀 50 个子布局,然后将它们插入 ScrollView 而不是使用 AdapterView?

在我看来,您可能应该将 ListView 与某种适配器一起使用,该适配器将为您处理行膨胀和数据绑定,这不仅会提高效率和性能,还会让您避免这个“错误”你遇到的。

任何时候你在循环中膨胀视图都应该是一个strong提示你应该重新考虑你的方法并开始使用某种AdapterView(ListView、Gallery等... )

【讨论】:

  • 50 个孩子只是查看滚动的示例。在实际应用中,它通常是 4-5 个视图,但更大,因此无需添加太多视图即可看到滚动。使用 LienarLayout 的主要原因是遵循这个框架示例:developer.android.com/training/animation/layout.html
【解决方案3】:

当您添加多个 TextViews 并为它们重新使用相同的 id (android:id="@+id/text") 时,我最好的猜测是,一旦您调用 findViewByID,您就会遇到意外行为(充其量)方法。做你显然想做的事情(使用TextViews 的列表,你可以做类似于here 建议的事情,即创建一个TextViews 的数组,将它们实例化并保留它们以供内部参考。

你发现的实际上并不是一个错误,它的行为应该是这样的:所有TextViews 都有相同的 id,所以所有的都会同时改变。

我在文档中查找了actual reference(重点是我的):

ID 在整个树中不必是唯一的,但它应该是 在您正在搜索的树的一部分中是唯一的(通常可能 是整棵树,所以最好是完全唯一的 可能)。

【讨论】:

  • 我不会从容器中调用 findViewById() ,这将是一个问题,从子视图本身调用它的错误不是问题,因为搜索仅限于子视图。如果从 ListView 容器本身调用 findViewById(),拥有 ListView + Adapter 也会遇到同样的问题。关于 TextView 上的相同 id:显然在第一次实例化 LinearLayout 时这不是问题。在片段内的方向更改后重新创建相同的视图后,它成为一个问题。我仍然认为这是一个框架错误。
  • 想想吧。您正在向 LinearLayout 添加一些兄弟姐妹。它们都被命名为相同并被解析,例如值 123。当您请求 findViewById(123) 时,框架应该返回哪一个?首先?第二?最后?事实上,框架多次告诉你标识符不必是唯一的(例如developer.android.com/reference/android/view/…
  • (顺便说一句:在“这成为一个问题......”之前,你能改写你想说的话吗?老实说,我不明白你想说什么。)
  • 从相同的 XML 布局中膨胀子元素是很常见的技术。对于这些孩子来说,定义 ID 也是很常见的。它们将是相同的 ID。 ListView + Adapter 使用这种技术。 findViewById() 仅当在视图层次结构中的容器上或之上调用时才会出现问题。如果在孩子本身上调用 findViewById() 不是问题。
  • 看:没有人说技术是错误的。他们定义 ID 也没有错。文档实际上是这样说的:id 应该不同,它们必须不一样。问题仅在于您希望该函数执行它不打算执行的操作(找出您希望它访问的现有 id 之一,即使它们相同)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-18
  • 1970-01-01
  • 2017-10-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多