09 April 2014

(Android) AlertDialogで各種Widgetの利用法

テキスト入力やリスト選択のAlertDialogを表示する方法

ソースコード

MainActivity.java と activity_main.xml をまとめてダウンロードする場合

20140409-alertdlg-src.zipをダウンロードする

下準備(Fragment無効化とボタン押下イベントハンドラの記述法)

(Android) フラグメント fragment_main を使う場合・使わない場合』で書いたように、Fragmentを使わないようにADTが自動生成したソースコードを修正する。

その上で、XMLで画面インターフェースを設計する。緑の部分はAlertDialogから読み書きするところ。赤の部分はXMLでイベントハンドラの関数を定義しているところ。(XMLでイベントハンドラを定義しない場合、onCreate関数内で定義してやれば良い)

※ なお、GoogleのADTサンプルでは、onCreate内でイベントハンドラを定義している

activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >
 
    <EditText
        android:id="@+id/editText1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:singleLine="true"
        android:inputType="text"
        android:width="@dimen/dialog_fixed_width_major" >
        <requestFocus />
    </EditText>
 
    <CheckBox
        android:id="@+id/checkBox1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/editText1"
        android:text="CheckBox" />
 
    <ToggleButton
        android:id="@+id/toggleButton1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/checkBox1"
        android:text="ToggleButton" />
 
    <Button
        android:id="@+id/button_ok_dlg"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/toggleButton1"
        android:onClick="onClickButton_OkDlg"
        android:text="OK AlertDialog"
        android:width="@dimen/dialog_fixed_width_major" />
 
    <Button
        android:id="@+id/button_yn_dlg"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:onClick="onClickButton_YnDlg"
        android:layout_below="@+id/button_ok_dlg"
        android:text="Y/N AlertDialog"
        android:width="@dimen/dialog_fixed_width_major" />
 
    <Button
        android:id="@+id/button_input_dlg"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:onClick="onClickButton_InputDlg"
        android:layout_below="@+id/button_yn_dlg"
        android:text="TextInput AlertDialog"
        android:width="@dimen/dialog_fixed_width_major" />
 
    <Button
        android:id="@+id/button_list_dlg"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/button_input_dlg"
        android:text="List AlertDialog"
        android:width="@dimen/dialog_fixed_width_major" />
 
    <Button
        android:id="@+id/button_list_dlg2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/button_list_dlg"
        android:text="SingleSelect AlertDialog"
        android:width="@dimen/dialog_fixed_width_major" />
 
    <Button
        android:id="@+id/button_check_dlg"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/button_list_dlg2"
        android:text="CheckBox AlertDialog"
        android:width="@dimen/dialog_fixed_width_major" />
 
    <Button
        android:id="@+id/button_quit"
        android:drawableLeft="@android:drawable/ic_delete"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/button_check_dlg"
        android:onClick="onClickButton_Quit"
        android:text="Quit"
        android:width="@dimen/dialog_fixed_width_major" />
</RelativeLayout>

画面は次のような感じになる。

20140409-dlginit.jpg

MainActivity.javaの共通部分は次のような感じになる。赤の部分は、XMLではなくonCreate内でボタン押下のイベントハンドラ関数を定義している部分。緑の部分は「Quit」ボタンを押した時のイベントハンドラ関数。

MainActivity.java
package com.example.android_actiondlg_test_1;
 
import android.support.v7.app.ActionBarActivity;
import android.support.v7.app.ActionBar;
import android.support.v4.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.os.Build;
 
import android.widget.Button;
import android.view.View.OnClickListener;
 
import android.app.AlertDialog;
import android.widget.EditText;
import android.text.InputType;
import android.widget.CheckBox;
import android.widget.ToggleButton;
import android.content.DialogInterface;
import android.widget.Toast;
 
public class MainActivity extends ActionBarActivity {
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
 
        // ボタン押下イベントリスナーの登録
        Button button = (Button)findViewById(R.id.button_list_dlg);
        button.setOnClickListener(mButtonListDlgListener);
 
        button = (Button)findViewById(R.id.button_list_dlg2);
        button.setOnClickListener(mButtonListDlg2Listener);
 
        button = (Button)findViewById(R.id.button_check_dlg);
        button.setOnClickListener(mButtonCheckboxDlgListener);
 
