背景:我有一个ScrollView / TextView对,它接收来自外部源的间歇性文本流.它会在每次更新时自动滚动到底部.
我希望用户能够通过手动滚动到某个地方来突破自动向下滚动模式,但是我不清楚如何将手动滚动与我自己编写的程序滚动区分开来.
我的UI更新在计时器上运行以缓冲重绘:
- private Handler outputUpdater = new Handler ();
- private static String outputBuffer = "";
- private static boolean outputHasChanged = false;
- private static final Object lock = new Object ();
- private Runnable outputUpdaterTask = new Runnable () {
- public void run () {
- synchronized (lock) {
- // if the output has changed,update the TextView
- if (outputHasChanged) {
- TextView tv = (TextView) findViewById (R.id.textView);
- tv.setText (outputBuffer);
- }
- // if the output has changed,or the scroll hasn't reached the bottom yet
- // then keep scrolling down
- if (outputHasChanged || !scrollAtBottom ()) {
- ScrollView sv = (ScrollView) findViewById (R.id.scrollView);
- sv.fullScroll (View.FOCUS_DOWN);
- }
- outputHasChanged = false;
- }
- outputUpdater.postDelayed (this,100);
- }
- };
scrollAtBottom从onScrollChanged处理程序获取它的值.
一切正常.即使没有文本更新也需要调用fullScroll,因为如果有TextView更新,或者虚拟键盘可见性发生变化等,对fullScroll的单次调用并不总是到底.
我希望如果用户手动滚动,我可以知道决定停止调用fullScroll.
不幸的是,仅仅将“从底部,自动模式”到“不在底部”的转换视为切换到手动模式的提示似乎还不够,因为各种UI更改似乎也将滚动视图从底部移开(例如虚拟键盘显示).
问题重述:
如何区分用户启动的滚动与编程滚动?
解决方法
您是否尝试过使用onTouchEvent的布尔值,类似于:
- boolean userIntercept = false;
- @Override
- public boolean onTouchEvent(MotionEvent me) {
- int action = me.getAction();
- if (action == MotionEvent.ACTION_MOVE) {
- userIntercept = true;
- }
- return super.onTouchEvent(me);
- }
然后在你的outputUpdaterTask中:
- // if the output has changed,or the scroll hasn't reached the bottom yet
- // then keep scrolling down
- if (outputHasChanged || !scrollAtBottom () && !userIntercept) {
- ScrollView sv = (ScrollView) findViewById (R.id.scrollView);
- sv.fullScroll (View.FOCUS_DOWN);
- }
您只需要确定一种方法,即将userIntercept返回到false,以最适合您的应用程序的方式.