209

XML ファイルでは、 のようなビューに ID を割り当てて をandroid:id="@+id/something"呼び出すことができfindViewById()ますが、プログラムでビューを作成する場合、ID を割り当てるにはどうすればよいでしょうか?

setId()デフォルトの割り当てと同じではないと思います。setId()余分です。

誰でも私を修正できますか?

4

3 に答える 3

533

Androididの概要

Androididは、ビューを識別するために一般的に使用される整数です。これは、XML (可能な場合) およびコード(idプログラム) を介して割り当てることができます。idViewInflatersetContentView

割り当てid_XML

  • android:id="@+id/ビューにsomenameの属性を追加"します。
  • アプリケーションがビルドされると、コードで使用するために一意android:idのが割り当てられます。 int
  • 「 somename」を使用してコード内android:idの のint値を参照します(実質的には定数です)。R.id.
  • これintはビルドごとに変わる可能性があるため、 package.name /からID をコピーしないでください。「 somename」を使用してください。gen/R.javaR.id.
  • (また、XML で にid割り当てられた は、がその を生成するときに使用されません)。PreferencePreferenceView

コードによる割り当てid(プログラムによる)

  • intidを使用して s を手動で設定するsomeView.setId();
  • int正でなければなりませんが、それ以外は恣意的です - それはあなたが望むものであれば何でもかまいません (これが恐ろしい場合は読み続けてください.)
  • たとえば、アイテムを表す複数のビューを作成して番号を付ける場合、それらのアイテム番号を使用できます。

ids の一意性

  • XML-割り当てられidた は一意になります。
  • コード割り当ては一意であるid必要はありませ
  • コードで割り当てられたidは (理論的には) -割り当てられた と競合する可能性がありXMLますid
  • これらの競合するids は、正しく照会されれば問題になりません(読み続けてください)

id競合するs が問題にならない場合 (およびその理由)

  • findViewById(int)指定したビューからビュー階層を深さ優先で再帰的に反復Viewし、一致する最初に見つかったものを返しますid
  • 階層内でidXML 定義の前にコード割り当て が割り当てられていない限り、常に XML 定義のビューを返します。idfindViewById(R.id.somename)id

ビューの動的な作成とIDs の割り当て

  • レイアウト XML で、空のViewGroupwith を定義しidます。
  • など。LinearLayout_android:id="@+id/placeholder"
  • コードを使用して、プレースホルダーViewGroupViews を設定します。
  • 必要に応じidて、各ビューに便利な を割り当てます。
  • placeholder.findViewById(convenientInt); を使用してこれらの子ビューをクエリします。

  • API 17 が導入さView.generateViewId()れ、一意の ID を生成できるようになりました。

ビューへの参照を保持することを選択した場合は、必ず でそれらをインスタンス化し、 でgetApplicationContext()各参照を null に設定してくださいonDestroy。どうやら(が破壊された後にそれにぶら下がっている)リークActivity無駄です.. :)

android:idコードで使用するためにXML を予約する

View.generateViewId() 一意の ID を生成するAPI 17 が導入されました。(これを指摘してくれた take-chances-make-changes に感謝します。)*

XML 経由で定義できない場合ViewGroup(または定義したくない場合) は、XML 経由で ID を予約して、ID が一意であることを確認できます。

ここで、values/ids.xmlは custom を定義します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の 1 つは両方とも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);

*そんなに悪くない

于 2012-11-05T22:45:50.790 に答える
6

これには を使用できますView.setId(integer)。XML では、文字列 ID を設定していても、これは整数に変換されます。このため、Views プログラムで追加する任意の (正の) 整数を使用できます。

Viewドキュメントによると

識別子は、このビューの階層内で一意である必要はありません。識別子は正の数でなければなりません。

したがって、任意の正の整数を使用できますが、この場合、同等の ID を持つビューがいくつか存在する可能性があります。階層内のいくつかのビューを検索する場合は、いくつかのキー オブジェクトを使用して setTag を呼び出すと便利な場合があります。

この回答へのクレジット。

于 2011-12-10T23:43:55.903 に答える
5

はい、setId(value)任意の(正の)整数値を使用して任意のビューを呼び出し、を使用して親コンテナーでそれを見つけることができますfindViewById(value)setId()異なる兄弟ビューに対して同じ値で呼び出すことは有効ですがfindViewById()、最初のビューのみを返すことに注意してください。

于 2011-12-10T23:39:02.020 に答える