[Android Tips] Spinnerの選択肢をAlertDialogで表示する

2011.10.31

こんにちは。今日はハロウィンですね!

さて、AndroidのSpinnerコンポーネントはご存知でしょうか? Spinnerは以前のブログでも少しだけご紹介しましたが、 ユーザに選択を促す便利なコンポーネントです。

このSpinnerですが、 Android 2.x 系のテーマと、Android 3.x 系以降のテーマ (Holo) では少し挙動が違います。 それぞれ見てみましょう。

Android 2.x 系

Android 3.x 系以降(Holo) ※画面サイズが大きいので一部切り取っています spinner02

2.x 系はスマホ向けなので、画面いっぱいに選択肢が出てきます。 それに対して3.x系以降は(Holo)は解像度が高い端末が多くなったので、画面いっぱいではなく Spinnerボタンの下に小さく出てきます。

しかし、3.x系以降(Holo)でも選択肢を画面いっぱいに出したい!ということがあります。 今回はその方法についてご紹介したいと思います。

ボタン部分はButtonで、選択肢部分はAlertDialogで作る

Spinnerコンポーネントは、選択肢を表示するときのボタン部と、実際の選択肢を表示する部分で構成されています。 今回はSpinnerの標準の動作をカスタマイズする形になるので、実際にはSpinnerは使いません。 Button部分をButtonで、選択肢部分をAlertDialogというコンポーネントでSpinner風に見せていきます。

Buttonをカスタマイズする

前回のブログでご紹介した方法を使うことで、ButtonをSpinnerのスキンを当てることができます。 "@android:style/Widget.Holo.Spinner"のスキンを使うと見た目はSpinnerそのものになります。

AlertDialogで選択用ダイアログを作る

実際の選択肢はAlertDialogクラス使って実現します。 AlertDialogは、OK/キャンセルなどの簡単なアラートを作るときによく使われますが、 選択肢ダイアログを作るときにも適した機能を持っています。 AlertDialogを作るには、AlertDialog.Builderクラスを使ってインスタンスを生成します。 Builderクラスは、どのようなAlertDialogを作るかプロパティを設定することで、 好きなAlertDialogを作ることができます。 setSingleChoiceItems()メソッドを使うと、選択肢のAlertDialogを作ることができます。 以下の引数をセットします。

  • 第一引数 : Adapter
  • 第二引数 : 表示時に選択されているindex
  • 第三引数 : 選択肢が選ばれたときのリスナ

XMLソース

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity" >
    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"
        style="@android:style/Widget.Holo.Light.Spinner"
         />
</RelativeLayout>

Javaソース

package com.example.sampleproject;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ArrayAdapter;
import android.widget.Button;

public class MainActivity extends Activity {

    protected Button spinnerButton;
    protected AlertDialog alertDialog;
    protected ArrayAdapter<String> adapter;
    protected int selectedIndex = 0;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        adapter = new ArrayAdapter<String>(this,
                android.R.layout.simple_list_item_single_choice);
        adapter.add("ねずみ");
        adapter.add("うし");
        adapter.add("とら");
        adapter.add("うさぎ");
        adapter.add("りゅう");

        // Spinner風のボタン
        spinnerButton = (Button) findViewById(R.id.button);
        spinnerButton.setText("選択してください");
        spinnerButton.setOnClickListener(onClickListener);
    }
    private OnClickListener onClickListener = new OnClickListener() {
        @Override
        public void onClick(View v) {
            // AlertDialogで選択肢を表示
            AlertDialog.Builder builder = new AlertDialog.Builder(
                    MainActivity.this);
            builder.setTitle("選択してください");
            builder.setSingleChoiceItems(adapter, selectedIndex,
                    onDialogClickListener);
            alertDialog = builder.create();
            alertDialog.show();
        }
    };
    private DialogInterface.OnClickListener onDialogClickListener = new DialogInterface.OnClickListener() {
        @Override
        public void onClick(DialogInterface dialog, int which) {
            // AlertDialogで選択された内容を保持
            selectedIndex = which;
            spinnerButton.setText(adapter.getItem(which));
            alertDialog.dismiss();
        }
    };
}

実行結果 spinner03

spinner04

まとめ

今回はAlertDialogをSpinnerの選択肢風に見せるように使いましたが、 AlertDialogは好きなViewを配置できたりするので、何かと融通が利くコンポーネントです。 アイデア次第ではいろいろと広がっていくと思うので、ぜひお試しください!