        button = (Button)findViewById(R.id.button_quit);
        button.setOnClickListener(mButtonQuitListener);
 
    }
 
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }
 
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();
        if (id == R.id.action_settings) {
            return true;
        }
        return super.onOptionsItemSelected(item);
    }
 
 〜 ここに、ボタン押下時のイベントハンドラ関数を書く 〜
 
    // 終了ボタン
    private OnClickListener mButtonQuitListener = new OnClickListener() {
        public void onClick(View v) {
            finish();
        }
    };
 
}

OKボタンのみのダイアログ

20140409-dlg-ok.jpg

MainActivity.java
    // OKボタンのみのAlertDialogを表示する
    public void onClickButton_OkDlg(View view) {
        // AlertDialogを構築する
        AlertDialog.Builder dlg = new AlertDialog.Builder(this);
        dlg.setIcon(android.R.drawable.ic_dialog_info);
        dlg.setTitle("OKボタンのみのAlertDialog");
        dlg.setMessage("ダイアログに表示する文字列");
        dlg.setPositiveButton("OK", null);
        // AlertDialogを表示する
        dlg.show();
    }

Yes/Noボタンのダイアログ

20140409-dlg-yn.jpg

MainActivity.java
    // Y/NボタンのAlertDialogを表示し、Yesが選択された場合はEditTextに文字列を設定する
    public void onClickButton_YnDlg(View view) {
        // AlertDialogを構築する
        AlertDialog.Builder dlg = new AlertDialog.Builder(this);
        dlg.setTitle("Y/NボタンのAlertDialog");
        dlg.setMessage("ダイアログに表示する文字列");
        dlg.setPositiveButton("Yes", new DialogInterface.OnClickListener(){
            public void onClick(DialogInterface dialog, int which) {
                //Yesボタンが押された時の処理
                Toast.makeText(MainActivity.this, "Yesが押されました", Toast.LENGTH_LONG).show();
                EditText text1 = (EditText) MainActivity.this.findViewById(R.id.editText1);
                text1.setText("Yesが押されました");
            }});
        dlg.setNegativeButton("No", new DialogInterface.OnClickListener(){
            public void onClick(DialogInterface dialog, int which) {
                //Noボタンが押された時の処理
                Toast.makeText(MainActivity.this, "Noが押されました", Toast.LENGTH_LONG).show();
            }});
        // AlertDialogを表示する
        dlg.show();
    }

テキスト入力のダイアログ

20140409-dlg-input.jpg

MainActivity.java
    // テキスト入力のAlertDialogを表示し、入力された値をEditTextに設定する
    public void onClickButton_InputDlg(View view) {
        final EditText editView = new EditText(MainActivity.this);
        editView.setLines(1);   // 1行
        editView.setInputType(InputType.TYPE_CLASS_TEXT);   // 改行を許可しない
        // AlertDialogを構築する
        AlertDialog.Builder dlg = new AlertDialog.Builder(this);
        dlg.setTitle("テキスト入力のAlertDialog");
        dlg.setMessage("ダイアログに表示する文字列");
        // テキストボックスに初期値を入力する
        dlg.setView(editView);
        EditText text1 = (EditText) MainActivity.this.findViewById(R.id.editText1);
        editView.setText(text1.getText().toString());
        dlg.setPositiveButton("Yes", new DialogInterface.OnClickListener(){
            public void onClick(DialogInterface dialog, int which) {
                //Yesボタンが押された時の処理
                Toast.makeText(MainActivity.this, "Yesが押されました", Toast.LENGTH_LONG).show();
                // 入力値をメインダイアログに書き戻す
                EditText text1 = (EditText) MainActivity.this.findViewById(R.id.editText1);
                text1.setText(editView.getText().toString());
            }});
        dlg.setNegativeButton("No", new DialogInterface.OnClickListener(){
            public void onClick(DialogInterface dialog, int which) {
                //Noボタンが押された時の処理
                Toast.makeText(MainActivity.this, "Noが押されました", Toast.LENGTH_LONG).show();
            }});
        // AlertDialogを表示する
        dlg.show();
    }

テキスト入力2個のダイアログ

20140409-dlg-input2.jpg

LinearLayoutによるコンテナを作成し、その中に必要なヴィジェットを全て詰め込む。その後、コンテナをAlertDialogにsetViewで紐付ける。

