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

Duy*_*guK 195 android android-view findviewbyid android-resources android-identifiers

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

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

任何人都可以纠正我吗?

Cod*_*ane 512

Android id概述

Android id是一个常用于识别视图的整数; 这id可以通过XML(如果可能)和通过代码(以编程方式)分配.id对于获取ViewInflater(由使用setContentView.)生成的XML定义的s的引用最有用.

分配id通过XML

  • 在视图中添加android:id="@+id/somename 属性".
  • 构建应用程序时,android:id将为代码分配一个唯一 int的应用程序.
  • 使用" somename"(实际上是常量)在代码中引用您android:idintR.id..
  • int可以从构建更改为构建,所以永远不要gen/package.name/ 复制idR.java,只需使用" R.id.somename".
  • (此外,生成它时,不会使用id分配给PreferenceXML PreferenceView.)

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

  • id使用someView.setId(int 手动设置s);
  • int必须是积极的,但在其他方面arbitrary-它可以是任何你想要的(请继续阅读,如果这是可怕的.)
  • 例如,如果创建和编号表示项目的多个视图,则可以使用其项目编号.

ids的独特性

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

何时(和为什么)冲突id并不重要

  • findViewById(int)将从您指定的视图中以递归方式迭代深度优先于视图层次结构,并返回View匹配时找到的第一个深度id.
  • 只要在层次结构中id定义的XML之前没有分配代码分配id,findViewById(R.id.somename)就会始终返回XML定义的视图id.

动态创建视图和分配ID小号

  • 在布局XML中,定义一个空ViewGroupid.
  • LinearLayoutandroid:id="@+id/placeholder".
  • 使用代码ViewGroupViews 填充占位符.
  • 如果您需要或想要,请id为每个视图分配任何便利的.
  • 使用placeholder.findViewById(convenientInt)查询这些子视图;

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

如果您选择保留对视图的引用,请务必使用它们进行实例化,getApplicationContext()并确保将每个引用设置为null onDestroy.显然,泄漏Activity(挂到它之后被销毁)是一种浪费.. :)

保留XML android:id以用于代码

引入了API 17 View.generateViewId() ,它生成一个唯一的ID.(感谢抓住机会 - 改变指出这一点.)*

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

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

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <item name="reservedNamedId" type="id"/>
</resources>
Run Code Online (Sandbox Code Playgroud)

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

myViewGroup.setId(R.id.reservedNamedId);
Run Code Online (Sandbox Code Playgroud)

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

为了模拟冲突,让我们说最新的build 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);
}
Run Code Online (Sandbox Code Playgroud)

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

*没那么糟糕

  • 除此之外,对于编码类似解决方案的人来说,了解API> 17中的View.generateViewId()对于非冲突的ID可能是有用的 (9认同)

San*_*eer 6

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

根据View文件

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

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

相信这个答案.


dmo*_*mon 5

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