我在ScrollView中为歌词文本实现了非常慢的自动滚动:
private Handler timerHandler;
private Runnable timerRunnable;
private boolean isScrolling = false;
private TextView mSongTextTv;
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
....
mSongTextTv.setOnClickListener(this);
// Scroll Hendler
timerHandler = new Handler();
timerRunnable = new Runnable() {
@Override
public void run() {
mScrollView.smoothScrollBy(0, 1); // 1 is how many pixels you want it to scroll vertically by
timerHandler.postDelayed(this, 40); // 40 is how many milliseconds you want this thread to run
}
};
我可以通过单击TextView:
来启动和停止它@Override
public void onClick(View v) {
switch (v.getId()) {
...
case R.id.tv_song:
if (!isScrolling) {
timerHandler.postDelayed(timerRunnable, 0);
isScrolling = true;
Log.d("song tap", " is running = " + isScrolling);
} else {
timerHandler.removeCallbacks(timerRunnable);
isScrolling = false;
Log.d("song tap", " is running = " + isScrolling);
}
break;
}
}
我还使用NestedScrollView.setOnScrollChangeLisener来识别滚动是否到达底部。然后我使用与onClick相同的方法:timerHandler.removeCallbacks(timerRunnable)。我可以在日志中看到这个方法被调用但它没有效果!如果我然后再向上滚动继续自动滚动。这是我的onScrollChangeListener:
mScrollView.setOnScrollChangeListener(new NestedScrollView.OnScrollChangeListener() {
@Override
public void onScrollChange(NestedScrollView v, int scrollX, int scrollY, int oldScrollX, int oldScrollY) {
View view = mScrollView.getChildAt(mScrollView.getChildCount()-1);
int diff = (view.getBottom() - (mScrollView.getHeight() + mScrollView.getScrollY()));
if (diff == 0 && isScrolling) {
timerHandler.removeCallbacks(timerRunnable);
isScrolling = false;
Log.d("song tap", " isScrolling = " + isScrolling);
Log.d("onScrollChange", "reached bottom, diff = " + diff);
}
}
});
所以问题是为什么对removeCallbacks的调用在这种情况下不起作用(当它在onClick中工作时)以及如何在滚动到达底部后停止执行runnable?
答案 0 :(得分:1)
根据方法Handler.removeCallbacks的文件 它仅删除待处理的消息。请致电以下方法:
handler.removeCallbacksAndMessages(null);
删除所有邮件并阻止进一步通话。
答案 1 :(得分:0)
onScrollChange在smoothScrollBy()之后立即调用,它会删除任何回调,但postDelayed()会在此之后执行,并且所有onScrollChange的工作都没有意义。所以解决方案是:
timerRunnable = new Runnable() {
@Override
public void run() {
timerHandler.postDelayed(this, 10); // 10 is how many milliseconds you want this thread to run
mScrollView.smoothScrollBy(0, 5); // 5 is how many pixels you want it to scroll vertically by
}
};