先日リリースした「こづかい帳」ではダイアログを多用していますが、ほとんどが独自にカスタマイズしたダイアログです。
今回はその中でも特に作りこみ度が高かった数値入力のダイアログを例に、カスタマイズしたダイアログの実装方法についてまとめました。
本対応の目的
カスタマイズしたダイアログを呼び出して、ダイアログ内で入力した値を元の画面へ戻す機能を実装しています。
画面イメージは下記の通り。
ボタンを押下 |
ダイアログ上で値を入力 |
入力された値が表示 |
drawableの準備
<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_enabled="false"><shape> <solid android:color="@color/button3" /> </shape></item> <item android:state_pressed="true"><shape> <solid android:color="@color/button2" /> </shape></item> <item><shape> <solid android:color="@color/button1" /> </shape></item> </selector>
ボタンの背景色を定義しているファイルです。
layoutの準備
<?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:background="@android:color/black" android:gravity="center" android:orientation="vertical"> <TextView android:id="@+id/tv_output" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="@dimen/dp_l" android:background="@android:color/darker_gray" android:gravity="end" android:padding="@dimen/dp_l" android:textSize="@dimen/sp_m" /> <Button android:id="@+id/bt_open" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="@dimen/dp_l" android:background="@drawable/button_background" android:gravity="center" android:padding="@dimen/dp_l" android:text="@string/open_dialog" android:textColor="@android:color/white" android:textSize="@dimen/sp_m" /> </LinearLayout>
メイン画面のlayoutファイルです。ダイアログを起動するボタンとダイアログから連携された値を表示するTextViewのみを用意しています。
<?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:layout_alignParentTop="true" android:background="@color/dialog_background" android:gravity="center_horizontal" android:orientation="vertical"> <TextView android:id="@+id/tv_input" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="@dimen/dp_l" android:layout_weight="1" android:background="@android:color/darker_gray" android:gravity="end" android:padding="@dimen/dp_l" android:textSize="@dimen/sp_m" /> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginLeft="@dimen/dp_m" android:layout_marginRight="@dimen/dp_m" android:layout_marginTop="@dimen/dp_m" android:layout_weight="1" android:orientation="horizontal"> <Button android:id="@+id/bt_no7" android:layout_width="0dp" android:layout_height="match_parent" android:layout_margin="@dimen/dp_s" android:layout_weight="1" android:background="@drawable/button_background" android:padding="@dimen/dp_l" android:text="@string/no7" android:textColor="@android:color/white" android:textSize="@dimen/sp_m" /> <Button android:id="@+id/bt_no8" android:layout_width="0dp" android:layout_height="match_parent" android:layout_margin="@dimen/dp_s" android:layout_weight="1" android:background="@drawable/button_background" android:padding="@dimen/dp_l" android:text="@string/no8" android:textColor="@android:color/white" android:textSize="@dimen/sp_m" /> <Button android:id="@+id/bt_no9" android:layout_width="0dp" android:layout_height="match_parent" android:layout_margin="@dimen/dp_s" android:layout_weight="1" android:background="@drawable/button_background" android:padding="@dimen/dp_l" android:text="@string/no9" android:textColor="@android:color/white" android:textSize="@dimen/sp_m" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginLeft="@dimen/dp_m" android:layout_marginRight="@dimen/dp_m" android:layout_weight="1" android:orientation="horizontal"> <Button android:id="@+id/bt_no4" android:layout_width="0dp" android:layout_height="match_parent" android:layout_margin="@dimen/dp_s" android:layout_weight="1" android:background="@drawable/button_background" android:padding="@dimen/dp_l" android:text="@string/no4" android:textColor="@android:color/white" android:textSize="@dimen/sp_m" /> <Button android:id="@+id/bt_no5" android:layout_width="0dp" android:layout_height="match_parent" android:layout_margin="@dimen/dp_s" android:layout_weight="1" android:background="@drawable/button_background" android:padding="@dimen/dp_l" android:text="@string/no5" android:textColor="@android:color/white" android:textSize="@dimen/sp_m" /> <Button android:id="@+id/bt_no6" android:layout_width="0dp" android:layout_height="match_parent" android:layout_margin="@dimen/dp_s" android:layout_weight="1" android:background="@drawable/button_background" android:padding="@dimen/dp_l" android:text="@string/no6" android:textColor="@android:color/white" android:textSize="@dimen/sp_m" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginLeft="@dimen/dp_m" android:layout_marginRight="@dimen/dp_m" android:layout_weight="1" android:orientation="horizontal"> <Button android:id="@+id/bt_no1" android:layout_width="0dp" android:layout_height="match_parent" android:layout_margin="@dimen/dp_s" android:layout_weight="1" android:background="@drawable/button_background" android:padding="@dimen/dp_l" android:text="@string/no1" android:textColor="@android:color/white" android:textSize="@dimen/sp_m" /> <Button android:id="@+id/bt_no2" android:layout_width="0dp" android:layout_height="match_parent" android:layout_margin="@dimen/dp_s" android:layout_weight="1" android:background="@drawable/button_background" android:padding="@dimen/dp_l" android:text="@string/no2" android:textColor="@android:color/white" android:textSize="@dimen/sp_m" /> <Button android:id="@+id/bt_no3" android:layout_width="0dp" android:layout_height="match_parent" android:layout_margin="@dimen/dp_s" android:layout_weight="1" android:background="@drawable/button_background" android:padding="@dimen/dp_l" android:text="@string/no3" android:textColor="@android:color/white" android:textSize="@dimen/sp_m" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="@dimen/dp_m" android:layout_marginLeft="@dimen/dp_m" android:layout_marginRight="@dimen/dp_m" android:layout_weight="1" android:orientation="horizontal"> <Button android:id="@+id/bt_no0" android:layout_width="0dp" android:layout_height="match_parent" android:layout_margin="@dimen/dp_s" android:layout_weight="1" android:background="@drawable/button_background" android:padding="@dimen/dp_l" android:text="@string/no0" android:textColor="@android:color/white" android:textSize="@dimen/sp_m" /> <Button android:id="@+id/bt_clear" android:layout_width="0dp" android:layout_height="match_parent" android:layout_margin="@dimen/dp_s" android:layout_weight="2" android:background="@drawable/button_background" android:padding="@dimen/dp_l" android:text="@string/clear" android:textColor="@android:color/white" android:textSize="@dimen/sp_m" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <Button android:id="@+id/bt_ok" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginRight="@dimen/dp_s" android:layout_weight="1" android:background="@drawable/button_background" android:enabled="false" android:padding="@dimen/dp_l" android:text="@string/ok" android:textColor="@android:color/white" android:textSize="@dimen/sp_l" /> <Button android:id="@+id/bt_close" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_weight="1" android:background="@drawable/button_background" android:padding="@dimen/dp_l" android:text="@string/close" android:textColor="@android:color/white" android:textSize="@dimen/sp_l" /> </LinearLayout> </LinearLayout>
ダイアログ用のlayoutファイルです。
valuesの準備
<?xml version="1.0" encoding="utf-8"?> <resources> <!-- ボタン通常時 --> <color name="button1">#404040</color> <!-- ボタン押下時 --> <color name="button2">#808080</color> <!-- ボタン選択不可 --> <color name="button3">#b0b0b0</color> <!-- dialog背景色 --> <color name="dialog_background">#202020</color> </resources>
色を定義するファイルです。
<resources> <!-- 文字サイズ(小) --> <dimen name="sp_s">16sp</dimen> <!-- 文字サイズ(中) --> <dimen name="sp_m">20sp</dimen> <!-- 文字サイズ(大) --> <dimen name="sp_l">24sp</dimen> <!-- 余白などのサイズ(小) --> <dimen name="dp_s">1dp</dimen> <!-- 余白などのサイズ(中) --> <dimen name="dp_m">4dp</dimen> <!-- 余白などのサイズ(大) --> <dimen name="dp_l">8dp</dimen> </resources>
文字サイズと余白のサイズを定義するファイルです。
<resources> <string name="app_name">Sample</string> <string name="open_dialog">ダイアログを開く</string> <string name="err_msg">1,000,000,000以上は入力できません。</string> <string name="ok">○</string> <string name="close">×</string> <string name="no0">0</string> <string name="no1">1</string> <string name="no2">2</string> <string name="no3">3</string> <string name="no4">4</string> <string name="no5">5</string> <string name="no6">6</string> <string name="no7">7</string> <string name="no8">8</string> <string name="no9">9</string> <string name="clear">C</string> </resources>
文字列を定義するファイルです。
Java側の記載
package jp.co.skys.android.sample; import android.app.Activity; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.TextView; public class MainActivity extends Activity { TextView tvOutput; Button btOpen; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.layout_main); tvOutput = (TextView) findViewById(R.id.tv_output); btOpen = (Button) findViewById(R.id.bt_open); //ボタン押下時 btOpen.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { // ダイアログの表示 final CustomizedDialog dialog = CustomizedDialog.newInstance(); dialog.setOnOkButtonClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //ダイアログから値を取得して、output用のTextViewに表示 tvOutput.setText(String.format("%1$,3d", dialog.getInputValue())); //ダイアログを消す dialog.dismiss(); } }); dialog.show(getFragmentManager(), "dialog_fragment"); dialog.setCancelable(false); } }); } }
メイン画面用のJavaファイルです。
package jp.co.skys.android.sample; import android.app.AlertDialog; import android.app.Dialog; import android.app.DialogFragment; import android.graphics.Color; import android.graphics.drawable.ColorDrawable; import android.os.Bundle; import android.util.DisplayMetrics; import android.view.LayoutInflater; import android.view.View; import android.view.Window; import android.view.WindowManager; import android.widget.Button; import android.widget.TextView; public class CustomizedDialog extends DialogFragment { private View.OnClickListener okButtonClickListener = null; Dialog dialog; Long mInput = 0L; TextView tvInput; Button[] btNo = new Button[10]; //0~9までのボタン Button btClear; Button btOk; Button btClose; public static CustomizedDialog newInstance() { CustomizedDialog fragment = new CustomizedDialog(); return fragment; } @Override public Dialog onCreateDialog(Bundle savedInstanceState) { //XMLとの紐付け LayoutInflater inflater = getActivity().getLayoutInflater(); View view = inflater.inflate(R.layout.layout_dialog, null, false); tvInput = (TextView) view.findViewById(R.id.tv_input); btNo[0] = (Button) view.findViewById(R.id.bt_no0); btNo[1] = (Button) view.findViewById(R.id.bt_no1); btNo[2] = (Button) view.findViewById(R.id.bt_no2); btNo[3] = (Button) view.findViewById(R.id.bt_no3); btNo[4] = (Button) view.findViewById(R.id.bt_no4); btNo[5] = (Button) view.findViewById(R.id.bt_no5); btNo[6] = (Button) view.findViewById(R.id.bt_no6); btNo[7] = (Button) view.findViewById(R.id.bt_no7); btNo[8] = (Button) view.findViewById(R.id.bt_no8); btNo[9] = (Button) view.findViewById(R.id.bt_no9); btClear = (Button) view.findViewById(R.id.bt_clear); btOk = (Button) view.findViewById(R.id.bt_ok); btClose = (Button) view.findViewById(R.id.bt_close); //ダイアログの作成 dialog = new Dialog(getActivity()); dialog.getWindow().requestFeature(Window.FEATURE_NO_TITLE); dialog.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN); dialog.setContentView(view); dialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); //数字ボタン押下時の処理 for (int i = 0; i < 10; i++) { btNo[i].setOnClickListener(new View.OnClickListener() { public void onClick(View v) { //入力された数値を元に一時的な値を取得 Long tmp = Long.parseLong(String.valueOf(mInput) + ((Button) v).getText().toString()); //一時的な値が1,000,000,000以上の場合はアラートを表示 if (tmp >= 1000000000) { new AlertDialog.Builder(getActivity()) .setMessage(getText(R.string.err_msg)) .setPositiveButton(getText(R.string.ok), null) .show(); } else { mInput = tmp; tvInput.setText(String.format("%1$,3d", mInput)); } //OKボタンの活性化(mValueが0以外の場合のみ活性) if (mInput == 0) { btOk.setEnabled(false); } else { btOk.setEnabled(true); } } }); } //クリアボタン押下時の処理 btClear.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { mInput = 0L; tvInput.setText(""); btOk.setEnabled(false); } }); //クローズボタン押下時はダイアログを消す btClose.setOnClickListener(new View.OnClickListener() { public void onClick(View v) { dialog.dismiss(); } }); //OKボタンのリスナー btOk.setOnClickListener(okButtonClickListener); return dialog; } // ダイアログの横幅、高さ、表示位置を設定 @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); WindowManager.LayoutParams lp = dialog.getWindow().getAttributes(); DisplayMetrics metrics = getResources().getDisplayMetrics(); lp.width = (int) (metrics.widthPixels * 0.8);//横幅を80% //lp.height = (int) (metrics.heightPixels * 0.8);//高さを80% //lp.x = 100; //表示位置を指定した分、右へ移動 //lp.y = 200; //表示位置を指定した分、下へ移動 dialog.getWindow().setAttributes(lp); } public void setOnOkButtonClickListener(View.OnClickListener listener) { this.okButtonClickListener = listener; } //ダイアログ内の値を返すメソッド public Long getInputValue() { return mInput; } }
今回の肝となるダイアログ用のJavaファイルです。
詳細はいつものようにソース内のコメントを参照ください。
最後に
上記一式含まれるファイルを下記よりダウンロードできます。
今回の例ではダイアログを呼び出す際に引数を渡していませんが、引数を使うことで更に複雑な連携も可能となります。良かったらお試しください。