MainActivity.java
    // AlertDialog上に作成するレイアウトコンテナ
    final LinearLayout layout = new LinearLayout(MainActivity.this);
    layout.setOrientation(LinearLayout.VERTICAL);
     
    TextView text1 = new TextView(this);
    text1.setText("日付の入力");
    text1.setTextColor(Color.LTGRAY);
    layout.addView(text1);
     
    // 年月日入力のテキストボックス
    final EditText editViewDate = new EditText(MainActivity.this);
    editViewDate.setLines(1);   // 1行
    editViewDate.setInputType(InputType.TYPE_CLASS_DATETIME | InputType.TYPE_DATETIME_VARIATION_DATE);
    SimpleDateFormat dateFmt = new SimpleDateFormat("yyyy/MM/dd");
    Date dateNow = new Date();
    editViewDate.setText(dateFmt.format(dateNow));
    layout.addView(editViewDate);
     
    TextView text2 = new TextView(this);
    text2.setText("時間の入力");
    text2.setTextColor(Color.LTGRAY);
    layout.addView(text2);
     
    // 時分入力のテキストボックス
    final EditText editViewTime = new EditText(MainActivity.this);
    editViewTime.setLines(1);   // 1行
    editViewTime.setInputType(InputType.TYPE_CLASS_DATETIME | InputType.TYPE_DATETIME_VARIATION_TIME);
    dateFmt.applyPattern("HH:mm");
    editViewTime.setText(dateFmt.format(dateNow));
    layout.addView(editViewTime);
     
    // AlertDialogを構築する
    AlertDialog.Builder dlg = new AlertDialog.Builder(this);
    dlg.setTitle("テキスト入力2個のAlertDialog");
    dlg.setMessage("日時を入力します");
    dlg.setView(layout);
     
    dlg.setPositiveButton("決定", new DialogInterface.OnClickListener(){
        public void onClick(DialogInterface dialog, int which) {
            //Yesボタンが押された時の処理(ここではログに出力している)
            Log.d("EditViewDate", editViewDate.getText().toString());
            Log.d("EditViewTime", editViewTime.getText().toString());
        }});
    dlg.setNegativeButton("キャンセル", new DialogInterface.OnClickListener(){
        public void onClick(DialogInterface dialog, int which) {
            //Noボタンが押された時の処理
        }});
    // AlertDialogを表示する
    dlg.show();

リスト選択のダイアログ

20140409-dlg-list.jpg

MainActivity.java
    // リスト選択のAlertDialogを表示し、選択値をEditTextに設定する
    private OnClickListener mButtonListDlgListener = new OnClickListener() {
        public void onClick(View v) {
            // 選択肢リストを作成する
            final String[] items = new String[10];
            for(int i=0; i<10; i++) {
                items[i] = String.format("選択肢 %d", i);
            }
            // AlertDialogを構築する
            AlertDialog.Builder dlg = new AlertDialog.Builder(MainActivity.this);
            dlg.setTitle("リストのAlertDialog");
            dlg.setItems(items, new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int idx) {
                    Toast.makeText(MainActivity.this, String.format("%s が選択された", items[idx]), Toast.LENGTH_LONG).show();
                    // 入力値をメインダイアログに書き戻す
                    EditText text1 = (EditText) MainActivity.this.findViewById(R.id.editText1);
                    text1.setText(items[idx]);
                }
            });
            dlg.setNegativeButton("キャンセル", null);
            // AlertDialogを表示する
            dlg.show();
        }
    };

リスト選択のダイアログ

20140409-dlg-list-radio.jpg

