【问题标题】:SeekBar color bar does not match progress and thumbSeekBar 颜色条与进度和拇指不匹配
【发布时间】:2013-01-03 02:26:45
【问题描述】:

当屏幕旋转时,我的搜索栏的彩色条恢复到初始值,而拇指保持在正确的位置。

基本上由此而来:

变成这样:

请注意,显示15TextView 已连接到搜索栏并正确显示相同的值,该值在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()onCreateViewonStartonResume 中的条形,但问题仍然存在。我还尝试在onResume 中添加levelBar.setValue(levelBar.getValue()),但没有任何改变。 我真的不明白发生了什么。

EDIT3:我添加了另一个片段,其中包含六个这样的条,并且只有上面代码中的 levelBar 行为异常。我想知道这怎么可能。要么有一些非常奇怪的错误,要么我做的不正确,即使我看不到哪里(在 android 4.x 中一切正常)。

EDIT4:我的第三次编辑不正确:现在几乎所有的酒吧都有这种行为。上面的statsBar 似乎是唯一一个从未受到影响的。

【问题讨论】:

    标签: android seekbar repaint autorotate


    【解决方案1】:

    我终于明白代码有什么问题了。

    似乎更改SeekBar 的最大值不会触发彩条的重绘,而它确实会触发拇指的重绘。这可能是 android 2.x 中的一个错误(因为它不会在 android 4.x 中发生)。

    要解决这个问题,您只需在设置搜索栏上的进度之前设置最大值

    在我的情况下,只有一些条受到影响,因为我将 NumericSeekBar 的默认最大值设置为 100,并且只有具有不同最大值的条受到影响。

    目前尚不清楚为什么在onResume 中使视图无效不会产生正确的小部件重绘。

    【讨论】:

      【解决方案2】:

      我找到了递归方法:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-05-11
        • 2012-04-28
        • 2020-09-05
        • 2022-01-28
        • 2015-12-11
        • 1970-01-01
        • 2015-10-01
        相关资源
        最近更新 更多