稍后在文件中安装Android布局参考xml元素

时间:2015-08-04 20:27:47

标签: android xml android-layout android-linearlayout

如何引用以后的XML元素?

这是一个特定的用例。我们假设我有一个带有LinearLayout根的表单,其中包含多行的LinearLayouts,每行包含一个或多个文本输入区域。

这里是我想要的视觉效果。第一张图片来自Venmo的应用程序,第二张是以下XML的呈现。

Example of Venmo The layout

这样的布局可能如下所示:

<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?

2 个答案:

答案 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"
    ... />