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

Anu*_*oob 5 xml android android-layout android-linearlayout

如何引用以后的XML元素?

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

这是我想要的视觉效果.第一张照片来自Venmo的应用程序,第二张是以下XML的渲染.

Venmo的例子 布局

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

<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>
Run Code Online (Sandbox Code Playgroud)

在这个用例中,前向引用是必要的,以便设置下一个焦点元素.这样,当您按下键盘上的下一个按钮时,它将转到正确的视图.在这个样本xml中,没有nextFocusDowns,按下next将从名称到月份,并且永远不会去年.

但是,如果您尝试编译它,您将收到一个错误:

错误:(18,36)找不到与给定名称匹配的资源(在'nextFocusDown',值为'@id/month').

这是因为month当我尝试引用它时,id 尚未初始化,因为它稍后在文件中.如何引用文件中稍后出现的xml中的id?

Anu*_*oob 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"/>
Run Code Online (Sandbox Code Playgroud)

解析它时,SOME_RANDOM_ID会创建一个新的id元素.但是,当Android尝试在运行时应用它时,它无法找到具有该id的元素.如果你看一下Logcat,你会看到:

W/View:找不到ID为2131689604的视图

此日志消息很难找到并且难以调试.a中的一个小错字,@+id/你会有一个非常难以调试的错误.但是,如果我们做了:

android:nextFocusDown="@id/SOME_RANDOM_ID"

然后我们会得到编译器错误,例如:

错误:(18,36)找不到与给定名称匹配的资源(在'nextFocusDown',值为'@id/SOME_RANDOM_ID').

这更容易查找和调试.


tl; dr:您可以使用@+id/而不是@id/并且您将能够转发引用,但请注意,这可能会使小错误调整难以置信.

您可以使用RelativeLayout来使所有视图在xml中以相反的顺序存在,但这对我来说似乎有些过分.