繁体   English   中英

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

[英]How can I assign an ID to a view programmatically?

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

我认为setId()与默认赋值不同。 setId()是额外的。

任何人都可以纠正我吗?

Android id概述

Android id是一个通常用于标识视图的整数; 这个id可以通过XML(如果可能),并且经由代码分配(编程)的id是用于获取用于XML定义的引用最有用的View S按一个产生Inflater (例如,通过使用setContentView 。)

通过XML分配id

  • 在您的视图中添加android:id="@+id/ somename "的属性。
  • 构建应用程序时,将为android:id分配一个唯一的 int ,以便在代码中使用。
  • 使用“ R.id. somename”(实际上是常量)在代码中引用你的android:idint值。
  • 这个int可以从build更改为build,所以永远不要复制 gen/ package.name/ R.java 的id ,只需使用“ R.id. somename”。
  • (另外,当Preference生成其View时,不会使用分配给XML中的Preferenceid 。)

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

  • 使用someView.setId( int );手动设置id );
  • int必须是正数,否则是任意的 - 它可以是你想要的任何东西(如果这是可怕的话,继续阅读。)
  • 例如,如果创建和编号表示项目的多个视图,则可以使用其项目编号。

id的唯一性

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

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

  • findViewById(int)将从您指定的视图中以递归方式迭代遍历视图层次结构并返回其找到的具有匹配id的第一个View
  • 只要在层次结构中的XML定义的id之前没有分配代码分配的idfindViewById(R.id.somename)将始终返回XML定义的View,因此id d。

动态创建视图和分配ID

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

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

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

保留XML android:id以在代码中使用

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

如果无法通过XML定义ViewGroup (或者您不希望它),则可以通过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都具有12的id 但是,如果我们查询占位符的子视图,这不是一个真正的问题:

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

*没那么糟糕

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

根据View文档

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

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

相信这个答案

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM