我有一个包含很多内容的滚动视图。现在,当用户进行甩动或向下滚动时,我希望滚动视图停止在特定的视图位置,我正在做一些动画,然后用户可以再次甩动或向下滚动。
我已经尝试过禁用滚动视图,如此处所述,但它仅在滚动视图完全停止并且无法在投掷中间停止时禁用。
当达到某个视图位置或某个 y 值时,有什么方法可以停止滚动视图的滚动?
我有一个包含很多内容的滚动视图。现在,当用户进行甩动或向下滚动时,我希望滚动视图停止在特定的视图位置,我正在做一些动画,然后用户可以再次甩动或向下滚动。
我已经尝试过禁用滚动视图,如此处所述,但它仅在滚动视图完全停止并且无法在投掷中间停止时禁用。
当达到某个视图位置或某个 y 值时,有什么方法可以停止滚动视图的滚动?
我遇到了同样的问题,我的解决方案是。
listView.smoothScrollBy(0,0)
这将停止滚动。
要在特定点停止投掷,只需调用
fling(0)
如果您只关心投掷,我认为这是最合乎逻辑的方式,因为velosityY
设置为 0,因此投掷立即停止。
这是 fling 方法的 javadoc:
/**
* Fling the scroll view
*
* @param velocityY The initial velocity in the Y direction. Positive
* numbers mean that the finger/cursor is moving down the screen,
* which means we want to scroll towards the top.
*/
一种方法可能是使用smoothScrollToPosition,它会停止任何现有的滚动动作。请注意,此方法需要 API 级别 >= 8(Android 2.2,Froyo)。
请注意,如果当前位置远离所需位置,那么平滑滚动将需要相当长的时间并且看起来有点生涩(至少在我对 Android 4.4 KitKat 的测试中)。我还发现调用 setSelection 和 smoothScrollToPosition 的组合有时会导致位置稍微“错过”,这似乎仅在当前位置非常接近所需位置时才会发生。
就我而言,当用户按下按钮时,我希望我的列表跳到顶部(位置 = 0)(这与您的用例略有不同,因此您需要根据您的需要进行调整)。
我使用以下方法
private void smartScrollToPosition(ListView listView, int desiredPosition) {
// If we are far away from the desired position, jump closer and then smooth scroll
// Note: we implement this ourselves because smoothScrollToPositionFromTop
// requires API 11, and it is slow and janky if the scroll distance is large,
// and smoothScrollToPosition takes too long if the scroll distance is large.
// Jumping close and scrolling the remaining distance gives a good compromise.
int currentPosition = listView.getFirstVisiblePosition();
int maxScrollDistance = 10;
if (currentPosition - desiredPosition >= maxScrollDistance) {
listView.setSelection(desiredPosition + maxScrollDistance);
} else if (desiredPosition - currentPosition >= maxScrollDistance) {
listView.setSelection(desiredPosition - maxScrollDistance);
}
listView.smoothScrollToPosition(desiredPosition); // requires API 8
}
然后在我的按钮操作处理程序中,我按如下方式调用它
case R.id.action_go_to_today:
ListView listView = (ListView) findViewById(R.id.lessonsListView);
smartScrollToPosition(listView, 0); // scroll to top
return true;
以上并没有直接回答您的问题,但是如果您可以检测到当前位置何时处于或接近您想要的位置,那么也许您可以使用smoothScrollToPosition来停止滚动。
您需要禁用ScrollView
对投掷操作的处理。为此,只需重写和注释fling
中的方法。让我知道这个是否奏效 !ScrollView
super.fling()
public class CustomScrollView extends ScrollView {
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY)
{
return false;
}
@Override
public void fling (int velocityY)
{
/*Scroll view is no longer gonna handle scroll velocity.
* super.fling(velocityY);
*/
}
}
我正在尝试实现类似的情况。我有一个部分解决方案:
我已经设法通过覆盖onScrollChanged
然后调用smoothScrollTo
. 我允许用户通过保持一个布尔值来继续向下滚动超过该点,该布尔值指示这是否是第一次投掷/拖动。从下到上滚动也是如此——我再次在同一点停止滚动。然后允许用户再次继续向上滚动。
代码看起来像这样:
boolean beenThereFromTop = false;
boolean beenThereFromBottom = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final ScrollView scrollView = (ScrollView) findViewById(R.id.scrollView);
scrollView.getViewTreeObserver().addOnScrollChangedListener(new ViewTreeObserver.OnScrollChangedListener() {
@Override
public void onScrollChanged() {
TextView whereToStop = (TextView) findViewById(R.id.whereToStop);
final int y = whereToStop.getBottom();
int scrollY = scrollView.getScrollY();
// manage scrolling from top to bottom
if (scrollY > y) {
if (!beenThereFromTop) {
beenThereFromTop = true;
scrollView.post(new Runnable() {
@Override
public void run() {
scrollView.smoothScrollTo(0, y);
}
});
}
}
if (scrollY < y && beenThereFromTop) {
beenThereFromTop = false;
}
// manage scrolling from bottom to top
if (scrollY < y) {
if (!beenThereFromBottom) {
beenThereFromBottom = true;
scrollView.post(new Runnable() {
@Override
public void run() {
scrollView.smoothScrollTo(0, y);
}
});
}
}
if (scrollY > y && beenThereFromBottom) {
beenThereFromBottom = false;
}
}
});
}
那么我实际上使用这种方法:
list.post(new Runnable()
{
@Override
public void run()
{
list.smoothScrollToPositionFromTop(arg2, 150);
}
});