我如何以编程方式将ID分配给视图?
在一个XML文件中,我们可以像android:id="@+id/something"
一样为一个视图分配一个ID,然后调用findViewById()
,但是当以编程方式创build一个视图时,如何分配一个ID?
我认为setId()
是不一样的默认分配。 setId()
是额外的。
有人可以纠正我吗?
Android id
概览
Android id
是一个通常用于识别视图的整数。 这个id
可以通过XML(如果可能的话)和通过代码(以编程方式)分配。id对于获取由Inflater
生成的XML定义的View
的引用(例如通过使用setContentView
)是非常有用的。
通过XML
分配id
- 将
android:id="@+id/
somename"
的属性添加到您的视图中。 - 在构build应用程序时,
android:id
将被分配一个唯一的int
用于代码。 - 在代码中使用“
R.id.
somename”引用你的android:id
的int
值(实际上是一个常量)。 - 这个
int
可以从构build变为构build,所以不要从gen/
package.namegen/
R.java
复制一个id ,只需使用“R.id.
somename”即可。 - (此外,在
Preference
生成View
时,不会使用分配给XML中的Preference
的id
。
通过代码分配id
(以编程方式)
- 手动设置
id
使用someView.setId(
INT);
-
int
必须是正数,但在其他方面是任意的 – 它可以是任何你想要的(如果这是可怕的,请继续阅读)。 - 例如,如果创build和编号代表项目的几个视图,您可以使用他们的项目编号。
id
的唯一性
-
XML
分配的id
将是唯一的。 - 代码分配的
id
不必是唯一的 - 代码分配的
id
可以(理论上)与XML
分配的id
冲突。 - 如果查询正确,这些冲突的
id
将无关紧要(继续阅读) 。
何时(以及为什么)冲突的id
不重要
-
findViewById(int)
将从您指定的View中recursion地遍历视图层次结构,并返回它find的第一个View
和一个匹配的id
。 - 只要在层次结构中的XML定义的
id
之前没有分配代码分配的id
,findViewById(R.id.somename)
将始终返回XML定义的View,因此id
“d”。
dynamic创build视图并分配ID
- 在布局XML中,用
id
定义一个空的ViewGroup
。 - 比如带有
android:id="@+id/placeholder"
的LinearLayout
。 - 使用代码使用
View
来填充占位符ViewGroup
。 - 如果您需要或想要,请为每个视图指定方便的
id
。 -
使用placeholder.findViewById(convenienceInt)查询这些子视图;
-
API 17引入了
View.generateViewId()
,它允许你生成一个唯一的ID。
如果select保持对视图的引用,请确保使用getApplicationContext()
实例化它们,并确保在onDestroy
中将每个引用设置为null。 显然泄露 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>
然后,一旦创build了ViewGroup或View,您可以附加自定义ID
myViewGroup.setId(R.id.reservedNamedId);
相冲突的例子
通过混淆示例的方式来澄清,让我们来看看在幕后出现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中,即使您设置了stringID,也会将其转换为整数。 由于这个原因,您可以使用任何(正数)整数来以编程方式添加的Views
。
根据
View
文档标识符在该视图的层次结构中不必是唯一的。 标识符应该是一个正数。
所以你可以使用你喜欢的任何正整数,但在这种情况下,可以有一些视图与等效的ID。 如果你想在层次结构中search一些视图,调用setTag和一些关键对象可能会很方便。
学分到这个答案 。
是的,您可以在任何视图中使用您喜欢的任何(正数)整数值调用setId(value)
,然后使用findViewById(value)
在父容器中find它。 请注意,为不同的同级视图调用setId()
具有相同的值是有效的,但findViewById()
将仅返回第一个。
- 当ViewPager的父代片段隐藏然后显示ViewPager的片段的视图丢失
- 创build模糊的透明背景效果
- 设置Slidemenu – 示例不工作
- getExtractedText在android上处于非活动状态的InputConnection警告
- Android:HTTP通讯应该使用“Accept-Encoding:gzip”
- Android如何在一个活动中一个接一个地显示2个列表视图
- 这个应用程序没有configurationAndroid密钥散列。 – 使用Facebook SDK进行login
- 安全地修复:javax.net.ssl.SSLPeerUnverifiedException:没有对等证书
- 如何退出应用程序并显示主屏幕?