如何以编程方式为视图分配ID?

时间:2011-12-10 23:17:13

标签: android android-view android-resources findviewbyid android-identifiers

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

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

有人可以纠正我吗?

3 个答案:

答案 0 :(得分:508)

Android id概述

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

通过setContentView

分配id
  • 在您的视图中添加XML somename android:id="@+id/的属性。
  • 构建应用程序后,系统会为"分配唯一 android:id,以便在代码中使用。
  • 使用“int somename”在代码中引用android:id的{​​{1}}值(实际上是常量。)
  • int可以从构建更改为,因此永远不会从R.id. package.name / int复制ID ,只需使用“gen/ somename”。
  • (另外,当R.java生成R.id.时,不会使用分配给XML id的{​​{1}}。)

通过代码(以编程方式)

分配Preference
  • 使用Preference int View
  • 手动设置id
  • id必须是正面的,但在其他方面是任意的 - 它可以是你想要的任何东西(如果这是可怕的话,请继续阅读。)
  • 例如,如果创建和编号表示项目的多个视图,则可以使用其项目编号。

someView.setId( s

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

何时(和为什么)冲突XML无关紧要

  • id将通过您指定的视图中的视图层次结构以递归方式迭代深度,并返回其找到的匹配id的第一个id
  • 只要在层次结构中的XML定义的findViewById(int)之前没有分配代码分配的Viewid将始终返回XML定义的视图{{1 }}'d。

动态创建视图并分配id s

  • 在布局XML中,使用id定义空findViewById(R.id.somename)
  • 例如id ID
  • 使用代码使用ViewGroup s。
  • 填充占位符id
  • 如果您需要或想要,请指定方便每个视图的任何LinearLayout
  • 使用placeholder.findViewById(convenientInt)查询这些子视图;

  • API 17引入了android:id="@+id/placeholder",允许您生成唯一ID。

如果您选择保留对您的观点的引用,请务必使用ViewGroup对其进行实例化,并确保在View中将每个引用设置为null。显然泄漏 id(在被销毁之后挂在它上面)是浪费的.. :)

保留XML View.generateViewId()以用于代码

API 17引入了 getApplicationContext() ,它会生成一个唯一的ID。(感谢抓取机会 - 制作更改以指出这一点。)*

如果无法通过XML定义onDestroy(或者您不希望它),则可以通过XML保留ID以确保它保持唯一:

此处, values / ids.xml 定义了自定义Activity

android:id

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

View.generateViewId()

冲突ViewGroup示例

为了清楚地通过混淆示例,让我们来看看幕后发生id冲突时会发生什么。

<强>布局/ mylayout.xml

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

要模拟冲突,请说明我们的最新版本已分配myViewGroup.setId(R.id.reservedNamedId); idid值为 <?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> ..

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

R.id.placeholder

所以@+id/placeholder和我们的新int之一都有12 12!但是,如果我们查询占位符的子视图,这不是一个真正的问题:

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);
}

*不太糟糕

答案 1 :(得分:6)

您可以使用View.setId(integer)来实现此目的。在XML中,即使您正在设置String id,也会将其转换为整数。因此,您可以对以编程方式添加的Views使用任何(正)整数。

  

根据View文档

     
    

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

  
     

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

this answer的信用。

答案 2 :(得分:5)

是的,您可以在任何视图中使用您喜欢的任何(正)整数值调用setId(value),然后使用findViewById(value)在父容器中找到它。请注意,对于不同的兄弟视图,使用相同的值调用setId()是有效的,但findViewById()将仅返回第一个。