page.title=レイアウト page.tags=view,viewgroup @jd:body
レイアウトでは、アクティビティやアプリ ウィジェットの UI のような、ユーザー インターフェースの視覚的構造が定義されます。次の 2 つの方法でレイアウトを宣言できます。
Android フレームワークでは、アプリケーション UI の宣言と管理に、これらのいずれかのメソッドまたは両方のメソッドを柔軟に使うことができます。たとえば、レイアウトに表示されるスクリーン要素やそのプロパティを含む、アプリケーションのデフォルト レイアウトを XML で宣言できます。スクリーン オブジェクトの状態を変更するコードをアプリケーション内で追加できます(実行時の XML での宣言を含む)。
XML で UI を宣言する利点は、動作を制御するコードとアプリケーションの表示をうまく切り離すことができる点です。UI の記述は、アプリケーション コード外にあるため、ソースコードの変更や再コンパイルをすることなく、記述を修正したり改良したりできます。たとえば、異なる画面の向き、端末の画面サイズ、言語に対して XML レイアウトを作成できます。XML でレイアウトを宣言すると、UI の構造を簡単に視覚化できるため、問題のデバッグも簡単です。そのため、本書では XML でレイアウトを宣言する方法を中心に説明しています。実行時に View オブジェクトのインスタンスを作成することに関心がある場合は、{@link android.view.ViewGroup} と {@link android.view.View} クラス参照をご覧ください。
通常、UI 要素を宣言する XML ボキャブラリは、クラスとメソッドの構造と命名に厳密に従っており、要素名はクラス名に、属性名はメソッドに対応しています。実際、ほとんどの場合、直接的に対応しているため、クラスメソッドに対応する XML 属性を推測したり、与えられた XML 要素に対応するクラスを推測したりできます。ただし、すべてのボキャブラリが同一とは限りません。場合によっては、命名が若干異なります。たとえば、EditText 要素には、EditText.setText()
に対応する text
属性があります。
ヒント: 異なるレイアウト タイプの詳細については、共通レイアウト オブジェクトをご覧ください。 また、Hello Views のチュートリアル ガイドには、さまざまなレイアウトのビルドに関するチュートリアルがあります。
Android の XML ボキャブラリを使って、HTML でウェブページを作成するのと同じ方法で(ネストした一連の要素を使って)、UI レイアウトとそれに含まれる画面要素を素早く設計できます。
各レイアウト ファイルには、必ず 1 つのルート要素が含まれていて、そのルート要素は View または ViewGroup オブジェクトでなくてはなりません。ルート要素を定義すれば、追加のレイアウト オブジェクトやウィジェットを子の要素として追加して、レイアウトを定義するビュー階層を少しずつビルドできます。{@link android.widget.TextView} と {@link android.widget.Button} を保持するために、縦方向の {@link android.widget.LinearLayout} を使用する 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" > <TextView android:id="@+id/text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hello, I am a TextView" /> <Button android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hello, I am a Button" /> </LinearLayout>
XML でレイアウトを宣言した後、そのファイルを Android プロジェクトの res/layout/
ディレクトリ内で .xml
拡張子を付けて保存して、正しくコンパイルされるようにします。
レイアウト XML ファイルの構文の詳細については、「Layout Resources」のドキュメントをご覧ください。
アプリケーションをコンパイルすると、各 XML レイアウト ファイルは {@link android.view.View} リソースにコンパイルされます。
{@link android.app.Activity#onCreate(android.os.Bundle) Activity.onCreate()} コールバックの実装で、アプリケーション コードからレイアウト リソースを読み込んでください。これを行うには、{@link android.app.Activity#setContentView(int) setContentView()}
を呼び出し、R.layout.layout_file_name
の形式でレイアウト リソースへの参照を渡します。たとえば、XML レイアウトが main_layout.xml
として保存される場合、次のようにしてアクティビティに読み込みます。
public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main_layout); }
アクティビティの onCreate()
コールバック メソッドは、アクティビティが起動されるときに、Android フレームワークによって呼び出されます(ライフサイクルに関する説明については、「アクティビティ」のドキュメントをご覧ください)。
すべての View と ViewGroup オブジェクトでは、独自のさまざまな XML 属性がサポートされています。一部の属性は、View オブジェクト特有のものですが(たとえば TextView では textSize
属性がサポートされています)、これらの属性はこのクラスを拡張可能な View オブジェクトによっても継承されます。一部は、ルート View クラスから継承されるため、すべての View オブジェクトに共通します(id
属性のような)。
その他の属性は「レイアウト パラメータ」として考慮され、オブジェクトの親である ViewGroup オブジェクトとして定義された、View オブジェクトの特定のレイアウト方向を記述する属性となります。
ツリー内で View を一意に識別するために、すべての View オブジェクトには、それに関連付けられた整数の ID があることがあります。アプリケーションがコンパイルされると、この ID は整数として参照されますが、一般的にその ID は id
属性で文字列としてレイアウト XML ファイルに割り当てられます。これは、すべての View オブジェクトに共通の XML 属性で({@link android.view.View} クラスで定義)、非常に頻繁に使用されます。XML タグ内の ID の構文を次に示します。
android:id="@+id/my_button"
文字列の先頭にあるアットマーク(@)は、その XML パーサーが ID の残りの文字列をパースして展開し、それを ID リソースとして識別する必要があることを示します。
プラス記号(+)は、それが新しいリソース名で、作成してリソースに追加する(R.java
ファイル内で)必要があることを意味しています。
Android フレームワークによって提供されるその他のさまざまな ID リソースがあります。
Android リソース ID を参照するときは、プラス記号を使う必要はありませんが、次のように android
パッケージ名前空間を追加する必要があります。
android:id="@android:id/empty"
android
パッケージ名前空間付きの場合、ローカルのリソースクラスからではなく android.R
リソースクラスから ID を参照するようになります。
ビューを作成してアプリケーションからそれを参照するには、次のような共通のパターンがあります。
<Button android:id="@+id/my_button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/my_button_text"/>
{@link android.app.Activity#onCreate(Bundle) onCreate()}
メソッド内で)。
Button myButton = (Button) findViewById(R.id.my_button);
View オブジェクトの ID を定義することは、{@link android.widget.RelativeLayout} を作成するときに重要になります。相対レイアウトでは、兄弟ビューは一意の ID で参照される別の兄弟ビューに相対するレイアウトを定義できます。
ツリー全体で ID が一意である必要はありませんが、探しているツリーの一部では、一意である必要があります。ほとんどの場合、それはツリー全体になりますが、可能な時に完全に一意になるようにすることが最善です。
layout_something
という名前の XML レイアウト属性では、含まれている ViewGroup に適した View に対するレイアウト パラメータが定義されます。
すべての ViewGroup クラスでは、{@link android.view.ViewGroup.LayoutParams} を拡張するネストされたクラスが実装されます。このサブクラスには、各子ビューのサイズと位置を ViewGroup に合うように定義するプロパティ タイプが含まれています。 図 1 にあるように、親 ViewGroup によって、子 ViewGroup を含む、各子ビューのレイアウト パラメータが定義されます。
すべての LayoutParams サブクラスには、設定値に独自の構文があります。 それぞれの子の要素では、その親に適した LayoutParams が定義される必要がありますが、自分の子に対して異なる LayoutParams を定義することもできます。
すべての ViewGroup には、幅と高さ(layout_width
と layout_height
)が含まれていて、各ビューでそれが定義されている必要があります。
多くの LayoutParams には、省略可能なマージンと境界線も含まれています。
必要になる頻度は少ない可能性はありますが、幅と高さを正確なサイズで指定することもできます。 ほとんどの場合は、次の定数のいずれかを使って幅や高さを設定します。
通常、ピクセルなどの絶対単位でレイアウトの幅と高さを指定することは推奨されません。 密度非依存ピクセル単位(dp)、 wrap_content、 match_parentなどの相対測定を使う方が賢明です。そうすることで、さまざまな端末の画面サイズでアプリケーションが正しく表示されるようになります。使用可能な測定タイプは、「使用可能なリソース」のドキュメントで定義されています。
ビューの形状は、矩形です。ビューには、左と上の座標ペアで表される位置と、幅と高さで表される 2 次元があります。 位置と寸法の単位はピクセルです。
{@link android.view.View#getLeft()} と {@link android.view.View#getTop()} メソッドを呼び出してビューの位置を取得できます。
前者では、左またはビューを表す矩形の X 座標が返されます。
後者では、上またはビューを表す矩形の Y 座標が返されます。
これらのメソッドでは、両方とも親に相対するビューの位置が返されます。
たとえば、getLeft()
で 20 が返される場合、そのビューはその直属の親の左端から右に 20 ピクセルの位置にあることを意味します。
他にも、{@link android.view.View#getRight()} や {@link android.view.View#getBottom()} といった不要な計算を回避するさまざまな便利なメソッドが提供されています。
これらのメソッドでは、ビューを表す矩形の右端と下端の座標が返されます。
たとえば、{@link android.view.View#getRight()} を呼び出すことは、getLeft() + getWidth()
の計算と同様です。
ビューのサイズは、幅と高さで示します。実際に、ビューには幅と高さ 2 つの値がペアとして保持されています。
最初のペアは、測定された幅と測定された高さと呼ばれます。 これらの寸法で、その親内でのビューの大きさが定義されます。 測定された寸法は、{@link android.view.View#getMeasuredWidth()} と {@link android.view.View#getMeasuredHeight()} を呼び出して取得できます。
2 番目のペアは、単に幅と高さと呼ばれたり、描画する幅と描画する高さと呼ばれたりします。 これらの寸法は、描画時とレイアウト後に、画面上のビューの実サイズを定義するものです。 これらの値は、測定された幅や高さと異なる値にすることもできますが、必須ではありません。 幅と高さは、{@link android.view.View#getWidth()} と {@link android.view.View#getHeight()} を呼び出して取得できます。
その寸法を測るために、ビューではパディングも考慮されます。パディングは、ビューの上下左右に対し、ピクセルで記述されます。 パディングを使って、特定のピクセル値でビュー コンテンツのオフセットを指定できます。 たとえば、左側のパディングが 2 の場合は、左端から 2 ピクセル右にビューのコンテンツが寄せられます。 パディングは {@link android.view.View#setPadding(int, int, int, int)} メソッドを使って設定でき、{@link android.view.View#getPaddingLeft()}、{@link android.view.View#getPaddingTop()}、{@link android.view.View#getPaddingRight()}、{@link android.view.View#getPaddingBottom()} を呼び出してクエリできます。
ビューではパディングを定義できますが、マージンについてはサポートされていません。 ただし、ViewGroup ではそのようなサポートが提供されています。詳細については、{@link android.view.ViewGroup} と {@link android.view.ViewGroup.MarginLayoutParams} をご覧ください。
寸法の詳細については、寸法の値をご覧ください。
{@link android.view.ViewGroup} クラスの各サブクラスでは、ビュー内でネストするビューを表示する一意の方法が提供されます。 Android プラットフォームにビルドされる共通のレイアウト タイプの一部を以下に示します。
注: 別のレイアウト内で 1 つ以上のレイアウトをネストして UI を設計できますが、レイアウトの階層はできる限り浅くしておくようにしてください。 ネストが浅いレイアウトの場合、レイアウトの描画がより速くなります。深いビュー階層より、ワイドなビュー階層の方がより良いと言えます。
レイアウトのコンテンツが動的または事前設定されていないとき、{@link android.widget.AdapterView} のサブクラスのレイアウトを使って、実行時にビューでレイアウトを設定できます。 {@link android.widget.AdapterView} クラスのサブクラスでは、{@link android.widget.Adapter} を使ってそのレイアウトにデータがバインドされます。 {@link android.widget.Adapter} はデータソースと {@link android.widget.AdapterView} レイアウト間の仲介として動作します。{@link android.widget.Adapter} によって、配列やデータベース クエリのようなソースからデータが取得され、各エントリが {@link android.widget.AdapterView} レイアウトに追加できるビューに変換されます。
アダプタでサポートされている共通レイアウトには次が含まれます。
{@link android.widget.AdapterView} インスタンスを {@link android.widget.Adapter} にバインドして、{@link android.widget.ListView} や {@link android.widget.GridView} などの {@link android.widget.AdapterView} を入力できます。外部ソースのデータが取得され、各データエントリを表す {@link android.view.View} が作成されます。
Android ではさまざまな種類のデータの取得と {@link android.widget.AdapterView} のビューのビルドに役立つ {@link android.widget.Adapter} のサブクラスがいくつか提供されます。 最も一般的なアダプタは次の 2 つです。
たとえば、{@link android.widget.ListView} に表示する文字列の配列がある場合、コンストラクタを使って新しい {@link android.widget.ArrayAdapter} を初期化して、各文字列と文字列配列のレイアウトを指定します。
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, myStringArray);
このコンストラクタの引数を次に示します。
次に、{@link android.widget.ListView} で {@link android.widget.ListView#setAdapter setAdapter()} を呼び出します。
ListView listView = (ListView) findViewById(R.id.listview); listView.setAdapter(adapter);
各アイテムの概観をカスタマイズするには、自分の配列内のオブジェクトに {@link java.lang.Object#toString()} メソッドをオーバーライドします。または、たとえば各配列アイテムに {@link android.widget.ImageView} が必要な場合など、{@link android.widget.TextView} 以外の各アイテムの表示を作成するには、{@link android.widget.ArrayAdapter} クラスを拡張し、{@link android.widget.ArrayAdapter#getView getView()} をオーバーライドして、各アイテムに必要なビュータイプが返されるようにします。
String[] fromColumns = {ContactsContract.Data.DISPLAY_NAME, ContactsContract.CommonDataKinds.Phone.NUMBER}; int[] toViews = {R.id.display_name, R.id.phone_number};
{@link android.widget.SimpleCursorAdapter} のインスタンスを作成するとき、各結果に使うレイアウト、結果を含む {@link android.database.Cursor}、次の 2 つの配列を渡します。
SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, R.layout.person_name_and_number, cursor, fromColumns, toViews, 0); ListView listView = getListView(); listView.setAdapter(adapter);
次に、{@link android.widget.SimpleCursorAdapter} によって、対応する {@code toViews} ビューに各 {@code fromColumns} アイテムを挿入して提供されたレイアウトを使って {@link android.database.Cursor} で各行のビューが作成されます。
.アプリケーションのライフサイクル中に、アダプタによって読み取られる基礎となるデータを変更する場合は、{@link android.widget.ArrayAdapter#notifyDataSetChanged()} を呼び出してください。 これによって、データが変更されたアタッチされたビューが通知され、それ自体を更新する必要があることが通知されます。
{@link android.widget.AdapterView.OnItemClickListener} インターフェースを実装して {@link android.widget.AdapterView} の各アイテムでのクリック イベントに応答できます。 次に例を示します。
// Create a message handling object as an anonymous class. private OnItemClickListener mMessageClickedHandler = new OnItemClickListener() { public void onItemClick(AdapterView parent, View v, int position, long id) { // Do something in response to the click } }; listView.setOnItemClickListener(mMessageClickedHandler);