如何引用以后的XML元素?
这是一个特定的用例。我们假设我有一个带有LinearLayout根的表单,其中包含多行的LinearLayouts,每行包含一个或多个文本输入区域。
这里是我想要的视觉效果。第一张图片来自Venmo的应用程序,第二张是以下XML的呈现。
这样的布局可能如下所示:
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:id="@+id/row_card_number"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<EditText
android:id="@+id/card_number"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:nextFocusDown="@id/month"/>
</LinearLayout>
<LinearLayout
android:id="@+id/row_date"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<EditText
android:id="@+id/month"
android:layout_height="wrap_content"
android:layout_width="100dp"
android:nextFocusDown="@id/year"/>
<EditText
android:id="@+id/year"
android:layout_height="wrap_content"
android:layout_width="match_parent"/>
</LinearLayout>
</LinearLayout>
在此用例中,前向引用是必需的,以便设置下一个焦点元素。这样,当您按下键盘上的下一个按钮时,它将转到正确的视图。在这个没有nextFocusDown
的样本xml中,按下next将从名称到月份,并且永远不会去年。
但是,如果您尝试编译它,则会收到错误:
错误:(18,36)找不到与给定名称匹配的资源(在&#39; nextFocusDown&#39;值为&#39; @ id / month&#39;)。
这是因为当我试图引用ID时,month
尚未初始化,因为该文件后面会有{{1}}。如何引用稍后出现在文件中的xml中的id?
答案 0 :(得分:11)
最简单的解决方案就是替换
android:nextFocusDown="@id/month"
带
android:nextFocusDown="@+id/month"
当编译器解析你的XML以将id添加到R.java时,它只是从上到下读取。当您拥有@id/month
时,它会搜索现有的ID,但无法找到它。
但是,如果您执行@+id/month
,则会创建一个新ID,并链接到该ID。当它在实际月份视图中到达android:id=@+id/month
时,它会将其链接到我们已创建的相同ID。
这提出了一个问题:如果您可以将@id/
替换为@+id/
,@+id/
无论元素的顺序如何都会有效,为什么还要费心使用@id/
?
原因是如果id不存在,@id/
将抛出编译器错误,而@+id/
将在运行时记录警告。
考虑这个XML:
<EditText
android:id="@+id/month"
android:layout_height="wrap_content"
android:layout_width="100dp"
android:nextFocusDown="@+id/SOME_RANDOM_ID"/>
<EditText
android:id="@+id/year"
android:layout_height="wrap_content"
android:layout_width="match_parent"/>
解析时,会创建一个新的id元素SOME_RANDOM_ID
。但是,当Android尝试在运行时应用它时,它无法找到具有该id的元素。如果你看一下Logcat,你会看到:
W / View:找不到ID为2131689604的视图
此日志消息很难找到并且难以调试。 @+id/
中的一个小错字,你会有一个非常难以调试的错误。但是,如果我们做了:
android:nextFocusDown="@id/SOME_RANDOM_ID"
然后我们会遇到编译器错误,例如:
错误:(18,36)找不到与给定名称匹配的资源(在'nextFocusDown',值为'@ id / SOME_RANDOM_ID')。
这更易于查找和调试。
tl;博士:您可以使用@+id/
而不是@id/
,并且您将能够转发参考,但请注意,这可能会使小错误难以调试。
你或许可以使用RelativeLayout来使所有的视图在xml中以相反的顺序存在,但这对我来说似乎有些过分。
答案 1 :(得分:0)
我最近遇到了同样的问题,我第一次引用元素时使用了 @ + id / my_new_id ,后来在元素定义的XML中,我分配了 @ id / my_new_id 到 android:id 属性。它似乎工作正常,并且不必使用相同的id多次写@ + id以避免可能的警告。
例如:
<LinearLayout
...
android:layout_toLeftOf="@+id/my_new_id"
... >
...
</LinearLayout>
<ImageButton
android:id="@id/my_new_id"
... />