【问题标题】:Android: SeekBar onProgressChanged-event doesn't get fired when setting progress programmaticallyAndroid:以编程方式设置进度时,SeekBar onProgressChanged-event 不会被触发
【发布时间】:2013-08-27 02:58:09
【问题描述】:

当我以编程方式设置 SeekBar 的进度时,我的 onProgressChanged() 事件不会被触发,但是当我以物理方式移动 SeekBar 滑块时,它会被触发得非常好。

我希望在使用 setProgress() 时触发该事件 - Android 开发人员参考甚至指出:

public abstract void onProgressChanged (SeekBar seekBar, int progress, boolean fromUser)

进度级别已更改的通知。客户端可以使用 fromUser 参数来区分用户发起的更改和以编程方式发生的更改。

我项目中的一些代码 sn-ps:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.my_activity);               

    final SeekBar mySeekBar = ((SeekBar) findViewById(R.id.mySeekBar));
    
    mySeekBar.setOnSeekBarChangeListener(new OnSeekBarChangeListener(){
        @Override
        public void onProgressChanged(SeekBar arg0, int arg1, boolean arg2) {
            // Do some stuff
        }
    }
}


@Override
protected void onResume() {
    super.onResume();

    final SeekBar mySeekBar = ((SeekBar) findViewById(R.id.mySeekBar));
    mySeekBar.setProgress(someValue); // This SHOULD trigger onProgressChanged(), but it doesn't...
}

【问题讨论】:

    标签: android seekbar


    【解决方案1】:

    刚才偶然发现了同样的问题。

    在我的例子中,onProgressChanged 并没有因为值实际上没有改变而被解雇。我设置的值与当前值相同 (0 :)

    (我看不出你的代码有什么问题)

    【讨论】:

      【解决方案2】:

      Romuald Brunet 的回答 +1:

      这是我修复它的“技巧”:

              <SeekBar android:id="@+id/seekbar" 
                  android:layout_width="match_parent" 
                  android:layout_height="wrap_content"  
                  android:progress="1"
                  android:max="200" />
      

      注意 progress="1",将布局中的默认进度设置为 1,然后在我的代码中,当我实际将其默认为 0 时,进度发生变化并触发 onProgressChanged() 事件。

      【讨论】:

      • 没有为我解决(holo 无处不在 + android 5.1.1)
      • 这既不是修复也不是破解,因为如果进度设置为 1,onProgressChanged 不会被触发
      【解决方案3】:

      我可以确定setProgress 适用于 Android 6.0.1 版本。

      另一个StackOverflow answer 说这是一个错误。如果这是真的,那肯定不再是这样了。

      此代码适用于我的测试设置:

      @Override
      public void onResume() {
          super.onResume();
      
          SeekBar seekBar = (SeekBar)findViewById(R.id.seek_bar);
          seekBar.setProgress(seekBar.getProgress());
      }
      

      正如预期的那样,SeekBarOnSeekBarChangeListener 正在被调用。

      对于故障排除,请确保您使用setOnSeekBarChangeListener() 正确设置了侦听器,并确保您实现了接口函数。 其他 SO 答案似乎表明您应该只从 UI 线程调用 setProgress()This answer 展示了如何做到这一点。

      【讨论】:

      • @Downvoter。 (或其他任何人)。我想知道这个答案是否有错误,以便更正。谢谢!
      • if (progress == mProgress) { // 与当前没有变化。返回假;这段代码来自 ProgressBar.java 你可以自己查看。如果进度和之前一样,它不会给你回调
      【解决方案4】:

      SeekBar.OnSeekBarChangeListener.onProgressChanged 仅在实际更改进度时调用,不一定在调用 setProgress 时调用 - 只有当新进度与上一个不同时才会发生这种情况。

      查看the source of SeekBar,它扩展了AbsSeekBar,又扩展了ProgressBar,我们可以看到对setProgress() 的调用不会触发onProgressChanged() 事件,除非新进度与之前的进度不同如下图所示。

      /* 
          Snippet from ProgressBar.java 
      */
      
      public void setProgress(int progress, boolean animate) {
          setProgressInternal(progress, false, animate);
      }
      
      
      synchronized boolean setProgressInternal(int progress, boolean fromUser, boolean animate) {
          if (mIndeterminate) {
              // Not applicable.
              return false;
          }
      
          progress = MathUtils.constrain(progress, mMin, mMax);
          if (progress == mProgress) {
              // No change from current.
              return false;
          }
      
          mProgress = progress;
          refreshProgress(R.id.progress, mProgress, fromUser, animate);
          return true;
      }
      

      【讨论】:

        【解决方案5】:

        直接调用

         mySeekBar.setOnSeekBarChangeListener(new OnSeekBarChangeListener(){
            @Override
            public void onProgressChanged(SeekBar arg0, int arg1, boolean arg2) {
               int i=    arg0.getProgress();
             //youre seekbar.setProgress(i);
            }
        }
        

        【讨论】:

          【解决方案6】:

          在xml文件中设置progress=10如下图:

          <SeekBar android:id="@+id/seekbar" 
            android:layout_width="match_parent" 
            android:layout_height="wrap_content"  
            android:progress="10"
            android:max="100" />
          

          然后在主文件中写入以下代码:

          new Handler().postDelayed(new Runnable() {
                                  @Override
                                  public void run() {
                                      seekbar.setProgress(50)
                                  }
                              }, 100);
          

          减少延迟,以免影响 UI。

          【讨论】:

            【解决方案7】:

            一种可能的解决方法是创建自己的小部件来扩展 Seekbar 并根据您的需要实现两种方法:

                private OnSeekBarChangeListener onSeekBarChangeListener;
            
                @Override
                public void setOnSeekBarChangeListener(OnSeekBarChangeListener l) {
                    super.setOnSeekBarChangeListener(l);
                    onSeekBarChangeListener = l;
                }
            
                @Override
                public void setProgress(int progress) {
                    super.setProgress(progress);
                    if (onSeekBarChangeListener != null) {
                        onSeekBarChangeListener.onProgressChanged(this, progress, false);
                    }
                }
            

            【讨论】:

              【解决方案8】:

              接受的答案对我不起作用,因为当进度以编程方式设置为 1 时它停止被触发(这是相同的错误)。

              我所做的是自己调用 onProgressChanged()。我的搜索栏是一个成员变量。

              void setProgressValue(int progress){
                  if(progress == 0){ //the default progress is 0. if i set it to 0 again the call back wont be invoked
                      mSeekBar.setProgress(progress);
                      onProgressChanged(progress,mSeekBar,false);
                  }
              }
              
              @Override
              public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                  //things to be done when the call back is received
              }
              

              发帖希望以后能帮助到别人。

              【讨论】:

                【解决方案9】:

                我的监听器没有触发,因为我在设置监听器之前调用了setProgress()

                【讨论】:

                  【解决方案10】:

                  您需要确保该值确实发生了变化,否则将不会被拾取。放入2行。第一个不想要。第二个想要的。

                  seekbar.setProgress(7); // Necessary to force the change to desired
                  seekbar.setProgress(50); // Desired progress
                  

                  【讨论】:

                    猜你喜欢
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2012-04-05
                    • 2012-03-14
                    • 1970-01-01
                    相关资源
                    最近更新 更多