以前、レイアウトXMLで定義されているウィジェットの取得方法を紹介しました。
今回は、レイアウトXML自体をソースコード上にViewとして取得する方法を紹介します。
レイアウトXMLを取得するには LayoutInflater#inflateメソッドを使用します。
そこで、まず最初にContextから LayoutInflaterクラスを取得するのですが、なんと3種類の方法があります。
※ 以下のソースコードは Activityクラス内で呼ばれています。
レイアウトXMLから取得したビューを画面に反映させるには以下のコードになります。
リソースIDで指定した方が簡単に済む!
と思うかもしれませんが、Viewクラスとして取得することでできることもあります。
たとえば、独自のリストビューを作ったり、ダイアログに設定したり。
他にも色々使いどころはあるので覚えておきましょう。
今回は、レイアウトXML自体をソースコード上にViewとして取得する方法を紹介します。
レイアウトXMLを取得するには LayoutInflater#inflateメソッドを使用します。
そこで、まず最初にContextから LayoutInflaterクラスを取得するのですが、なんと3種類の方法があります。
※ 以下のソースコードは Activityクラス内で呼ばれています。
// コンテキストから取得このように複数の方法がありますが、結果はどれも同じです。
LayoutInflater inflater1 = LayoutInflater.from(this);
// アクティビティから取得
LayoutInflater inflater2 = getLayoutInflater();
// システムサービスから取得
LayoutInflater inflater3 = (LayoutInflater)
getSystemService(Context.LAYOUT_INFLATER_SERVICE);
レイアウトXMLから取得したビューを画面に反映させるには以下のコードになります。
// レイアウトインフレーターを取得最後のビューを画面に反映する処理は、リソースIDを指定する setContentView(R.layout.main) と同じ結果になります。
LayoutInflater inflater1 = LayoutInflater.from(this);
// レイアウトXMLからビューを取得
View view = inflater.inflate(R.layout.main, null);
// ビューを画面に反映
setContentView(view);
リソースIDで指定した方が簡単に済む!
と思うかもしれませんが、Viewクラスとして取得することでできることもあります。
たとえば、独自のリストビューを作ったり、ダイアログに設定したり。
他にも色々使いどころはあるので覚えておきましょう。
ウィジェットにイベントを設定するには、イベントリスナーと呼ばれるインターフェースを使用します。
インターフェースの使用方法には、インプリメントするか、匿名クラス(無名クラス)の2種類があります。
インプリメントには、アクティビティにインプリメントする方法と、イベントリスナークラスを作成してそれにインプリメントする方法があるので、正確には3種類でしょうか…
オライリー社の書籍曰く、匿名クラスを使用した場合には約1キロバイトのメモリを余計に使用するため、インプリメントする方が良いそうです。
以下のサンプルは、ボタンのウィジェットをクリックした時にトースト通知するようになっています。
インプリメントで実装
17-18行目ではボタンにクリックイベントを設定し、引数に this を付ける事でアクティビティとイベントを紐付けています。
これで、ボタンをクリックする事で21-33行のイベント処理が実行されるようになります。
この方法だと複数のウィジェットにクリックイベントを設定した場合、同じView#onClickメソッドが呼ばれてしまいます。
そこで、引数のViewからgetId()を呼んで、ウィジェットの android:id を取得して判別します。
上記の理由により、ソースコードが冗長になってしまうことから匿名クラスを使用して実装する手法が多用されています。
インプリメントで実装されたソースコードを匿名クラスに書き換えると以下の様になります。
匿名クラスで実装
(良くなっていると思っています)
ネストが深くなってしまいますが、そこはカプセル化するなどで対応できます。
個人的にも匿名クラスでの実装の方が好きですが、優先すべきはメモリ。
MVCアーキテクチャによる実装手法のこともあるしインプリメントでの実装が正しそうです。
インターフェースの使用方法には、インプリメントするか、匿名クラス(無名クラス)の2種類があります。
インプリメントには、アクティビティにインプリメントする方法と、イベントリスナークラスを作成してそれにインプリメントする方法があるので、正確には3種類でしょうか…
オライリー社の書籍曰く、匿名クラスを使用した場合には約1キロバイトのメモリを余計に使用するため、インプリメントする方が良いそうです。
以下のサンプルは、ボタンのウィジェットをクリックした時にトースト通知するようになっています。
インプリメントで実装
package jp.inujirushi.sample;9行目でアクティビティにView#OnClickListenerをインプリメントしています。
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Toast;
public class SampleActivity extends Activity
implements View.OnClickListener {
/** アクティビティを生成したときに呼ばれます。 */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// ボタンにクリックイベントを設定
findViewById(R.id.button1).setOnClickListener(this);
}
/** ビューをクリックしたときに呼ばれます。 */
@Override
public void onClick(View view) {
// クリックされたビューに応じて処理を分岐
switch (view.getId()) {
// ボタンがクリックされた時
case R.id.button1:
Toast.makeText(this, "ボタンが押されました",
Toast.LENGTH_LONG).show();
break;
}
}
}
17-18行目ではボタンにクリックイベントを設定し、引数に this を付ける事でアクティビティとイベントを紐付けています。
これで、ボタンをクリックする事で21-33行のイベント処理が実行されるようになります。
この方法だと複数のウィジェットにクリックイベントを設定した場合、同じView#onClickメソッドが呼ばれてしまいます。
そこで、引数のViewからgetId()を呼んで、ウィジェットの android:id を取得して判別します。
上記の理由により、ソースコードが冗長になってしまうことから匿名クラスを使用して実装する手法が多用されています。
インプリメントで実装されたソースコードを匿名クラスに書き換えると以下の様になります。
匿名クラスで実装
package jp.inujirushi.sample;この様に、匿名クラスで実装するとインプリメントされたときよりも可読性が良くなります。
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
public class SampleActivity extends Activity {
/** アクティビティを生成したときに呼ばれます。 */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// ボタンを取得
Button button = (Button) findViewById(R.id.button1);
// ボタンにクリックイベントを追加
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// ボタンが押されるとトーストが表示される
Toast.makeText(SampleActivity.this,
"ボタンが押されました",
Toast.LENGTH_LONG).show();
}
});
}
}
(良くなっていると思っています)
ネストが深くなってしまいますが、そこはカプセル化するなどで対応できます。
個人的にも匿名クラスでの実装の方が好きですが、優先すべきはメモリ。
MVCアーキテクチャによる実装手法のこともあるしインプリメントでの実装が正しそうです。
Toast は画面に一時的なメッセージを表示するための機能です。
ダイアログとは違い、一定時間経過すると自動的に消えます。
API Reference: Toast
■ 画面イメージ -----------------------------------------------

