値を入力するダイアログで、コミットするボタン(positiveボタン)を制御したいと思った時、
AlertDialog で何とかしようなんて思わないことである。
Wheel と連動する EditText の入力ダイアログで、EditText の誤入力で
positiveボタンに抑制をかける。
ということがしたい。Toast エラーメッセージなどは表示しない仕様
カスタマイズの Dialog を作ったが、残念なことに完全な汎用性はない。
画面は、以下のとおり。
入力MAX を超えると、、、
Wheelは、http://code.google.com/p/android-wheel/ を使用する。
<?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:gravity="center_horizontal"
android:orientation="vertical"
android:background="@drawable/picker_background">
<LinearLayout
android:id="@+id/linearLayout1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:layout_marginBottom="25dp"
android:layout_marginLeft="12dp"
android:layout_marginRight="12dp"
android:gravity="center_horizontal|center_vertical" >
<kankan.wheel.widget.WheelView android:id="@+id/wheelValue"
android:layout_height="120dp"
android:layout_width="80dp" />
<EditText
android:id="@+id/editText1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:ems="4"
android:inputType="number"
android:maxEms="6"
android:text="1" >
</EditText>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<Button
android:id="@+id/positiveButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_weight="1"
android:text="OK" />
<Button
android:id="@+id/negativeButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_weight="1"
android:text="cancel" />
</LinearLayout>
</LinearLayout>
drawable/picker_background.xml の内容
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" >
<gradient android:angle="90" android:startColor="#ff000000" android:endColor="#ff606060"/>
</shape>
BACKキーでキャンセルさせない、ダイアログ外側をタップしてキャンセルさせないように以下のとおりとする。Al
import kankan.wheel.widget.OnWheelChangedListener;
import kankan.wheel.widget.WheelView;
import kankan.wheel.widget.adapters.NumericWheelAdapter;
import android.app.Dialog;
import android.content.Context;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
/**
* DecimalPicker.
*/
public class DecimalPicker extends Dialog{
/**
* Positiveボタン実行時の処理を約束。これをコンストラクタに渡す。
* min <= 入力値 <= max が約束されて呼ばれる
*/
public interface PositiveListner{
public void doPositive(int result);
};
private LayoutInflater layoutInflater;
int min;
int max;
private int defaultValue;
PositiveListner positiveListner;
/**
* Constructort
* @param context Context
* @param min 最小値
* @param max 最大値
* @param defaultValue 初期値
* @param positiveListner Positiveボタン実行時の処理
*/
public DecimalPicker(Context context,int min,int max,int defaultValue,PositiveListner positiveListner){
super(context);
layoutInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
this.min = min;
this.max = max;
this.defaultValue = defaultValue;
this.positiveListner = positiveListner;
}
@Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(layoutInflater.inflate(R.layout.decimal_picker,null));
final int diff = min - 0;
super.setCancelable(false);
final EditText editText = (EditText)findViewById(R.id.editText1);
editText.setText(Integer.toString(defaultValue));
final WheelView pageWheel = (WheelView)findViewById(R.id.wheelValue);
pageWheel.setViewAdapter(new NumericWheelAdapter(getContext(),min,max));
pageWheel.setCurrentItem(defaultValue - diff);
pageWheel.addChangingListener(new OnWheelChangedListener(){
@Override
public void onChanged(WheelView wheel,int oldValue,int newValue){
editText.setText(Integer.toString(newValue+diff));
}
});
final Button positiveButton = (Button)findViewById(R.id.positiveButton);
editText.addTextChangedListener(new TextWatcher(){
@Override
public void onTextChanged(CharSequence s,int start,int before,int count){
}
@Override
public void beforeTextChanged(CharSequence s,int start,int count,int after){
}
@Override
public void afterTextChanged(Editable s){
String str = s.toString();
if (str.length() > 0){
try{
int i = Integer.parseInt(str);
if (min <= i && i <= max){
positiveButton.setEnabled(true);
pageWheel.setCurrentItem(i - diff);
}else{
positiveButton.setEnabled(false);
}
}catch(Exception e){
positiveButton.setEnabled(false);
}
}else{
positiveButton.setEnabled(false);
}
}
});
positiveButton.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v){
positiveListner.doPositive(pageWheel.getCurrentItem()+diff);
dismiss();
}
});
*1.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v){
dismiss();
}
});
}
@Override
public void setCancelable(boolean flag){
super.setCancelable(false);
}
}
呼び出しの例、、、
Button button = (Button)findViewById(R.id.button1);
button.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v){
Dialog dialog = new DecimalPicker(DecimalPickActivity.this, 1, 100, 21
,new DecimalPicker.PositiveListner(){
@Override
public void doPositive(int result){
// 入力値 result に従った処理を行う。
}
});
dialog.setTitle("テスト");
dialog.show();
}
});
*1:Button)findViewById(R.id.negativeButton