画面が回転すると、シークバーの色付きのバーが初期値に戻りますが、親指は正しい位置に留まります。
基本的にこれから:
次のようになります。
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
には 2 つのインクリメント ボタンとデクリメント ボタンとシークバーがあります。
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:これらのバーのうち 6 つを含む別のフラグメントを追加しましたがlevelBar
、上記のコードのみが奇妙に動作します。これがどのように可能なのだろうか。本当に奇妙なバグがあるか、場所がわかりませんが、適切に何かをしていません(Android 4.xではすべて正常に動作します)。
EDIT4:私の 3 番目の編集は正しくありません: 現在、ほぼすべてのバーがこの動作をしています。上記statsBar
は影響を受けない唯一のもののようです。