■ ソースコードで定義 -----------------------------------------
ダイアログとは違い、一定時間経過すると自動的に消えます。
API Reference: Toast
■ 画面イメージ -----------------------------------------------

■ ソースコードで定義 -----------------------------------------
package jp.inujirushi.sample.activity;
import jp.inujirushi.sample.R;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
public class ToastActivity extends Activity {
/** アクティビティを生成した時に呼ばれます。 */
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.sample_dialog);
// ボタンのクリックイベントにトースト通知を設定する
Button button = (Button) findViewById(R.id.button1);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
// トーストを生成する
Toast toast = Toast.makeText(
ToastActivity.this,
"メッセージ",
Toast.LENGTH_LONG);
// トーストを表示する
toast.show();
}
});
}
}
ImageView はレイアウト上に画像を表示するウィジェットです。
API Reference: ImageView
■ 画面イメージ -----------------------------------------------

※プロジェクト作成時に作られる res/drawable フォルダの icon.png を表示しています。
■ XMLで定義 --------------------------------------------------
■ ソースコードで定義 -----------------------------------------
javaで画像を取得するには、最初にresフォルダを参照するために、ContextWrapper#getResourcesメソッドからResourcesクラスを取得します。
次にdrawableフォルダから画像を取得するために、先ほど取得したResourcesクラスのgetDrawableメソッドを使用して画像を取得しています。
API Reference: ImageView
■ 画面イメージ -----------------------------------------------

