在<include>视图上调用findViewById返回null

11

让我们直接进入代码。

活动代码,onCreate方法。

setContentView(R.layout.main);

View main_view = findViewById(R.id.main_view);
View view_flipper = main_view.findViewById(R.id.vf);
View first_tab = view_flipper.findViewById(R.id.prev_pane);
<ViewFlipper android:id="@+id/vf"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >  

    <include android:id="@+id/prev_pane" layout="@layout/vf_inner" /> 
<include android:id="@+id/cur_pane" layout="@layout/vf_inner" />
    <include android:id="@+id/next_pane" layout="@layout/vf_inner" />
</ViewFlipper>
问题!主视图和 ViewFlipper 都被正确找到,但 prev_pane、cur_pane 或 next_pane 找不到,返回空指针。有任何想法吗?此活动是通过 Intent 通过选项卡调用的。所有引用都正确解决,除了包含的 ID。当我检查变量时,我发现 vf_inner 布局的内容在 mChildren 中。
2个回答

8
这是因为<include />标签不是UI层次结构中的实际视图。它们更像是Android工具的复制和粘贴指令。
如果您想在运行时找到窗格,请将ID添加到所包含布局的根元素中。这样,它们可以通过findViewById()被找到。

所有的窗格都是相同的,但它们需要有不同的内容。我该如何实现这一点?事实上,所有包含视图都包含一个带有ID的图像和TextView。图像保持静态,但对于所有窗格来说,文本都是不同的。 - Artis
哦,我明白了。我相信在这方面XML是有限制的(至少目前我不知道怎么做)。不过你可以通过代码构建它。使用布局填充器服务来填充三个布局实例,使用 setId() 设置填充的视图ID。然后通过 findViewById() 搜索 ViewFlipper,并通过 ViewFlipper.addView() 添加这三个布局。 - user658042
3
请注意,您还可以通过ViewFlipper.getChildAt (index)引用ViewFlipper的子项,而不是它们的id。例如:View first_tab = view_flipper.getChildAt(0) - user658042
谢谢,alextsc!这解决了我的问题,因为视图计数是固定的! - Artis

0

你可以做的一件事是将<include>语句包含在父布局内(仍然是您主要父布局的子项)。给这些视图分配不同的ID,以便您可以单独使用findViewById检索每个视图。


如果您在ViewFlipper中只有固定数量的视图,则它们仍将被视为其子项,因此您不应该遇到任何问题。 - josephus
+1 正确,我忽略了这种可能性。如果您需要分配给子元素的ID,则可以使用此方法。如果不需要这些,请改用ViewFlipper.getChildAt(),如我的答案评论所述。原因是应尽可能保持视图层次结构的扁平化。深度嵌套的视图层次结构会对性能产生严重影响。 - user658042

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接