Androidの設定画面で使われるプリファレンスを作りました。
今回のモノは、先日の投稿の「Androidで範囲を選択する為のSeekBar的なカスタムビュー「RangeSelectBar」をつくってみた。」を使って作成しました。
ポイント
・表示する値に書式を指定できる。
・カスタムダイアログに表示するレイアウトをxmlで作成した。
・プリファレンスで保存される値が「<value>,<value>」なのでそれぞれの値を取得する為のstaticメソッドを作成した。
スクリーンショット
実際に使ってみた感じです。
時間の範囲を選択できるようにしたかったので値を「%d:00」という書式指定を使って表現しています。
というわけで、今回は前回の投稿のクラスが必要ですのでご注意ください。
ブログに貼ってあるコードよりGoogleCodeの方が新しくなっています。
このクラスは「GoogleCode relog」にも保存されてますのでよろしければどうぞ。
今回のモノは、先日の投稿の「Androidで範囲を選択する為のSeekBar的なカスタムビュー「RangeSelectBar」をつくってみた。」を使って作成しました。
ポイント
・表示する値に書式を指定できる。
・カスタムダイアログに表示するレイアウトをxmlで作成した。
・プリファレンスで保存される値が「<value>,<value>」なのでそれぞれの値を取得する為のstaticメソッドを作成した。
スクリーンショット
実際に使ってみた感じです。
時間の範囲を選択できるようにしたかったので値を「%d:00」という書式指定を使って表現しています。
というわけで、今回は前回の投稿のクラスが必要ですのでご注意ください。
ブログに貼ってあるコードよりGoogleCodeの方が新しくなっています。
このクラスは「GoogleCode relog」にも保存されてますのでよろしければどうぞ。
プリファレンスの組み込み方
クラス
レイアウトxml
ファイル名は「range_select_preference_dialog.xml」にしています。
基底クラス
<Category : Java(Android)>
<jp.xii.relog.customlibrary.preference.RangeSelectPreference android:key="@string/m8102_mute_time" android:title="@string/m1102_mute_time" max="24" min="0" step="1" default_first="22" default_last="8" unit="24hour" value_format="%d:00" >
クラス
package jp.xii.relog.customlibrary.preference;
import jp.xii.relog.customlibrary.widget.RangeSelectBar;
import jp.xii.relog.customlibrary.widget.RangeSelectBar.onRangeSelectBarChangeListener;
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.LayoutInflater;
import android.view.View;
import android.widget.TextView;
public class RangeSelectPreference extends OriginalDialogPreference {
public final static String STR_ATTR_UNIT = "unit"; //単位
public final static String STR_ATTR_VALUE_FORMAT = "value_format"; //値のフォーマット書式
private int _max = 100; //最大値
private int _min = 0; //最小値
private int _step = 10; //可変値
private int _first = 40; //最初の値
private int _last = 80; //最後の値
private boolean _isLoop = true; //左右がループするか
private String _unitString = ""; //単位の文字列(サマリの表示用)
private String _valueFormatString = ""; //値のフォーマット書式指定
/**
* 最大値
* @param _max the _max to set
*/
public void setMax(int _max) {
if(_max <= getMin()){
_max = getMin() + 1;
}
this._max = _max;
}
/**
* 最大値
* @return the _max
*/
public int getMax() {
return _max;
}
/**
* 最小値
* @param _min the _min to set
*/
public void setMin(int _min) {
if(_min >= getMax()){
_min = getMax() - 1;
}if(_min < 0){
_min = 0;
}
this._min = _min;
}
/**
* 最小値
* @return the _min
*/
public int getMin() {
return _min;
}
/**
* 可変値
* @param _step the _step to set
*/
public void setStep(int _step) {
this._step = _step;
}
/**
* 可変値
* @return the _step
*/
public int getStep() {
return _step;
}
/**
* 最初の値
* @param _first the _first to set
*/
public void setFirst(int _first) {
this._first = _first;
}
/**
* 最初の値
* @return the _first
*/
public int getFirst() {
return _first;
}
/**
* 最後の値
* @param _last the _last to set
*/
public void setLast(int _last) {
this._last = _last;
}
/**
* 最後の値
* @return the _last
*/
public int getLast() {
return _last;
}
/**
* 左右がループするか
* @param _isLoop the _isLoop to set
*/
public void setIsLoop(boolean _isLoop) {
this._isLoop = _isLoop;
}
/**
* 左右がループするか
* @return the _isLoop
*/
public boolean isLoop() {
return _isLoop;
}
/**
* 単位の文字列(サマリの表示用)
* @param _unitString the _unitString to set
*/
public void setUnitString(String _unitString) {
this._unitString = _unitString;
}
/**
* 単位の文字列(サマリの表示用)
* @return the _unitString
*/
public String getUnitString() {
return _unitString;
}
/**
* 値のフォーマット書式指定
* @param _valueFormatString the _valueFormatString to set
*/
public void setValueFormatString(String _valueFormatString) {
this._valueFormatString = _valueFormatString;
}
/**
* 値のフォーマット書式指定
* @return the _valueFormatString
*/
public String getValueFormatString() {
return _valueFormatString;
}
/**
* コンストラクタ
* @param context
* @param attrs
*/
public RangeSelectPreference(Context context, AttributeSet attrs) {
super(context, attrs);
String temp = null;
//最大値
temp = attrs.getAttributeValue(null, RangeSelectBar.STR_ATTR_MAX);
if(temp != null){
setMax(Integer.parseInt(temp));
}
//最小値
temp = attrs.getAttributeValue(null, RangeSelectBar.STR_ATTR_MIN);
if(temp != null){
setMin(Integer.parseInt(temp));
}
//可変値
temp = attrs.getAttributeValue(null, RangeSelectBar.STR_ATTR_STEP);
if(temp != null){
setStep(Integer.parseInt(temp));
}
//最初の値の初期値
temp = attrs.getAttributeValue(null, RangeSelectBar.STR_ATTR_DEFAULT_FIRST);
if(temp != null){
setFirst(Integer.parseInt(temp));
}
//最後の値の初期値
temp = attrs.getAttributeValue(null, RangeSelectBar.STR_ATTR_DEFAULT_LAST);
if(temp != null){
setLast(Integer.parseInt(temp));
}
//単位
temp = attrs.getAttributeValue(null, STR_ATTR_UNIT);
if(temp != null){
setUnitString(temp);
}
//書式指定文字列
temp = attrs.getAttributeValue(null, STR_ATTR_VALUE_FORMAT);
if(temp != null){
setValueFormatString(temp);
}
//不正な値を治す
if(getFirst() < getMin()){
setFirst(getMin());
}
if(getLast() > getMax()){
setLast(getMax());
}
}
/**
* 表示したときに呼ばれる
*/
@Override
protected void onBindView(View view) {
//設定読込
SharedPreferences pref = getSharedPreferences();
if(pref == null){
}else{
String temp = "";
String[] values = null;
temp = pref.getString(getKey(), temp);
values = temp.split(",");
if(values == null){
}else if(values.length < 2){
}else{
setFirst(Integer.valueOf(values[0]));
setLast(Integer.valueOf(values[1]));
}
}
//サマリに表示する
if(getUnitString().length() == 0){
setSummary("Range : " + getFirst() + " - " + getLast());
}else{
setSummary("Range(" + getUnitString() + ") : " + getFirst() + " - " + getLast());
}
super.onBindView(view);
}
/**
* クリックイベント
*/
@Override
protected void onClick() {
//inflaterを使ってxmlのレイアウトをViewに反映する
LayoutInflater inflater = (LayoutInflater)getContext()
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View v = inflater.inflate(jp.xii.relog.customlibrary.R.layout.range_select_preference_dialog, null);
final RangeSelectBar bar = (RangeSelectBar)v.findViewById(jp.xii.relog.customlibrary.R.id.RangeSelect_RangeSelectBar);
final TextView text_first = (TextView)v.findViewById(jp.xii.relog.customlibrary.R.id.LavelFirst_TextView);
final TextView text_last = (TextView)v.findViewById(jp.xii.relog.customlibrary.R.id.LavelLast_TextView);
TextView text_min = (TextView)v.findViewById(jp.xii.relog.customlibrary.R.id.LavelMin_TextView);
TextView text_max = (TextView)v.findViewById(jp.xii.relog.customlibrary.R.id.LavelMax_TextView);
TextView text_center = (TextView)v.findViewById(jp.xii.relog.customlibrary.R.id.LavelCenter_TextView);
bar.setMax(getMax());
bar.setMin(getMin());
bar.setFirst(getFirst());
bar.setLast(getLast());
bar.setStep(getStep());
setFormatText(text_first, getFirst());
setFormatText(text_last, getLast());
setFormatText(text_max, getMax());
setFormatText(text_min, getMin());
setFormatText(text_center, (getMax() + getMin()) / 2);
//値変更時のイベント
bar.setOnRangeSelectBarChangeListener(new onRangeSelectBarChangeListener() {
@Override
public void onProgressChanged(RangeSelectBar rangeSelectBar, int first,
int last) {
//ダイアログの現在の値を設定する
setFormatText(text_first, first);
setFormatText(text_last, last);
}
});
//ダイアログ表示
showCustumDialog(getContext()
, (String)getDialogTitle(), (String)getDialogMessage()
, v, new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
//ダイアログのビューから結果を取得
if(bar != null){
setFirst(bar.getFirst());
setLast(bar.getLast());
}
// 設定保存
SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(getContext());
SharedPreferences.Editor editor = pref.edit();
editor.putString(getKey(), getFirst() + "," + getLast());
editor.commit();
//表示を更新
notifyChanged();
}
});
}
/**
* 書式指定の文字列をテキストビューに指定する
* @param v
* @param value
*/
private void setFormatText(TextView v, int value){
if(v == null){
}else{
try{
v.setText(String.format(getValueFormatString(), value));
}catch(Exception e){
v.setText(String.valueOf(value));
}
}
}
/**
* プリファレンスに保存された文字列から前の値を取得する
* @param value
* @return
*/
static public int getPref2First(String value){
int ret = 0;
String[] values = null;
values = value.split(",");
if(values == null){
}else if(values.length < 2){
}else{
ret = Integer.valueOf(values[0]);
}
return ret;
}
/**
* プリファレンスに保存された文字列から後の値を取得する
* @param value
* @return
*/
static public int getPref2Last(String value){
int ret = 0;
String[] values = null;
values = value.split(",");
if(values == null){
}else if(values.length < 2){
}else{
ret = Integer.valueOf(values[1]);
}
return ret;
}
}
レイアウトxml
ファイル名は「range_select_preference_dialog.xml」にしています。
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" android:paddingLeft="10dip" android:paddingRight="10dip" android:paddingBottom="10dip" > <LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" > <TextView android:id="@+id/LavelFirst_TextView" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_weight="1" android:paddingRight="10dip" android:gravity="right" android:text="0" android:textSize="24dip" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text=" - " android:textSize="24dip" /> <TextView android:id="@+id/LavelLast_TextView" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_weight="1" android:paddingLeft="10dip" android:gravity="left" android:text="0" android:textSize="24dip" /> </LinearLayout> <LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" > <TextView android:id="@+id/LavelMin_TextView" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="0" android:gravity="left" android:layout_weight="1" /> <TextView android:id="@+id/LavelCenter_TextView" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="50" android:gravity="center" android:layout_weight="1" /> <TextView android:id="@+id/LavelMax_TextView" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="100" android:gravity="right" android:layout_weight="1" /> </LinearLayout> <jp.xii.relog.customlibrary.widget.RangeSelectBar android:id="@+id/RangeSelect_RangeSelectBar" android:layout_width="fill_parent" android:layout_height="wrap_content" max="100" min="0" step="10" default_first="25" default_last="75" /> </LinearLayout>
基底クラス
package jp.xii.relog.customlibrary.preference;
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;
}
}

