AndroidでTimePickerプリファレンスを使う

Androidの設定画面はPreferencesという機能を作ると非常に簡単に作れて便利なのですが、種類が少ないのがたまに傷ってやつです。
なので、今度はタイムピッカー用のPreferenceを作ってみました。

どんな感じかってのは以下のSSの通りです。



最終的にサマリーに設定した時間が反映されてSharedPreferenceに保存されます。
12/24時間表示も切り替えれます。


イケテないところがあったの修正しました。
今後、共通で使う基底というか中間クラス作りました。



ソースは「GoogleCode relog」にも保存していますのでよろしければどうぞ。

使い方は、xmlに以下の感じで追加します。
パッケージ名は各自調節してください。

<jp.xii.relog.setting.TimePickerPreference
		android:key="TimePicker"
		android:title="時間設定(12H)"
		android:summary="現在の設定 : "
		android:dialogTitle="- 時間設定 -"
		android:dialogMessage="何時にしますか?"
		defaultHour="1"
		defaultMinute="2"
		is24Hour="false"
		>
</jp.xii.relog.setting.TimePickerPreference>


具体的なクラスは、「DialogPreference」クラスを継承しています。これはプリファレンスの一覧画面の項目の右はじに▽マークを出すためにあえてやってます。
実際は「Preference」クラスを継承すれば実装可能です。ただ、その場合は▽マークを自力で実装しないといけないので(よーするに別でxml用意しないといけない)今回は見送りました。
同じ理由でDialogPreferenceを継承しているならAlartDialogを使用してダイアログを表示する必要はないのですが見送りました。

package jp.xii.relog.setting;

import android.content.Context;
import android.content.DialogInterface;
import android.content.SharedPreferences;
import android.content.DialogInterface.OnClickListener;
import android.preference.PreferenceManager;
import android.util.AttributeSet;
import android.view.View;
import android.widget.TimePicker;

/**
 * @author Iori
 *
 */
public class TimePickerPreference extends OriginalDialogPreference {

	//追加属性の名称
	private final static String STR_ATTR_DEFAULT_HOUR = "defaultHour";
	private final static String STR_ATTR_DEFAULT_MINUTE = "defaultMinute";
	private final static String STR_ATTR_IS_24HOUR = "is24Hour";
	
	//プリファレンス保存時のキー名の追加文字列
	private final static String STR_KEY_HOUR = "_Hour";		
	private final static String STR_KEY_MINUTE = "_Minute";
	
	private int _defaultHour = 0;			//設定値(時)
	private int _defaultMinute = 0;			//設定値(分)
	private boolean _is24HourView = false;	//設定値(24時間表示)
	
	

	/**
	 * 24時間表示か
	 * @param _is24HourView the _is24HourView to set
	 */
	public void setIs24HourView(boolean _is24HourView) {
		this._is24HourView = _is24HourView;
	}

	/**
	 * 24時間表示か
	 * @return the _is24HourView
	 */
	public boolean is24HourView() {
		return _is24HourView;
	}

	
	/**
	 * コンストラクタ
	 * @param context
	 * @param attrs
	 */
	public TimePickerPreference(Context context, AttributeSet attrs) {
		super(context, attrs);

		String temp;
		
		//時間を取得
		temp = attrs.getAttributeValue(null, STR_ATTR_DEFAULT_HOUR);
		if(temp != null){
			_defaultHour = Integer.valueOf(temp);
		}
		//分を取得
		temp = attrs.getAttributeValue(null, STR_ATTR_DEFAULT_MINUTE);
		if(temp != null){
			_defaultMinute = Integer.valueOf(temp);
		}
		//24時間表示を取得
		temp = attrs.getAttributeValue(null, STR_ATTR_IS_24HOUR);
		if(temp == null){
		}else if(temp.toLowerCase().compareTo("true") != 0){
		}else{
			_is24HourView = true;			
		}
		
	}