MainActivity.java
    // リスト選択のAlertDialogを表示し、選択値をEditTextに設定する
    private OnClickListener mButtonListDlg2Listener = new OnClickListener() {
        private int selectedItem = 1;       // リストの選択値(onClickに対してグローバルで宣言する)
        public void onClick(View v) {
            // 選択肢リストを作成する
            final String[] items = new String[10];
            for(int i=0; i<10; i++) {
                items[i] = String.format("選択肢 %d", i);
            }
            // AlertDialogを構築する
            AlertDialog.Builder dlg = new AlertDialog.Builder(MainActivity.this);
            dlg.setTitle("リストのAlertDialog");
            dlg.setSingleChoiceItems(items, selectedItem, new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int idx) {
                    selectedItem = idx;
                }
            });
            dlg.setPositiveButton("OK", new DialogInterface.OnClickListener(){
                public void onClick(DialogInterface dialog, int idx) {
                    //Yesボタンが押された時の処理
                    Toast.makeText(MainActivity.this, String.format("%s が選択された", items[selectedItem]), Toast.LENGTH_LONG).show();
                    // 入力値をメインダイアログに書き戻す
                    EditText text1 = (EditText) MainActivity.this.findViewById(R.id.editText1);
                    text1.setText(items[selectedItem]);
                }});
            dlg.setNegativeButton("キャンセル", null);
            // AlertDialogを表示する
            dlg.show();
        }
    };

リスト選択のダイアログ

20140409-dlg-checkbox.jpg

MainActivity.java
    // チェックボックスのリストを表示し、選択値を画面上のチェックボックスとプッシュボタンに反映する
    private OnClickListener mButtonCheckboxDlgListener = new OnClickListener() {
        private boolean[] checkedItems = {false, false};        // リストの選択値(onClickに対してグローバルで宣言する)
        public void onClick(View v) {
            final String[] items = {"チェックボックス", "トグルボタン"};
            // 現在のチェック状態を読み出す
            CheckBox checkBox = (CheckBox) MainActivity.this.findViewById(R.id.checkBox1);
            if(checkBox.isChecked()){ checkedItems[0] = true; }
            ToggleButton toggleButton = (ToggleButton) MainActivity.this.findViewById(R.id.toggleButton1);
            if(toggleButton.isChecked()){ checkedItems[1] = true; }
            // AlertDialogを構築する
            AlertDialog.Builder dlg = new AlertDialog.Builder(MainActivity.this);
            dlg.setTitle("チェックボックスのAlertDialog");
            dlg.setMultiChoiceItems(items, checkedItems, new DialogInterface.OnMultiChoiceClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int idx, boolean isChecked) {
                    checkedItems[idx] = isChecked;
                    Toast.makeText(MainActivity.this, String.format("idx=%d, sel=%b", idx, isChecked), Toast.LENGTH_LONG).show();
                }
            });
            dlg.setPositiveButton("OK", new DialogInterface.OnClickListener(){
                public void onClick(DialogInterface dialog, int idx) {
                    //Yesボタンが押された時の処理
                    // 入力値をメインダイアログに書き戻す
                    CheckBox checkBox = (CheckBox) MainActivity.this.findViewById(R.id.checkBox1);
                    checkBox.setChecked(checkedItems[0]);
                    ToggleButton toggleButton = (ToggleButton) MainActivity.this.findViewById(R.id.toggleButton1);
                    toggleButton.setChecked(checkedItems[1]);
                }});
            dlg.setNegativeButton("キャンセル", null);
            // AlertDialogを表示する
            dlg.show();
        }
    };

XMLを用いずに、onCreat内で全てのwidgetを定義する方法

ソースコードの先頭付近の部分の抜粋。レイアウトを配置し、そこに各widgetを配置していく。

MainActivity.java
〜 プログラム先頭のimport列挙部分は省略 〜
 
import android.view.ViewGroup.LayoutParams;
 
public class MainActivity extends ActionBarActivity {
 
    // イベントリスナ関数内で参照する必要のあるwidget
    private EditText text1;
    private CheckBox checkBox;
    private ToggleButton toggleButton;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
 
        LinearLayout layout = new LinearLayout(this);
        layout.setOrientation(LinearLayout.VERTICAL);
        setContentView(layout);
 
        text1 = new EditText(this);
        text1.setText("文字列の初期値");
        layout.addView(text1);
        
        checkBox = new CheckBox(this);
        checkBox.setText("CheckBox");
        layout.addView(checkBox);
        
        toggleButton = new ToggleButton(this);
        // 幅を最大化せずに追加する
        layout.addView(toggleButton, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
        
        Button buttonOkDlg = new Button(this);
        buttonOkDlg.setText("OK AlertDialog");
        layout.addView(buttonOkDlg);
        buttonOkDlg.setOnClickListener(mButtonOkDlgListener);
 
    }
 
〜 この後は省略 〜