Цветная полоса SeekBar не соответствует прогрессу и большому пальцу
Когда экран вращается, цветная полоса моей панели поиска возвращается к своему первоначальному значению, в то время как большой палец остается в правильном положении.
В основном из этого:
Это становится так:
Обратите внимание, что TextView
показ 15
подключен к панели поиска и правильно показывает то же значение, которое обновляется в onCreateView
получение значения с getProgress
на панели поиска, поэтому панель поиска имеет правильный внутренний прогресс, но "забывает" обновить свою панель. Также обратите внимание, что при небольшом перемещении панель будет обновлена правильно.
Странно то, что у меня есть идентичная панель поиска, на которой я выполняю точно такие же действия (вызовы методов и т. Д.), Но эта проблема никогда не возникает.
Они определены таким же образом в файле макета XML (за исключением id
).
Эти панели поиска находятся внутри Fragment
показано в ViewPager
Вот более или менее код для фрагмента:
public class NewCharacterNameFragment extends Fragment
implements NumericSeekBar.OnValueChangedListener {
private static final String LEVEL = "org.my.package.LEVEL";
private static final String STATS = "org.my.package.STATS";
private NumericSeekBar levelBar; // Causing problems
private NumericSeekBar statsBar; // Well behaved
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
if (savedInstanceState == null) { // defaults values to avoid multiple checks later
savedInstanceState = new Bundle();
savedInstanceState.putInt(LEVEL, 1);
savedInstanceState.putInt(STATS, 30);
}
View view = inflater.inflate(R.layout.new_character_name_fragment, container,
false);
levelBar = (NumericSeekBar) view.findViewById(R.id.levelSeekBar);
statsBar = (NumericSeekBar) view.findViewById(R.id.statPointsSeekBar);
levelBar.setValue(savedInstanceState.getInt(LEVEL));
levelBar.setMax(20);
levelBar.setValueChangedListener(this);
statsBar.setValue(savedInstanceState.getInt(STATS));
statsBar.setMax(100);
statsBar.setValueChangedListener(this);
// Initialize the text-views with the progress values:
TextView tView = (TextView) view.findViewById(R.id.statPointsNumTextView);
tView.setText(Integer.valueOf(statsBar.getValue()).toString());
tView = (TextView) view.findViewById(R.id.levelNumTextView);
tView.setText(Integer.valueOf(levelBar.getValue()).toString());
return view;
}
@Override
public void onSaveInstanceState(Bundle savedInstanceState) {
super.onSaveInstanceState(savedInstanceState);
savedInstanceState.putInt(LEVEL, levelBar.getValue());
savedInstanceState.putInt(STATS, statsBar.getValue());
}
@Override
public void onNumericSeekBarValueChanged(NumericSeekBar bar, int value,
boolean fromUser) {
// Called whenever the seekbar value changes
if (bar == statsBar) {
TextView view = (TextView) getView().findViewById(R.id.statPointsNumTextView);
view.setText(Integer.valueOf(value).toString());
} else if (bar == levelBar) {
TextView view = (TextView) getView().findViewById(R.id.levelNumTextView);
view.setText(Integer.valueOf(value).toString());
}
}
}
куда NumericSeekBar
это виджет, который я создал, и в основном LinearLayout
с двумя кнопками увеличения и уменьшения и панелью поиска:
public class NumericSeekBar extends LinearLayout
implements SeekBar.OnSeekBarChangeListener, View.OnClickListener {
public interface OnValueChangedListener {
public void onNumericSeekBarValueChanged(NumericSeekBar bar, int value,
boolean fromUser);
}
private Button incButton;
private Button decButton;
private SeekBar seekBar;
private OnValueChangedListener listener = null;
private int maxValue = 100;
private int value = 0;
public NumericSeekBar(Context ctx) {
super(ctx);
setOpts();
setWidgets();
}
public NumericSeekBar(Context ctx, AttributeSet attributes) {
super(ctx, attributes);
setOpts();
setWidgets();
}
public void setValueChangedListener(OnValueChangedListener listener) {
this.listener = listener;
}
public void setMax(int maxValue) {
this.maxValue = maxValue;
seekBar.setMax(maxValue);
}
public int getValue() {
return this.value; // using seekBar.getProgress() obtains same results
}
public boolean setValue(int value) {
if (value < 0 || value > maxValue) {
return false;
}
this.value = value;
seekBar.setProgress(value);
return true;
}
@Override
public void onStopTrackingTouch(SeekBar bar) {
bar.setSecondaryProgress(bar.getProgress());
}
@Override
public void onStartTrackingTouch(SeekBar bar) {
}
@Override
public void onProgressChanged(SeekBar bar, int value, boolean fromUser) {
this.value = value;
if (listener != null ){
listener.onNumericSeekBarValueChanged(this, value, fromUser);
}
if (!fromUser) {
bar.setSecondaryProgress(0);
}
}
@Override
public void onClick(View v) {
// Handle increment/decrement button clicks
if (v.equals(incButton)) {
this.setValue(this.getValue() + 1);
} else if(v.equals(decButton)) {
this.setValue(this.getValue() - 1);
}
}
private void setOpts() {
setOrientation(HORIZONTAL);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
setShowDividers(SHOW_DIVIDER_NONE);
}
}
private void setWidgets() {
incButton = new Button(getContext());
decButton = new Button(getContext());
seekBar = new SeekBar(getContext());
incButton.setText("+");
incButton.setTextSize(TypedValue.COMPLEX_UNIT_SP, 16);
incButton.setLayoutParams(new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT,
(float) 0.4));
incButton.setOnClickListener(this);
decButton.setText("-");
decButton.setTextSize(TypedValue.COMPLEX_UNIT_SP, 16);
decButton.setLayoutParams(new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT,
(float) 0.4));
decButton.setOnClickListener(this);
LayoutParams layoutParams = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT,
(float) 0.2);
layoutParams.gravity = Gravity.CENTER;
seekBar.setLayoutParams(layoutParams);
setMax(this.maxValue);
setValue(this.value);
addView(incButton);
addView(seekBar);
addView(decButton);
seekBar.setOnSeekBarChangeListener(this);
}
}
Это происходит как на эмуляторе, так и на физическом устройстве.
РЕДАКТИРОВАТЬ: я только что проверил мое приложение на эмуляторе Android 4, и это не происходит, так что, похоже, что-то связано 2.x.
EDIT2: я пытался invalidate()
бары в onCreateView
, onStart
а также onResume
но проблемы все еще возникают. Я также пытался поставить levelBar.setValue(levelBar.getValue())
в onResume
но ничего не изменилось. Я действительно не понимаю, что происходит.
EDIT3: я добавил другой фрагмент, который содержит шесть из этих столбцов и только levelBar
в коде выше ведет себя странно. Интересно, как это возможно? Либо есть какая-то действительно странная ошибка, либо я делаю что-то не так, хотя я не могу видеть, где (и в Android 4.x все работает хорошо).
EDIT4: мое третье редактирование неверно: теперь почти все бары имеют такое поведение. statsBar
выше, кажется, единственный, который никогда не затрагивается.
2 ответа
Я наконец понял, что не так с кодом.
Кажется, что изменение максимального значения SeekBar
не вызывает перерисовку цветовой шкалы, пока она вызывает перерисовку большого пальца. Это, вероятно, ошибка в Android 2.x(так как это не происходит в Android 4.x).
Чтобы решить эту проблему, вам просто нужно установить максимальное значение, прежде чем устанавливать прогресс на панели поиска.
В моем случае только некоторые бары были затронуты, потому что я установил максимум по умолчанию для NumericSeekBar
до 100, и только бары с другим максимумом, где затронуты.
До сих пор не ясно, почему аннулировать представление в onResume
не производит правильную перерисовку виджета.
Я нахожу метод повторения:
final SeekBar seekBar = (SeekBar) findViewById(R.id.test_seekbar);
seekBar.setMax(4000);
seekBar.setProgress(1500);
new Thread(new Runnable() {
public void run() {
seekBar.setProgress(500);
}
}).start();
for (int i = 0; i < 5000; i++) {
seekBar.setProgress(2000);
}
код выше, называется ProgressBar#setProgress
в рабочем потоке это вызывает ошибку. Официальный совет Android по документации назвал его в главном потоке, например так:
public class MyActivity extends Activity {
private static final int PROGRESS = 0x1;
private ProgressBar mProgress;
private int mProgressStatus = 0;
private Handler mHandler = new Handler();
protected void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.progressbar_activity);
mProgress = (ProgressBar) findViewById(R.id.progress_bar);
// Start lengthy operation in a background thread
new Thread(new Runnable() {
public void run() {
while (mProgressStatus < 100) {
mProgressStatus = doWork();
// Update the progress bar
mHandler.post(new Runnable() {
public void run() {
mProgress.setProgress(mProgressStatus);
}
});
}
}
}).start();
}
}