Custom preference jumping all over screen
I have written a custom preference class which contains a simple progress bar in it to allow setting things like volume. The preference worked great until I tried putting two of these preference in my preference screen.
When I did that the preference screen started to act wierdly » the two custom preferences switch locations constantly as i drag the seek bar.
Any one have any idea why this is happening? Thanks
EDIT: here is the code of the custom preference
import android.content.Context; import
android.content.SharedPreferences; import android.content.res.TypedArray; import android.graphics.Typeface; import android.preference.Preference; import android.util.AttributeSet; import android.view.Gravity; import android.view.View; import android.view.ViewGroup; import android.widget.LinearLayout; import android.widget.SeekBar; import android.widget.SeekBar.OnSeekBarChangeListener; import android.widget.TextView;
public class SeekBarPreference extends Preference implements OnSeekBarChangeListener {
private int mMaximum = 60; private int mInterval = 1; private int mMinimum = 1;
private int mDefault = 50; private TextView monitorBox;
public SeekBarPreference(Context context) { super(context); }
public SeekBarPreference(Context context, AttributeSet attrs) { super(context, attrs); initValues(context, attrs); }
public SeekBarPreference(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); initValues(contex开发者_高级运维t, attrs); }
private void initValues(Context context, AttributeSet attrs) { TypedArray styledAttributes = context.obtainStyledAttributes(attrs,
R.styleable.SeekBarPreference); mMinimum = styledAttributes.getInt(
R.styleable.SeekBarPreference_barMinValue, 1); mMaximum = styledAttributes.getInt(
R.styleable.SeekBarPreference_barMaxValue, 1); mInterval = styledAttributes.getInt(
R.styleable.SeekBarPreference_barInterval, 1); mDefault = styledAttributes.getInt(
R.styleable.SeekBarPreference_defaultValue, mMaximum); }
@Override protected View onCreateView(ViewGroup parent) {
LinearLayout horizontalLayout = new LinearLayout(getContext()); horizontalLayout.setPadding(15, 5, 10, 5); horizontalLayout.setOrientation(LinearLayout.HORIZONTAL);
LinearLayout verticalLayout = new LinearLayout(getContext()); verticalLayout.setOrientation(LinearLayout.VERTICAL);
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT); layoutParams.gravity = Gravity.LEFT; layoutParams.weight = 0.5f;
LinearLayout.LayoutParams settingTitleLayoutParams = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT); settingTitleLayoutParams.gravity = Gravity.LEFT; settingTitleLayoutParams.weight =
1.0f;
LinearLayout.LayoutParams seekbarLayoutParams = new LinearLayout.LayoutParams(
80, LinearLayout.LayoutParams.WRAP_CONTENT); seekbarLayoutParams.gravity = Gravity.RIGHT | Gravity.CENTER_VERTICAL;
LinearLayout.LayoutParams selectedAmountLayoutParams = new LinearLayout.LayoutParams(
30, LinearLayout.LayoutParams.WRAP_CONTENT); selectedAmountLayoutParams.gravity = Gravity.CENTER;
TextView titleTextView = new TextView(getContext()); titleTextView.setText(getTitle()); titleTextView.setTextSize(18); titleTextView.setTypeface(Typeface.SANS_SERIF, Typeface.BOLD); titleTextView.setGravity(Gravity.LEFT); titleTextView.setLayoutParams(settingTitleLayoutParams);
TextView summeryTextView = new TextView(getContext()); summeryTextView.setText(getSummary()); summeryTextView.setTextSize(14); summeryTextView.setTypeface(Typeface.SANS_SERIF); summeryTextView.setGravity(Gravity.LEFT); summeryTextView.setLayoutParams(settingTitleLayoutParams);
SeekBar bar = new SeekBar(getContext()); bar.setMax(mMaximum); bar.setProgress(mDefault); bar.setPadding(10, 0, 10, 0); bar.setLayoutParams(seekbarLayoutParams); bar.setOnSeekBarChangeListener(this);
this.monitorBox = new TextView(getContext()); this.monitorBox.setTextSize(12); this.monitorBox.setTypeface(Typeface.MONOSPACE, Typeface.ITALIC); this.monitorBox.setLayoutParams(selectedAmountLayoutParams); this.monitorBox.setPadding(2, 5, 0, 0); this.monitorBox.setText(bar.getProgress()
+ "");
verticalLayout.addView(titleTextView); verticalLayout.addView(summeryTextView); horizontalLayout.addView(verticalLayout, layoutParams); horizontalLayout.addView(bar); horizontalLayout.addView(this.monitorBox); horizontalLayout.setId(android.R.id.widget_frame);
return horizontalLayout; }
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
progress = Math.round(((float) progress) / mInterval) * mInterval; if (progress < mMinimum) { progress = mMinimum; }
if (!callChangeListener(progress)) { seekBar.setProgress((int) this.mDefault); return; }
seekBar.setProgress(progress); this.mDefault = progress; this.monitorBox.setText(progress + ""); updatePreference(progress);
notifyChanged(); }
public void onStartTrackingTouch(SeekBar seekBar) { }
public void onStopTrackingTouch(SeekBar seekBar) { }
@Override protected Object onGetDefaultValue(TypedArray ta, int index) {
int dValue = (int) ta.getInt(index, 5);
return validateValue(dValue); }
@Override protected void onSetInitialValue(boolean restoreValue, Object defaultValue) { int temp = restoreValue ? getPersistedInt(5) : (Integer) defaultValue;
if (!restoreValue) persistInt(temp);
this.mDefault = temp; }
private int validateValue(int value) {
if (value > mMaximum) value = mMaximum; else if (value < 0) value = 0; else if (value % mInterval != 0) value = Math.round(((float) value) / mInterval) * mInterval;
return value; }
private void updatePreference(int newValue) {
SharedPreferences.Editor editor = getEditor(); editor.putInt(getKey(), newValue); editor.commit(); }
}
EDIT: I have found that creating a second class with the excat same code but different name an using one of each solves the problem = worst soulution ever. I do not want to do this. anyone have any idea?
Not a real solution but defining your layout as xml will lead to a better and faster program. You might solve your problem on the way. Needless to say that if your hacking something together its not wrong to do it programaticaly. That said...
You could try taking the elements that flow left to right and placing them in a linear view and setting it horizontally then stacking those elements into a vertical linear view. It seems that floating the views side by side is causing the phone to make the bars jump back and forth.A classic css problem( I am interchanging float and gravity )
I think that what is happening is when you update the seek bar the phone is updating the view and coming to different calculations for the positions of the floated views. If you lay everything out using vertical and horizontal linear views it should fix you problem and make your layouts much simpler.
I am guessing that this is an inline preference, like a CheckboxPreference
, instead of a DialogPreference
like an EditTextPreference
.
If so, take a look at your code and make sure you're not somehow sharing stuff inadvertently between multiple instances of the same preference. I have only done DialogPreferences
, so I'm not quite sure how an inline preference is set up. But if, say, you are calling findViewById()
on the activity or something to get your SeekBar
, I can see where your two preferences could accidentally become intertwined. Or, if you are using mutable static data members, I could see potential problems there.
Beyond that, as Mr. Bross suggested, it's tough to give you advice without seeing the code.
精彩评论