设计自己的Android Preference

SeekBar Preference

SeekBar Preference

Android提供了Preference供应用可以进行功能设置以及属性配置等操作,检查android.preference可以看到Preference下有若干子类,例如常用的EditTextPreference、CheckBoxPreference、ListPreference等。但是仅仅有这些是不够的。

在我现在的工作当中,应用里有这么一个场景,用户手指在屏幕滑动,应用绘制出移动的轨迹。

熟悉Android API Demo(可以在SDK/platforms/android-1.5/samples下找到)的人一定记得在graphics目录下,有一个FingerPaint的类实现了类似上述功能。但是还远远实现不了我们的需要,–需求是要在Preference中实现挑选颜色和调整粗细。

当然,他山之石可以攻玉,FingerPaint还是提供了不错的例子,尤其是FingPaint中选择颜色所使用的另外一个类ColorPickerDialog基本上具备了我们想要的部分功能。

除了上面提到的FingerPaint之外,还可以从Android的源码中找到可以参考的代码。从framework/base/core/java中,找到android.preference包,可以看到有一个SeekBarPreference的类,–这是一个“烂尾”类,代码未完成,因此被Google打上了@hide的标签。因此需要稍加完善,才能加以使用。

@Override
protected void onBindDialogView(View view) {
    super.onBindDialogView(view);
 
    bar = (SeekBar) view.findViewById(R.id.seekbar);
    bar.setOnSeekBarChangeListener(this);
    bar.setProgress(barValue);
}
 
public void setValue(int value) {
    barValue = value;
}
 
public int getValue() {
    return barValue;
}
 
@Override
protected void onDialogClosed(boolean positiveResult) {
    if (positiveResult) {
        this.getOnPreferenceChangeListener().onPreferenceChange(this, barValue);
    }
}
Color Picker Preference

Color Picker Preference

在这个类的改造过程中,override两个父类方法是关键所在,一个是onBindDialogView,另一个是onDialogClosed。

通过第一个方法,我们可以“找到”被当做content view的SeekBar的实例,进而可以获得到其progress。

通过第二个方法,我们可以方便的通知到Listener,告诉它,SeekBar的值有变化。这里我们把SeekBar的值,即progress看做是SeekBarPreference的value。除了这两个方法之外,就是要增加setValue和getValue两个方法了。

如果不看代码的话,就会有疑问:SeekBar是如何进入Diglog的呢?它正式通过DialogPreference的属性android:dialogLayout得以注入:

<net.poemcode.android.config.SeekBarPreference
	android:key="@string/setting_handwrite_width_key"
        android:title="@string/setting_handwrite_width_title"
        android:dialogTitle="@string/setting_handwrite_width_title"
        android:dialogLayout="@layout/setting_widthseekbar"
        android:persistent="true"/>

依此原理,可以举一反三,对于如何实现选择颜色是不是有了思路?

首先实现一个视图,负责展现不同颜色和接收用户选中的颜色,其可以从SeekBarPreference中的内部类ColorPickerView加以改造完成;然后新增一个布局文件,将刚才的视图加入到布局当中;接着继承DialogPreference实现自己的Preference子类ColorPickerPreference;最后在XML文件里增加这个Preference并把刚才的布局文件通过dialogLayout属性加入进去。从而实现了整个功能。

public class SeekBarPreference extends DialogPreference implements SeekBar.OnSeekBarChangeListener {
 
    private static final String TAG = "SeekBarPreference";
 
    private SeekBar bar;
 
    private int barValue;
 
    public SeekBarPreference(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
 
    @Override
    protected void onBindDialogView(View view) {
        super.onBindDialogView(view);
 
        bar = (SeekBar) view.findViewById(R.id.seekbar);
        bar.setOnSeekBarChangeListener(this);
        bar.setProgress(barValue);
    }
 
    public void setValue(int value) {
        barValue = value;
    }
 
    public int getValue() {
        return barValue;
    }
 
    @Override
    protected void onDialogClosed(boolean positiveResult) {
        if (positiveResult) {
            this.getOnPreferenceChangeListener().onPreferenceChange(this, barValue);
        }
    }
 
    public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
        Log.d(TAG, "onProgressChanged, progress : " + progress + ", fromUser : " + fromUser);
    }
 
    public void onStartTrackingTouch(SeekBar seekBar) {
        Log.d(TAG, "onStartTrackingTouch");
    }
 
    public void onStopTrackingTouch(SeekBar seekBar) {
        barValue = seekBar.getProgress();
    }
}

4 Comments

[…] 参考:诗意代码 – PoemCode » 设计自己的Android Preference    Android(開発)/ちょっとした設定の永続化 – 俺の基地    シークバー(SeekBar)を使用するには – 逆引きAndroid入門 初めてのAndroid posted with amazlet at 10.06.22 Ed Burnette オライリージャパン 売り上げランキング: 35045 Amazon.co.jp で詳細を見る […]

liuchao15 10 月, 2010 at 10:14 上午

求源码!!!liuchao.hit@gmail.com

Xu Haojie15 10 月, 2010 at 3:25 下午

Sorry,时间久远,已无法找出来源码,并且源码版权归属公司,我也无权公布,请理解。

mlianghua26 11 月, 2010 at 3:10 下午

很简单,就是自定义控件而已。

Leave a comment

Your comment