2013-01-19 79 views
1

當屏幕旋轉時,我的搜尋欄顏色條返回到其初始值,而拇指保持在正確的位置。SeekBar顏色條與進度和拇指不匹配

基本上從該:

enter image description here

它成爲這樣的:

enter image description here

注意,TextView表示15被連接到搜索條和正確地顯示相同的值,這在onCreateView中更新,在seekbar上檢索getProgress的值,所以seekba r 在內部有正確的進度,但「忘記」更新其欄。另請注意,如果稍微移動,則欄會正確更新。

奇怪的是,我有一個完全相同的行爲(方法調用等)相同的seekbar,但這個永遠不會有這個問題。

它們在XML佈局文件中的定義方式相同(id除外)。

這些seekbars顯示爲ViewPager一個Fragment內,這裏或多或少的片段代碼:

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()的酒吧onCreateViewonStartonResume,但問題仍未解決。我也試圖把levelBar.setValue(levelBar.getValue())放入onResume,但沒有任何變化。 我真的不明白髮生了什麼事。

EDIT3:我添加了含有這些酒吧的六隻在上面的代碼中levelBar行爲異常的其他片段。我想知道這是怎麼可能的。或者有一些非常奇怪的錯誤,或者我做的東西不正確,即使我看不到在哪裏(並且在Android 4.x中都可以正常工作)。

EDIT4:我的第三個編輯是不正確:現在幾乎所有的酒吧都有這種行爲。上述statsBar似乎是唯一一個從未受到影響的人。

回答

1

我終於明白代碼出了什麼問題。

看起來好像改變了SeekBar的最大值而不是觸發重新繪製顏色條,同時它確實觸發重新繪製拇指。這可能是Android 2.X的錯誤(因爲它沒有在安卓4.x的發生)。

要解決此問題,您只需在之前設置最大值,即可在seek-bar上設置進度。

在我的情況下,只有一些酒吧受到影響,因爲我默認最大爲NumericSeekBar設置爲100,只有用不同的最大酒吧,在那裏的影響。

它仍然不是爲什麼onResume無效視圖不會產生正確的重新繪製widget的清晰。

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(); 
} 
}