※プロジェクト作成時に作られる res/drawable フォルダの icon.png を表示しています。
■ XMLで定義 --------------------------------------------------
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView android:id="@+id/imageView1"
android:src="@drawable/icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
■ ソースコードで定義 -----------------------------------------
package jp.inujirushi.sample.activity;
import jp.inujirushi.sample.R;
import android.app.Activity;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.widget.ImageView;
import android.widget.LinearLayout;
public class ImageViewActivity extends Activity {
/** アクティビティを生成した時に呼ばれます。 */
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// リソースから画像を取得する
Drawable drawable = getResources().getDrawable(R.drawable.icon);
// イメージビューを生成する
ImageView imageView = new ImageView(this);
// イメージビューに画像を設定する
imageView.setImageDrawable(drawable);
// レイアウトを生成する
LinearLayout layout = new LinearLayout(this);
// レイアウトにイメージビューを追加する
layout.addView(imageView);
// レイアウトを画面に設定する
setContentView(layout);
}
}
javaで画像を取得するには、最初にresフォルダを参照するために、ContextWrapper#getResourcesメソッドからResourcesクラスを取得します。
次にdrawableフォルダから画像を取得するために、先ほど取得したResourcesクラスのgetDrawableメソッドを使用して画像を取得しています。
ListView はレイアウト上に一覧を表示するウィジェットです。
API Reference: ListView, ListAdapter, ArrayAdapter
■ 画面イメージ -----------------------------------------------

■ ListView 注意事項 ------------------------------------------
ListView に表示する項目は ListAdapter と呼ばれるインターフェースを実装したクラスに設定しなくてはいけません。
なので、XMLのみで一覧を表示することはできません。
このサンプルでは文字列を表示するだけなので ArrayAdapter クラスを使用します。
第二引数で指定するリソースIDはListViewに表示する1項目のレイアウトXMLになります。
ここでは、Androidの標準のレイアウトである android.R.layout.simple_list_item_1 を指定しています。
なお、独自に定義したレイアウトXMLを指定することもできます。
※独自のレイアウトを指定した場合、 ListAdapter も独自で実装する必要があります。
■ XML + ソースコードで定義 -----------------------------------
XML
ソースコード
■ ソースコードで定義 -----------------------------------------
API Reference: ListView, ListAdapter, ArrayAdapter
■ 画面イメージ -----------------------------------------------

■ ListView 注意事項 ------------------------------------------
ListView に表示する項目は ListAdapter と呼ばれるインターフェースを実装したクラスに設定しなくてはいけません。
なので、XMLのみで一覧を表示することはできません。
このサンプルでは文字列を表示するだけなので ArrayAdapter クラスを使用します。
第二引数で指定するリソースIDはListViewに表示する1項目のレイアウトXMLになります。
ここでは、Androidの標準のレイアウトである android.R.layout.simple_list_item_1 を指定しています。
なお、独自に定義したレイアウトXMLを指定することもできます。
※独自のレイアウトを指定した場合、 ListAdapter も独自で実装する必要があります。
■ XML + ソースコードで定義 -----------------------------------
XML
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ListView android:id="@+id/listView1"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
ソースコード
package jp.inujirushi.sample.activity;
import jp.inujirushi.sample.R;
import android.app.Activity;
import android.os.Bundle;
import android.widget.ArrayAdapter;
import android.widget.ListView;
public class ListViewActivity extends Activity {
/** アクティビティを生成した時に呼ばれます。 */
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// XMLレイアウトを画面に設定する
setContentView(R.layout.sample_listview);
// XMLレイアウトからリストビューを取得する
ListView listView = (ListView) findViewById(R.id.listView1);
// リストビューに表示する項目を設定する
String[] items = { "項目1", "項目2", "項目3" };
ArrayAdapter<String> adapter = new ArrayAdapter<String>(
this, android.R.layout.simple_list_item_1, items);
// リストビューにアダプターを設定する
listView.setAdapter(adapter);
}
}
■ ソースコードで定義 -----------------------------------------
package jp.inujirushi.sample.activity;
import android.app.Activity;
import android.os.Bundle;
import android.widget.ArrayAdapter;
import android.widget.LinearLayout;
import android.widget.ListView;
public class ListViewActivity extends Activity {
/** アクティビティを生成した時に呼ばれます。 */
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// リストビューを生成する
ListView listView = new ListView(this);
// レイアウトを生成する
LinearLayout layout = new LinearLayout(this);
// レイアウトにリストビューを追加する
layout.addView(listView);
// レイアウトを画面に設定します
setContentView(layout);
// リストビューに表示する項目を設定する
String[] items = { "項目1", "項目2", "項目3" };
ArrayAdapter<String> adapter = new ArrayAdapter<String>(
this, android.R.layout.simple_list_item_1, items);
// リストビューにアダプターを設定する
listView.setAdapter(adapter);
}
}