	/**
	 * 表示したときに呼ばれる
	 */
	@Override
	protected void onBindView(View view) {
		//設定を読み込み
		SharedPreferences pref = getSharedPreferences();
		if(pref == null){
		}else{
			_defaultHour = pref.getInt(getKey() + STR_KEY_HOUR, _defaultHour);
			_defaultMinute = pref.getInt(getKey() + STR_KEY_MINUTE, _defaultMinute);
		}

		//サマリーに現在値を設定
		String summary = "";
		if(_is24HourView){
			summary = String.format("%s%02d:%02d", getDefaultSummary(), _defaultHour, _defaultMinute);
		}else{
			if(_defaultHour > 12){
				summary = String.format("%s%02d:%02d PM", getDefaultSummary(), _defaultHour - 12, _defaultMinute);
			}else{
				summary = String.format("%s%02d:%02d AM", getDefaultSummary(), _defaultHour, _defaultMinute);
			}
		}
		setSummary((CharSequence) (summary));

		//これはなぜか最後じゃないとイケないらしい
		super.onBindView(view);
	}

	/**
	 * プリファレンスのクリックイベント
	 */
	@Override
	protected void onClick(){

		//ダイアログ表示
		final TimePicker picker = new TimePicker(getContext());
		picker.setIs24HourView(_is24HourView);
		picker.setCurrentHour(_defaultHour);
		picker.setCurrentMinute(_defaultMinute);
		showCustumDialog(getContext(), (String)getDialogTitle(), (String)getDialogMessage()
							, picker, new OnClickListener() {
			@Override
			public void onClick(DialogInterface dialog, int which) {
				// 設定保存
				SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(getContext());
				SharedPreferences.Editor editor = pref.edit();
				editor.putInt(getKey() + STR_KEY_HOUR, picker.getCurrentHour());
				editor.putInt(getKey() + STR_KEY_MINUTE, picker.getCurrentMinute());
				editor.commit();
				
				//表示を更新
				notifyChanged();
			}
		});

	}
	
}


オリジナルの基底クラス(随時拡張されます)
package jp.xii.relog.setting;

import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface.OnClickListener;
import android.preference.DialogPreference;
import android.util.AttributeSet;
import android.view.View;

public class OriginalDialogPreference extends DialogPreference {


	private String _summary = "";			//サマリーの文字列

	/**
	 * サマリの初期状態
	 * @param _summary the _summary to set
	 */
	public void setDefaultSummary(String _summary) {
		this._summary = _summary;
	}

	/**
	 * サマリの初期状態
	 * @return the _summary
	 */
	public String getDefaultSummary() {
		return _summary;
	}

	/**
	 * コンストラクタ
	 * @param context
	 * @param attrs
	 */
	public OriginalDialogPreference(Context context, AttributeSet attrs) {
		super(context, attrs);

		String temp;
		
		//サマリーの初期状態を保存しておく
		temp = (String) getSummary();
		if(temp != null){
			setDefaultSummary(temp);
		}

	}
	
	/**
	 * ダイアログの表示
	 * @param context 親のコンテキスト
	 * @param title ダイアログのタイトル
	 * @param text ダイアログの本文
	 */
	protected void showCustumDialog(Context context, String title, String text ,View custumItem, OnClickListener listener){
		AlertDialog.Builder ad = new AlertDialog.Builder(context);
		ad.setTitle(title);
		if(text != null){
			ad.setMessage(text);
		}
		ad.setView(custumItem);
		ad.setPositiveButton("OK", listener);
		ad.setNegativeButton("Cancel", null);
		ad.create();
		ad.show();
	}
	
	/**
	 * 数値に変換する
	 * @param number
	 * @return
	 */
	protected int toInt(String number){
		int num = 0;
		
		try{
			num = Integer.parseInt(number);
		}catch(Exception e){
			num = 0;
		}
		
		return num;
	}

	/**
	 * 数値か確かめる
	 * @param number
	 * @return
	 */
	protected boolean isInt(String number){
		boolean ret = false;
		
		try{
			Integer.parseInt(number);
			ret = true;
		}catch(Exception e){
			ret = false;
		}
		
		return ret;
	}

}

みなさんの参考になればと思います。