当屏幕旋转时,我的搜索条的彩色条会回到初始值,而拇指则保持在正确的位置。
基本上是这样的:
它变成这样:
请注意,显示TextView
的{{1}}已连接到搜索栏并正确显示相同的值,该值会在15
中更新,并在搜索栏上使用onCreateView
检索值,所以搜索栏在内部正确进行,但“忘记”更新其栏。另请注意,如果稍微移动,条形图将正确更新。
奇怪的是,我有一个相同的搜索栏,我在其上执行完全相同的操作(方法调用等),但这个问题从未出现过这个问题。
它们在XML布局文件中以相同的方式定义(getProgress
除外)。
这些搜索栏位于显示为id
的{{1}}内,这里或多或少是片段的代码:
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
在仿真器和物理设备上都会发生这种情况。
编辑:我刚刚在Android 4模拟器上测试了我的应用程序,但这不会发生,所以它似乎与2.x有关。
EDIT2:我已尝试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);
}
}
,invalidate()
和onCreateView
中的条形码,但问题仍然存在。我还尝试在onStart
中添加onResume
,但没有任何改变。
我真的不明白发生了什么。
EDIT3:我添加了另一个包含其中六个条形的片段,上面代码中只有levelBar.setValue(levelBar.getValue())
表现得很奇怪。我想知道这怎么可能。要么有一些非常奇怪的错误,要么我做的事情不正确,即使我看不到哪里(并且在android 4.x中一切正常)。
EDIT4:我的第三次修改不正确:现在几乎所有栏都有此行为。上面的onResume
似乎是唯一一个从未受到影响的人。
答案 0 :(得分:1)
我终于明白了代码的错误。
似乎更改SeekBar
的最大值不会触发彩条的重绘,同时触发重绘拇指。这可能是android 2.x中的一个错误(因为它不会发生在android 4.x中)。
要解决此问题,您只需在设置搜索栏上的进度之前设置的最大值。
在我的情况下,只有一些酒吧受到影响,因为我将NumericSeekBar
的默认最大值设置为100,并且只有受影响的最大值不同的栏。
目前还不清楚为什么onResume
中的视图无效,无法正确重新绘制小部件。
答案 1 :(得分:0)
我找到了重复方法:
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();
}
}