209

在 XML 文件中,我们可以为视图分配一个 ID android:id="@+id/something",然后调用findViewById(),但是当以编程方式创建视图时,我如何分配一个 ID?

我认为setId()与默认分配不同。setId()是额外的。

有人可以纠正我吗?

4

3 回答 3

533

安卓id概览

Androidid是一个整数,通常用于标识视图;这id可以通过 XML(如果可能)和代码(以编程方式)分配。这对于获取由 an 生成的idXML 定义的引用最有用(例如通过使用.)ViewInflatersetContentView

分配id方式XML

  • android:id="@+id/将somename的属性添加"到您的视图中。
  • 当您的应用程序被构建时,android:id将被分配一个唯一 int的以供在代码中使用。
  • 使用“ somename”(实际上是一个常量)在代码中引用您android:id的值。intR.id.
  • int可以从构建更改为构建,因此永远不要从package.name/复制 id,只需使用“ somename”。gen/R.javaR.id.
  • (此外,在生成其时不使用id分配给XML 中的 a 。)PreferencePreferenceView

通过代码分配id(以编程方式)

  • 使用int手动设置idssomeView.setId();
  • 必须是肯定的int,但在其他方面是任意的——它可以是你想要的任何东西(如果这很可怕,请继续阅读。)
  • 例如,如果创建多个表示项目的视图并为其编号,则可以使用它们的项目编号。

ids的唯一性

  • XML-assigned ids 将是唯一的。
  • 代码分配id的 s 不必唯一的
  • Code-assigned ids 可以(理论上)与XML-assigned ids 冲突。
  • 如果查询正确(继续阅读) ,这些冲突id的 s 将无关紧要。

何时(以及为什么)冲突id的 s 无关紧要

  • findViewById(int)将从您指定的视图中递归地遍历视图层次结构,并返回View它找到的第一个具有匹配的id.
  • 只要在层次结构中id的 XML-defined 之前没有分配 code-assigned ,就会始终返回 XML-defined View so 'd。idfindViewById(R.id.somename)id

动态创建视图并ID分配

  • 在布局 XML 中,ViewGroup使用id.
  • 比如一个LinearLayoutwith android:id="@+id/placeholder"
  • ViewGroup使用代码用Views填充占位符。
  • 如果您需要或想要,id为每个视图分配任何方便的 s。
  • 使用 placeholder.findViewById(convenientInt); 查询这些子视图

  • 引入的 API 17View.generateViewId()允许您生成唯一 ID。

如果您选择保留对您的视图的引用,请确保将它们实例化getApplicationContext()并确保将每个引用设置为 null in onDestroy。显然泄漏(在Activity被销毁后挂在上面)是浪费的.. :)

保留 XMLandroid:id以在代码中使用

引入的 API 17 View.generateViewId() 可生成唯一 ID。(感谢 take-chances-make-changes 指出这一点。)*

如果您ViewGroup不能通过 XML 定义(或者您不希望这样),您可以通过 XML 保留 id 以确保它保持唯一:

在这里,values/ids.xml定义了一个自定义id

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <item name="reservedNamedId" type="id"/>
</resources>

然后,一旦创建了 ViewGroup 或 View,您就可以附加自定义 id

myViewGroup.setId(R.id.reservedNamedId);

冲突的id例子

为了清楚起见,通过混淆示例,让我们检查当id幕后发生冲突时会发生什么。

布局/mylayout.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >
    <LinearLayout
        android:id="@+id/placeholder"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal" >
</LinearLayout>

为了模拟冲突,假设我们最新的构建分配R.id.placeholder( @+id/placeholder) 的int值是 12..

接下来,MyActivity.java 以编程方式(通过代码)定义了一些添加视图:

int placeholderId = R.id.placeholder; // placeholderId==12
// returns *placeholder* which has id==12:
ViewGroup placeholder = (ViewGroup)this.findViewById(placeholderId);
for (int i=0; i<20; i++){
    TextView tv = new TextView(this.getApplicationContext());
    // One new TextView will also be assigned an id==12:
    tv.setId(i);
    placeholder.addView(tv);
}

因此placeholder,我们的一个新TextView产品都有id12 个!但是,如果我们查询占位符的子视图,这并不是真正的问题:

// Will return a generated TextView:
 placeholder.findViewById(12);

// Whereas this will return the ViewGroup *placeholder*;
// as long as its R.id remains 12: 
Activity.this.findViewById(12);

*没那么糟糕

于 2012-11-05T22:45:50.790 回答
6

你可以使用View.setId(integer)这个。在 XML 中,即使您设置了 String id,它也会被转换为整数。因此,您可以使用任何(正)整数来以Views 编程方式添加。

根据View文档

标识符在此视图的层次结构中不必是唯一的。标识符应该是一个正数。

所以你可以使用任何你喜欢的正整数,但在这种情况下,可能会有一些具有等效 ID 的视图。如果您想在层次结构中搜索某些视图,使用一些关键对象调用 setTag 可能会很方便。

归功于这个答案

于 2011-12-10T23:43:55.903 回答
5

是的,您可以setId(value)使用您喜欢的任何(正)整数值在任何视图中调用,然后使用findViewById(value). 请注意,setId()对于不同的同级视图使用相同的值调用是有效的,但findViewById()只会返回第一个。

于 2011-12-10T23:39:02.020 回答