Android 布局引用 xml 文件后面的元素
Android layout reference xml element later in file
如何引用后面的 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>
在这个用例中,前向引用是必要的,以便设置下一个焦点元素。这样,当您按下键盘上的下一个按钮时,它会转到正确的视图。在此示例 xml 中,如果没有 nextFocusDown
,按下一步将从名称转到月份,而永远不会转到年份。
但是,如果您尝试编译它,您会得到一个错误:
Error:(18, 36) No resource found that matches the given name (at 'nextFocusDown' with value '@id/month').
这是因为当我试图引用它时,id month
还没有被初始化,因为它在文件的后面。如何引用 xml 中稍后出现在文件中的 ID?
最简单的解决方案就是更换
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﹕ couldn't find view with id 2131689604
此日志消息既难以查找又难以调试。 @+id/
中的一个小错字,您将遇到一个非常难以调试的错误。但是,如果我们这样做了:
android:nextFocusDown="@id/SOME_RANDOM_ID"
然后我们会得到一个编译器错误,类似于:
Error:(18, 36) No resource found that matches the given name (at 'nextFocusDown' with value '@id/SOME_RANDOM_ID').
这更容易查找和调试。
tl;dr:您可以使用 @+id/
而不是 @id/
并且您将能够转发参考,但请注意,这会使小的拼写错误变得非常难以调试。
您也许可以使用 RelativeLayout 使所有视图以相反的顺序存在于 xml 中,但这对我来说似乎有点过分了。
我最近遇到了同样的问题,我第一次引用元素时使用了@+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"
... />
如何引用后面的 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>
在这个用例中,前向引用是必要的,以便设置下一个焦点元素。这样,当您按下键盘上的下一个按钮时,它会转到正确的视图。在此示例 xml 中,如果没有 nextFocusDown
,按下一步将从名称转到月份,而永远不会转到年份。
但是,如果您尝试编译它,您会得到一个错误:
Error:(18, 36) No resource found that matches the given name (at 'nextFocusDown' with value '@id/month').
这是因为当我试图引用它时,id month
还没有被初始化,因为它在文件的后面。如何引用 xml 中稍后出现在文件中的 ID?
最简单的解决方案就是更换
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﹕ couldn't find view with id 2131689604
此日志消息既难以查找又难以调试。 @+id/
中的一个小错字,您将遇到一个非常难以调试的错误。但是,如果我们这样做了:
android:nextFocusDown="@id/SOME_RANDOM_ID"
然后我们会得到一个编译器错误,类似于:
Error:(18, 36) No resource found that matches the given name (at 'nextFocusDown' with value '@id/SOME_RANDOM_ID').
这更容易查找和调试。
tl;dr:您可以使用 @+id/
而不是 @id/
并且您将能够转发参考,但请注意,这会使小的拼写错误变得非常难以调试。
您也许可以使用 RelativeLayout 使所有视图以相反的顺序存在于 xml 中,但这对我来说似乎有点过分了。
我最近遇到了同样的问题,我第一次引用元素时使用了@+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"
... />