如何使Android的滑动条平滑移动?

12

我想让SeekBar的移动更加平滑,而不是直接跳到位置。我正在这样做,因为我有一个具有3个选项的SeekBar,用于实现滑块类型的实现。

我希望创建一个漂亮流畅的滑块,其具有3个选项“是”,“无选项”,“否”,这是我的应用程序中的一个功能,并且SeekBar看起来是最好和最容易的方法。

我尝试查看Android Animation,但似乎有点复杂,所以如果有人能提供任何帮助,那将是很好的:)

6个回答

14

我发现了以下解决方案,可以使SeekBar平滑移动,但仍然将其捕捉在有限的值范围内。假设您的布局中具有以下视图:

<SeekBar
  android:id="@+id/sldProgress"
  style="@style/MySliderStyle"
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  android:max="100"
  android:progress="50" />

<TextView
  android:id="@+id/lblProgress"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:text="5" />

您可以在活动中使用以下代码(根据需要更改上面xml中的android:max值和下面代码中的平滑系数 - 较高的值=更平滑):

public class MyActivity extends Activity {
  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    sliderListener sldListener = new sliderListener();
    SeekBar sldProgress = (SeekBar) findViewById(R.id.sldProgress);
    sldProgress.setOnSeekBarChangeListener(sldListener);
  }
  private class sliderListener implements OnSeekBarChangeListener {
    private int smoothnessFactor = 10;
    public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
      progress = Math.round(progress / smoothnessFactor);
      TextView lblProgress = (TextView) findViewById(R.id.lblProgress);
      lblProgress.setText(String.valueOf(progress));
    }

    public void onStartTrackingTouch(SeekBar seekBar) {
    }

    public void onStopTrackingTouch(SeekBar seekBar) {
      seekBar.setProgress(Math.round((seekBar.getProgress() + (smoothnessFactor / 2)) / smoothnessFactor) * smoothnessFactor);
    }
  }
}

5
谁给这个回答踩了个负,请解释一下有什么问题-请记住,踩负应该只用于极端情况,即回答没有付出任何努力或者回答很危险。如果这个回答是有害的,我想知道为什么!谢谢。 - Russ
1
Integer.parseInt(String.valueOf(Math.round(progress / smoothnessFactor))); 这看起来不对。progress/smoothnessFactor总是会产生一个整数,所以没有必要将其四舍五入,然后再将其转换为字符串,最后再转回整数。 - theelfismike
5
就这些吗?这不会对你的应用程序造成太大的影响吧?我已经修改了代码,删除了那些不必要的转换(任何人都可以做到这一点 - 没有必要投反对票)。 - Russ
5
如果答案可以通过删除几行来纠正,那么请不要点踩它的答案错误。恶意点踩者同样会让 Stack Overflow 混乱不堪。请明智使用点赞和点踩功能。 - Siddharth
1
@theelfismike 感谢你至少告诉我是什么问题,但请查看有关投票下降的准则:http://stackoverflow.com/privileges/vote-down - Russ
您不需要将最大值定义为100,这是默认值。 - worked

6

您不需要自己构建任何东西,只需使用Android动画即可为您完成

代码用Kotlin编写

    mySeekbar.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
        override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) {
            //Todo: code
        }

        override fun onStartTrackingTouch(seekBar: SeekBar?) {
        }

        override fun onStopTrackingTouch(seekBar: SeekBar) {
            if (seekBar.progress > 70) {
                ObjectAnimator.ofInt(seekBar, "progress", 100).setDuration(100).start()
            } else if (seekBar.progress < 30) {
                ObjectAnimator.ofInt(seekBar, "progress", 0).setDuration(100).start()
            } else {
                ObjectAnimator.ofInt(seekBar, "progress", 50).setDuration(100).start()
            }
        }
    })

4

我自己构建了控件。工作完成 :) 代码在这里


1
+1 你可以添加源代码,这样将来的访问者就能得到帮助。 - Eng.Fouad
我会的,我会在推送最新版本的应用程序后尽快发布它。我认为这个应用程序已经是开源的了。 - Joe Simpson
3
承诺过的,https://github.com/kennydude/Speaker/blob/master/src/me/kennydude/speaker/SmoothSeekBar.java,该位置将随着代码更新而更新。 - Joe Simpson

2
创建自定义SeekBar
public class SmoothSeekBar extends AppCompatSeekBar implements SeekBar.OnSeekBarChangeListener {

private SeekBar.OnSeekBarChangeListener mOnSeekBarChangeListener;

private boolean mNeedCallListener = true;

private ValueAnimator mAnimator;

public SmoothSeekBar(Context context) {
    super(context);
    init(context);
}

public SmoothSeekBar(Context context, AttributeSet attrs) {
    super(context, attrs);
    init(context);
}

public SmoothSeekBar(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    init(context);
}


public void init(Context context) {
    Context mContext = context;
}

@Override
public void setOnSeekBarChangeListener(
        SeekBar.OnSeekBarChangeListener onSeekBarChangeListener) {
    mOnSeekBarChangeListener = onSeekBarChangeListener;
    super.setOnSeekBarChangeListener(this);
}

@Override
public void setProgress(final int progress) {
    final int currentProgress = getProgress();
    if (mAnimator != null) {
        mAnimator.cancel();
        mAnimator.removeAllUpdateListeners();
        mAnimator.removeAllListeners();
        mAnimator = null;
        mNeedCallListener = true;
    }
    mAnimator = ValueAnimator.ofInt(currentProgress, progress);
    mAnimator.setDuration(getResources().getInteger(android.R.integer.config_longAnimTime));
    mAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
    mAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            int value = (int) animation.getAnimatedValue();
            if (value == progress) {
                mNeedCallListener = true;
            } else {
                mNeedCallListener = false;
            }
            Logger.e("ProgressBar value ", value + "");
            SmoothSeekBar.super.setProgress(value);
        }
    });
    mAnimator.start();

}

@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
    if (fromUser || mNeedCallListener) {
        if (mOnSeekBarChangeListener != null) {
            mOnSeekBarChangeListener.onProgressChanged(seekBar, progress, fromUser);
        }
    }
}

@Override
public void onStartTrackingTouch(SeekBar seekBar) {
    if (mOnSeekBarChangeListener != null) {
        mOnSeekBarChangeListener.onStartTrackingTouch(seekBar);
    }
}

@Override
public void onStopTrackingTouch(SeekBar seekBar) {
    if (mOnSeekBarChangeListener != null) {
        mOnSeekBarChangeListener.onStopTrackingTouch(seekBar);
    }
}
}

现在在xml中添加SeekBar并享受它。
 <com.yourPackage.SmoothSeekBar
    android:id="@+id/seekBar"
    style="?android:attr/progressBarStyleHorizontal"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"/>

1
这对我很有帮助,非常简单明了。
if (currentPosition > 0) {
    ObjectAnimator animation = ObjectAnimator.ofInt(seekBar, "progress", currentPosition);
    animation.setDuration(400);
    animation.setInterpolator(new DecelerateInterpolator());
    animation.start();
}

0
我为平滑拖动条动画制作了一个自定义视图库。
试试看吧!

https://github.com/WoochanLee/SmoothSeekBar

  • settings.gradle
dependencyResolutionManagement {
    ...
    repositories {
        ...
        maven { url "https://jitpack.io" }
    }
}
  • build.gradle
dependencies {
    ...
    implementation 'com.github.WoochanLee:SmoothSeekBar:1.0.0'
}
  • 在你的 XML 中
<com.woody.lee.library.smoothseekbar.SmoothSeekBar
    android:layout_width="match_parent"
    android:layout_height="wrap_content" />

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接