Android SeekBarPreference
в настоящее время я пытаюсь реализовать класс SeekBarPreference, используя http://android-journey.blogspot.com/2010/01/for-almost-any-application-we-need-to.html учебник с RelativeLayout. Первая проблема-TextView preferenceText не отображается вообще. Вторая проблема заключается в том, что панель не может скользить, как в обычных настройках (например, панель громкости мультимедиа)?
public class SeekBarPreference extends Preference implements
OnSeekBarChangeListener {
public static int maximum = 100;
public static int interval = 5;
private float oldValue = 25;
private TextView Indicator;
public SeekBarPreference(Context context) {
super(context);
}
public SeekBarPreference(Context context, AttributeSet attrs) {
super(context, attrs);
}
public SeekBarPreference(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
protected View onCreateView(ViewGroup parent) {
float scale = getContext().getResources().getDisplayMetrics().density;
RelativeLayout layout = new RelativeLayout(getContext());
RelativeLayout.LayoutParams textParams = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT);
RelativeLayout.LayoutParams sbarParams = new RelativeLayout.LayoutParams(
Math.round(scale * 160),
RelativeLayout.LayoutParams.WRAP_CONTENT);
RelativeLayout.LayoutParams indParams = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT);
TextView preferenceText = new TextView(getContext());
preferenceText.setId(0);
preferenceText.setText(getTitle());
preferenceText.setTextSize(18);
preferenceText.setTypeface(Typeface.SANS_SERIF, Typeface.BOLD);
SeekBar sbar = new SeekBar(getContext());
sbar.setId(1);
sbar.setMax(maximum);
sbar.setProgress((int)this.oldValue);
sbar.setOnSeekBarChangeListener(this);
this.Indicator = new TextView(getContext());
this.Indicator.setTextSize(12);
this.Indicator.setTypeface(Typeface.MONOSPACE, Typeface.ITALIC);
this.Indicator.setText("" + sbar.getProgress());
textParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
sbarParams.addRule(RelativeLayout.RIGHT_OF, preferenceText.getId());
indParams.setMargins(Math.round(20*scale), 0, 0, 0);
indParams.addRule(RelativeLayout.RIGHT_OF, sbar.getId());
preferenceText.setLayoutParams(textParams);
sbar.setLayoutParams(sbarParams);
this.Indicator.setLayoutParams(indParams);
layout.addView(preferenceText);
layout.addView(this.Indicator);
layout.addView(sbar);
layout.setId(android.R.id.widget_frame);
return layout;
}
@Override
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
progress = Math.round(((float) progress)/interval) * interval;
if(!callChangeListener(progress)) {
seekBar.setProgress((int) this.oldValue);
return;
}
seekBar.setProgress(progress);
this.oldValue = progress;
this.Indicator.setText("" + progress);
updatePreference(progress);
notifyChanged();
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
@Override
protected Object onGetDefaultValue(TypedArray ta, int index) {
int dValue = ta.getInt(index, 25);
return validateValue(dValue);
}
@Override
protected void onSetInitialValue(boolean restoreValue,
Object defaultValue) {
int temp = restoreValue ? getPersistedInt(25) : (Integer)defaultValue;
if(!restoreValue)
persistInt(temp);
this.oldValue = temp;
}
private int validateValue(int value) {
if(value > maximum)
value = maximum;
else if (value < 0)
value = 0;
else if (value % interval != 0)
value = Math.round(((float) value)/interval) * interval;
return value;
}
private void updatePreference(int newValue) {
SharedPreferences.Editor editor = getEditor();
editor.putInt(getKey(), newValue);
editor.commit();
}
}
3 ответов
проблема со скольжением здесь связана с notifyChange()
звонок. Это как-то мешает скольжению. Я также работаю над подобным виджетом, потому что мне не нравится диалоговый подход.
как и было обещано, вот решение, которое я добавил в свой проект с открытым исходным кодом:
Я написал класс SeekBarPreference, который встроен в виджет внутри действия preferences вместо всплывающего диалога. Вы можете скачать файл jar от:
документация и использование класса здесь: http://aniqroid.sileria.com/doc/api/com/sileria/android/view/SeekBarPreference.html
также не забудьте проверить удобный класс companion для автоматического отображения сводки при изменении панели поиска: http://aniqroid.sileria.com/doc/api/com/sileria/android/event/PrefsSeekBarListener.html
слайдер работает в учебнике, изменив onProgressChanged на
public void onProgressChanged( SeekBar seekBar, int progress, boolean fromUser )
{
progress = Math.round( ( (float) progress ) / interval ) * interval;
persistInt(progress);
callChangeListener( progress );
seekBar.setProgress( progress );
this.monitorBox.setText( progress + "" );
updatePreference( progress );
}
Что касается невозможности перемещения ползунка, это связано с тем, что его ширина установлена на 80 (см. params2), которая слишком узка, чтобы позволить скользить. После установки разумной ширины для него, например, 400, и связанного текстового представления и нескольких модов, чтобы заставить его скомпилироваться с моей версией SDK, он работал для меня. Одним из преимуществ этой версии перед многими другими является то, что макет выполняется в коде вместо XML, что позволяет приложению легко создавать несколько слайдеров.