如何在布局 XML 文件中使用 include 标签时指定 ID

128
在我的布局xml文件中,我已经包含了其他的布局xml文件(每个文件都有一个不同的android ID)。
<include layout="@layout/view_contact_name" android:id="+id/test1"/>
<include layout="@layout/view_contact_name" android:id="+id/test2"/>

但是当我在模拟器中运行它,并启动层次结构查看器时,每个布局仍显示“NO_ID”,而在我的代码中,我有findViewById(R.id.test1)findViewById(R.id.test2)都返回null。

请问是否有人能够帮助我解决问题?


8
您的ID缺少@符号。 - AutonomousApps
12个回答

313

<include>中指定ID。

<include layout="@layout/test" android:id="@+id/test1" />

然后使用两个findViewById来访问布局中的字段

View test1View = findViewById(R.id.test1);
TextView test1TextView = (TextView) test1View.findViewById(R.id.text);

使用这种方法,您可以访问您拥有的任何包含文件中的任何字段。


23
这个方法返回了一个空值(null),无法获得test1View对象。 - Nirav Shah
6
我不太看出区别,你能解释一下吗? - Goddchen
33
我发现,如果所包含的布局使用了合并(merge)方法,这将无法起到帮助作用。但在未使用合并方法的情况下,这是有效的。 - Zlatko
@Zlatko没错,即使从理论上讲,这也无法与merge一起使用,因为包含merge的结果不是单个视图,而是一堆视图。所以没问题。 - Display Name
那么如果包括<merge>,有什么需要做的吗? - Ampers4nd
1
只有在不使用合并的情况下才能起作用。如果使用合并,则无法实现,如此处所指定的:https://code.google.com/p/android/issues/detail?id=36918#c3 - Zahid Rasheed

66

我发现,如果在您的包含布局中使用<merge>标记,则include的ID将转移到不是真实视图的合并标记。

因此,要么删除merge标记,要么将其替换为某个布局。

Tor Norbye 写道:

<include>标记不是真正的视图,因此findByView将无法找到它。 @id属性(以及您在include标记上设置的任何其他属性)将应用于所包含布局的根标记上。 因此,您的activity.getView(R.id.included1)实际上应该是<TextView>本身。


3
好的。我删除了合并标签,它开始正常工作。但是我在这里的问题是,如果没有它包含布局也能正常工作,那么合并标签的用法是什么? - Ankur Chaudhary

44

Romain Guy 指出,您可以通过在<include>标签内添加android:id属性来覆盖包含布局的ID。

<include android:id="@+id/cell1" layout="@layout/workspace_screen" />

1
这是正确的。在包含的布局文件中引用根元素的方法是使用“include”标记中给定的ID(除非未给出)。 - Tom R
1
<include>标签中的ID = 包含布局中根元素的ID - Fadils
我认为如果我先设置id(在include标签中),它会覆盖包含布局的id,对吗?这样,我将使include标签最初为“@+id/cell1”,然后layout ='@layout/workspace_screen'将再次使用包含布局的id覆盖android:id。 @Ron Romero的答案对我更有意义。 - Neon Warge

22

我认为排名第一的答案忽略了最重要的一点,并可能会让人们误以为<include/>标签创建了一个包含所需内容的视图。

关键在于include的id被传递给所包含布局文件的根视图。

这意味着:

// activity_main.xml
<include layout="@layout/somelayout" android:id="@+id/someid"/>

// somelayout.xml
<?xml version="1.0" encoding="utf-8"?>
<ImageView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    />

变成这样:

// activity_main.xml
<ImageView
    android:id="@+id/someid"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    />

这是真的。这让我更清楚了。谢谢。 - ZarNi Myo Sett Win

4

是这样的,但是当插入到包含字段中的布局是自定义的,并且您想要访问该根布局时,请注意。在这种情况下,@layout/test test中的布局实际上是在第一行返回的。

test test1View = (test)findViewById(R.id.test1);

2
问题在于我们尝试使用当前布局文件中未声明的id。 不需要重新声明,可以使用@+id/来简单引用它。如果您通过Android Studio重构原始id名称,则还会在包含的布局中进行重构。
<include layout="@layout/toolbar"/>

<TextView
    android:id="@+id/txt_description"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    **android:layout_below="@+id/toolbar"**
    android:layout_marginTop="16dp"
    android:paddingLeft="8dp"
    android:paddingRight="8dp"/>

2
在使用<RecyclerView>时,如果不使用已经充气的视图实例查找<include>的ID,则会返回null。请注意保留HTML标签。
public class ViewHolder extends RecyclerView.ViewHolder {

        private mTextView;

        public ViewHolder(View view) {
            super(view);
            View include_1 = view.findViewById(R.id.include_1);
            mTextView = (TextView) include_1.findViewById(R.id.text_id);
        }
    }

2

1
如果您已将id设置为包含布局的根标签之一,则可以使用该id,或者您可以将id设置为包含的布局。但是,不能同时设置两个id,否则可能会抛出异常。
<include layout="@layout/view_contact_name" android:id="+id/test1"/>

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

....
</LinearLayout>

或者

<include layout="@layout/view_contact_name"/>

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
        android:id="@+id/llBottomMainView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

....
</LinearLayout>

0

当谈到include时,您可以在包含的布局文件中的根视图上具有id,也可以在include行本身上具有id,但不能同时具有。例如:

<include layout="@layout/layout1" android:id="@+id/layout1"/>

布局1文件

<RelativeLayout
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/layout2">

</RelativeLayout>

上面的例子是错误的,因为在同一个布局中技术上声明了两个id。所以你需要选择哪个元素将拥有这个id。

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