AlertDialogをボタンタップ等で閉じない



よく書かれていることだと思いますが、メモしておきます。

Androidの[AlertDialog](http://developer.android.com/reference/android/app/AlertDialog.html)は[Builder](http://developer.android.com/reference/android/app/AlertDialog.Builder.html)で作ったりした時に、[Builder.setPositiveButton](http://developer.android.com/reference/android/app/AlertDialog.Builder.html#setPositiveButton(int,%20android.content.DialogInterface.OnClickListener))などで追加したボタンは、タップされると強制的にダイアログが閉じてしまいます。

あまり美しくないですが、AlertDialogを生成後ならButtonなどを取得できるので閉じずに処理やUI変更をすることができます。

DialogFragmentでもカスタムでないAlertDialogを使う場合には使用できると思います。
今時、ほとんどのケースでダイアログはカスタマイズするかと思いますが。。

# Builder.setPositiveButton()等の場合

AlertDialogを[Builder.create](http://developer.android.com/reference/android/app/AlertDialog.Builder.html#create())や[Builder.show](http://developer.android.com/reference/android/app/AlertDialog.Builder.html#show())などで生成してから[getButton](http://developer.android.com/reference/android/app/AlertDialog.html#getButton(int))で取得します

```java
	AlertDialog.Builder b = new AlertDialog.Builder(activity);
	b.setTitle("タイトル");
	b.setPositiveButton(android.R.string.ok, null);
	
	// ここでリスナーを実装しても渡されないので実装しなくても構いません。
	b.setNegativeButton(android.R.string.cancel, null);
            
	// AlertDialogを生成する前にgetButton等してもnullが返されます。
	final AlertDialog dialog = b.show();
            
	// 種類に応じてButtonを取得します
	Button button = dialog.getButton(DialogInterface.BUTTON_NEGATIVE);
	// dialog.getButton(DialogInterface.BUTTON_POSITIVE);
	// dialog.getButton(DialogInterface.BUTTON_NEUTRAL);
            
	// 通常のViewのように実装します。
	button.setOnClickListener(new View.OnClickListener() {
		@Override
		public void onClick(View v) {
				...
				// 場合によっては自分で明示的に閉じる必要がある
				dialog.dismiss();
		}
	});
```

注意点として、自動で閉じられないので[setCancelable](http://developer.android.com/reference/android/app/AlertDialog.Builder.html#setCancelable(boolean))をfalseなどにして、アクションを起こすまでDialogを閉じれなくしている場合にはユーザが明示的にダイアログを閉じれなくなるのでどこかでdismissなどを呼ぶ必要があります。
その場合は、DialogInterfaceが渡されないので、生成したAlertDialogの[dismiss](http://developer.android.com/reference/android/app/Dialog.html#dismiss())を呼ぶ必要があります。


* 参考：[AlertDialogのボタンを押したときに、閉じる、閉じないをコントロールするには](http://www.hiramine.com/programming/android/alertdialogclosecontrol.html)

など

# Builder.setItems()等の場合

調べてもあまり書かれていなかったのですが、[setItems](http://developer.android.com/reference/android/app/AlertDialog.Builder.html#setItems(java.lang.CharSequence%5B%5D,%20android.content.DialogInterface.OnClickListener))等でリストを追加する場合も[AlertDialog.getListView](http://developer.android.com/reference/android/app/AlertDialog.html#getListView())によってListViewを取得し、同様のことができました。

```java
	AlertDialog.Builder b = new AlertDialog.Builder(activity);
	b.setTitle("タイトル");
	
	// ここでリスナーを実装しても渡されないので実装しなくても構いません。
	b.setItems(new String[]{"1","2"}, null);            
            
	// AlertDialogを生成する前にgetListView等してもnullが返されます。
	AlertDialog dialog = b.show();
            
	// ListViewを取得します
	ListView list = dialog.getListView();
            
	// 通常のListViewのように実装します。
	button.setOnItemClickListener(new AdapterView.OnItemClickListener() {
		@Override
		public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
				...
		}
	});
```

ただ、[Builder.setSingleChoiceItems()](http://developer.android.com/reference/android/app/AlertDialog.Builder.html#setSingleChoiceItems(java.lang.CharSequence%5B%5D,%20int,%20android.content.DialogInterface.OnClickListener))や[Builder.setMultiChoiceItems()](http://developer.android.com/reference/android/app/AlertDialog.Builder.html#setMultiChoiceItems(java.lang.CharSequence%5B%5D,%20boolean%5B%5D,%20android.content.DialogInterface.OnMultiChoiceClickListener))ではダイアログを閉じないので、こちらはそこまで用途がないかもしれません。