簡體   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