参考网上代码自己做了一个客户定制 Preference,没有使用 preference的 android:layout 属性,因为总觉得在不同版本系统上难以和其他preference的控件对齐,所以采用仅设置 android:widget_layout 的方式。
先创建自己要定制的 widget_layout 文件“preference_widget_seekbar.xml”:
建立 com.sample.preference.SeekBarPreference 类,用来初始化界面,同步音量滑块表示的preference数据
package com.sample.preference;import com.sample.R;
import android.content.Context;import android.content.res.TypedArray;import android.preference.Preference;import android.util.AttributeSet;import android.util.Log;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.view.ViewParent;import android.widget.RelativeLayout;import android.widget.SeekBar;import android.widget.SeekBar.OnSeekBarChangeListener;import android.widget.TextView;public class SeekBarPreference extends Preference implements OnSeekBarChangeListener{ private final String TAG = "SeekBarPreference"; //private static final String ANDROIDNS="http://schemas.android.com/apk/res/android"; private static final String SEEKBAR_PREFS="SeekBarPreference"; private static final int DEFAULT_VALUE = 50; Context mContext; private int mMaxValue = 100; private int mMinValue = 0; private int mInterval = 1; private int mCurrentValue = 50; private String mUnitsLeft = ""; private String mUnitsRight = ""; private SeekBar mSeekBar; private TextView mCurrentValueText; public SeekBarPreference(Context context, AttributeSet attrs) { super(context, attrs); initPreference(context, attrs); } public SeekBarPreference(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); initPreference(context, attrs); } private void initPreference(Context context, AttributeSet attrs) { Log.v(TAG,"initPreference"); mContext = context; updateValuesFromXml(attrs); this.setWidgetLayoutResource(R.layout.preference_widget_seekbar); } private void updateValuesFromXml(AttributeSet attrs) { mMaxValue = attrs.getAttributeIntValue(SEEKBAR_PREFS, "max", 100); mMinValue = attrs.getAttributeIntValue(SEEKBAR_PREFS, "min", 0); mUnitsLeft = getAttributeStringValue(attrs, SEEKBAR_PREFS, "unitsLeft", ""); String value = getAttributeStringValue(attrs, SEEKBAR_PREFS, "value", ""); mUnitsRight = getAttributeStringValue(attrs, SEEKBAR_PREFS, "unitsRight", ""); try { mInterval = attrs.getAttributeIntValue(SEEKBAR_PREFS, "interval", 1); if( mInterval <= 0 ) { mInterval = 1; } } catch(Exception e) { Log.e(TAG, "Invalid interval value", e); } } private String getAttributeStringValue(AttributeSet attrs, String namespace, String name, String defaultValue) { String value = attrs.getAttributeValue(namespace, name); if(value == null) value = defaultValue; return value; } @Override protected View onCreateView(ViewGroup parent){ Log.v(TAG, "onCreateView()"); return super.onCreateView(parent); } @Override public void onBindView(View view) { super.onBindView(view); View layout = view; Log.v(TAG, "onBindView()"); mSeekBar = (SeekBar)view.findViewById(R.id.seekBar1); mCurrentValueText = (TextView)view.findViewById(R.id.seekBarPrefValue); if( null != mCurrentValueText ){ mCurrentValueText.setText(String.valueOf(mCurrentValue)); mCurrentValueText.setMinimumWidth(30); } if( null != mSeekBar ) { mSeekBar.setMax(mMaxValue - mMinValue); mSeekBar.setProgress(mCurrentValue - mMinValue); mSeekBar.setOnSeekBarChangeListener(this); } TextView unitsRight = (TextView)view.findViewById(R.id.seekBarPrefUnitsRight); if( null != unitsRight ){ unitsRight.setText(mUnitsRight); } TextView unitsLeft = (TextView)view.findViewById(R.id.seekBarPrefUnitsLeft); if( null != unitsLeft ){ unitsLeft.setText(mUnitsLeft); } } @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { int newValue = progress + mMinValue; if(newValue > mMaxValue) newValue = mMaxValue; else if(newValue < mMinValue) newValue = mMinValue; else if(mInterval != 1 && newValue % mInterval != 0) newValue = Math.round(((float)newValue)/mInterval)*mInterval; // change rejected, revert to the previous value if(!callChangeListener(newValue)){ seekBar.setProgress(mCurrentValue - mMinValue); return; } // change accepted, store it mCurrentValue = newValue; if( null != mCurrentValueText ){ mCurrentValueText.setText(String.valueOf(newValue)); } persistInt(newValue); } @Override public void onStartTrackingTouch(SeekBar seekBar) {} @Override public void onStopTrackingTouch(SeekBar seekBar) { notifyChanged(); } @Override protected Object onGetDefaultValue(TypedArray ta, int index){ int defaultValue = ta.getInt(index, DEFAULT_VALUE); return defaultValue; } @Override protected void onSetInitialValue(boolean restoreValue, Object defaultValue) { if(restoreValue) { mCurrentValue = getPersistedInt(mCurrentValue); } else { int temp = 0; try { temp = (Integer)defaultValue; } catch(Exception ex) { Log.e(TAG, "Invalid default value: " + defaultValue.toString()); } persistInt(temp); mCurrentValue = temp; } } }
最后,在preference xml中加入对应项