的「您正在搜索的樹的一部分」是ViewGroup
你打電話findViewById
通常孩子上。
在Activity
,該findViewById
方法是這樣實現的(source):
public View findViewById(int id) {
return getWindow().findViewById(id);
}
好了,如何做一個Window
實現findViewById
(source)?
public View findViewById(int id) {
return getDecorView().findViewById(id);
}
getDecorView
返回View
- 和所有的View
實施工作不就是返回本身(如果該視圖ID相匹配的一個傳遞),或者爲空(source):
public final View findViewById(int id) {
if (id < 0) {
return null;
}
return findViewTraversal(id);
}
protected View findViewTraversal(int id) {
if (id == mID) {
return this;
}
return null;
}
這是多少更有趣的,如果我們看一下一個ViewGroup
(source)執行:
protected View findViewTraversal(int id) {
if (id == mID) {
return this;
}
final View[] where = mChildren;
final int len = mChildrenCount;
for (int i = 0; i < len; i++) {
View v = where[i];
if ((v.mPrivateFlags & PFLAG_IS_ROOT_NAMESPACE) == 0) {
v = v.findViewById(id);
if (v != null) {
return v;
}
}
}
return null;
}
所以您會看到一個ViewGroup
遍歷其孩子搜索您通過的ID。我不確定mChildren
的順序,但我懷疑它會按照您將視圖添加到層次結構的順序(只是選中 - addView(View child)
確實會添加mChildren
列表末尾的視圖,其中addView(View child, int index)
在列表中的index
位置添加視圖)。
因此,對於您的示例,返回哪個按鈕將取決於您打電話給哪個ViewGroup
findViewById
。
如果您撥打anOutterLayout.findViewById(R.id.my_button)
,您會看到第一個按鈕 - 因爲它是第一個包含該ID的子元素。
如果您撥打anInnerLayout.findViewById(R.id.my_button)
,您會看到第二個按鈕。
但是,如果你的佈局文件是這樣的:
<AnOutterLayout>
<ASuitableInnerLayout>
<Button android:id="@+id/my_button".../>
</ASuitableInnerLayout>
<Button android:id="@+id/my_button".../>
</AnOutterLayout>
然後anOutterLayout.findViewById(R.id.my_button)
實際上返回按鈕內佈局內 - 因爲這種觀點逐層增加較早,因此早在爲該觀點的兒童名單。
這假定視圖按照它們在XML視圖層次結構中的順序添加。
林特會警告你,如果你有相同的佈局相同的編號 – Raghunandan