這次主要打算實作一個 Custom Preference View(相當於 iOS stepper 的感覺)。
免不了要實作 java 以及 它的 layout。
最終我們可以用下面的使用方式。
preference.xml 1 2 3 4 5 6 7 <package.name.YumePreference android:title ="有多少行" android:summary ="10" android:defaultValue ="5" android:key ="YumeTest" android:widgetLayout ="@layout/yume_stepper_preference" />
Prefernce Preference 會以以下順序依序呼叫以及比較關鍵的幾個方法 :
onGetDefaultValue
onSetInitialValue
onCreateView
onBindView
onGetDefaultValue 務必 override 這個方法
不然在 onSetInitialValue(boolean restorePersistedValue, Object defaultValue)
的 defaultValue
會為 null
1 2 3 4 @Override protected Object onGetDefaultValue(TypedArray a, int index) { return a.getInteger(index,8); }
onSetInitialValue 這邊取決於是要用預設值
或是儲存值
。
1 2 3 4 5 6 7 8 9 10 11 @Override protected void onSetInitialValue(boolean restorePersistedValue, Object defaultValue) { if (restorePersistedValue) { // Restore existing state value = this.getPersistedInt(value); } else { // Set default state from the XML attribute value = (Integer) defaultValue; persistInt(value); } }
onCreateView 重點只在於要 inflate 哪個 layout
1 2 3 4 5 6 @Override protected View onCreateView( ViewGroup parent ) { View v = super.onCreateView(parent); LayoutInflater li = (LayoutInflater)getContext().getSystemService( Context.LAYOUT_INFLATER_SERVICE ); return li.inflate( R.layout.yume_stepper_preference, parent, false); }
onBindView 這邊比較有趣的地方是 super.onBindView(view)
要在最後呼叫
不然 setSummary(String.valueOf(value))
會沒有作用
1 2 3 4 5 6 7 8 9 10 11 @Override protected void onBindView(View view) { minus = (Button) view.findViewById(R.id.minus); plus = (Button) view.findViewById(R.id.plus); setSummary(String.valueOf(value)); // ... super.onBindView(view); }
Layout 部分 這邊比較值得注意的是可以用 android:id="@android:id/title"
以及 android:id="@android:id/summary"
分別來讀取 android:title="有多少行"
跟 android:summary="10"
1 2 3 4 5 6 7 8 9 <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@android:id/title" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@android:id/summary" />
Source Code YumePreference.java 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 import android.content.Context;import android.content.res.TypedArray;import android.preference.Preference;import android.util.AttributeSet;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.Button;public class YumePreference extends Preference { private Button minus; private Button plus; private int value = 0 ; public YumePreference (Context context) { super (context); } public YumePreference (Context context, AttributeSet attrs) { super (context, attrs); } public YumePreference (Context context, AttributeSet attrs, int defStyle) { super (context, attrs, defStyle); } @Override protected Object onGetDefaultValue (TypedArray a, int index) { return a.getInteger(index,8 ); } @Override protected View onCreateView ( ViewGroup parent ) { View v = super .onCreateView(parent); LayoutInflater li = (LayoutInflater)getContext().getSystemService( Context.LAYOUT_INFLATER_SERVICE ); return li.inflate( R.layout.yume_stepper_preference, parent, false ); } @Override protected void onBindView (View view) { minus = (Button) view.findViewById(R.id.minus); plus = (Button) view.findViewById(R.id.plus); setSummary(String.valueOf(value)); minus.setOnClickListener(new View.OnClickListener() { @Override public void onClick (View view) { value = --value >= 0 ? value : 0 ; persistInt(value); setSummary(String.valueOf(value)); } }); plus.setOnClickListener(new View.OnClickListener() { @Override public void onClick (View view) { value = ++value <= 100 ? value : 100 ; persistInt(value); setSummary(String.valueOf(value)); } }); super .onBindView(view); } @Override protected void onSetInitialValue (boolean restorePersistedValue, Object defaultValue) { if (restorePersistedValue) { value = this .getPersistedInt(value); } else { value = (Integer) defaultValue; persistInt(value); } } }
yume_stepper_preference.xml 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android ="http://schemas.android.com/apk/res/android" android:layout_width ="match_parent" android:layout_height ="match_parent" > <TextView android:layout_width ="wrap_content" android:layout_height ="wrap_content" android:id ="@android:id/title" style ="@android:style/TextAppearance.DeviceDefault.SearchResult.Title" android:textColor ="#FFF" android:text ="預設 Title" android:layout_centerVertical ="true" android:layout_alignParentLeft ="true" android:layout_marginLeft ="8dp" android:layout_alignParentRight ="true" android:layout_marginRight ="160dp" /> <TextView android:layout_width ="wrap_content" android:layout_height ="wrap_content" android:id ="@android:id/summary" style ="@android:style/TextAppearance.DeviceDefault.SearchResult.Subtitle" android:textColor ="#FFF" android:text ="0" android:layout_centerVertical ="true" android:layout_alignRight ="@+id/minus" android:layout_marginRight ="76dp" /> <Button android:layout_height ="44dp" android:layout_width ="60dp" android:id ="@+id/minus" android:text ="-" android:textColor ="#FFF" android:layout_centerVertical ="true" android:layout_alignRight ="@+id/plus" android:layout_marginRight ="60dp" /> <Button android:layout_height ="44dp" android:layout_width ="60dp" android:id ="@+id/plus" android:text ="+" android:textColor ="#FFF" android:layout_centerVertical ="true" android:layout_alignParentRight ="true" /> </RelativeLayout >
Reference Android: Creating custom preference 設定 A custom preference type. The preference counts the number of clicks it has received and stores/retrieves it from the storage. : Preference « Core Class « Android