我有一个内容很多的滚动视图。当用户进行 fling 或向下滚动时,我希望滚动视图停在特定的视图位置,其中我正在进行一些动画,然后用户可以再次 fling 或向下滚动。
我尝试了禁用 scrollview,如此处所述,但它只在 scrollview 完全停止时才禁用,并且不能在 fling 的中途停止。
是否有任何方法可以在达到某个视图位置或特定y值时停止滚动视图的 fling?
我有一个内容很多的滚动视图。当用户进行 fling 或向下滚动时,我希望滚动视图停在特定的视图位置,其中我正在进行一些动画,然后用户可以再次 fling 或向下滚动。
我尝试了禁用 scrollview,如此处所述,但它只在 scrollview 完全停止时才禁用,并且不能在 fling 的中途停止。
是否有任何方法可以在达到某个视图位置或特定y值时停止滚动视图的 fling?
我曾经遇到过同样的问题,我的解决方案是:
listView.smoothScrollBy(0,0)
这将停止滚动。
要在特定点停止 fling,只需调用
fling(0)
velosityY
被设置为0,从而立即停止了短暂操作。/**
* 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.
*/
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 停止滚动。
onScrollChanged
方法并调用 smoothScrollTo
方法,我已经成功停止了 ScrollView 在特定的 y 坐标处滚动。我通过保留一个布尔值来指示这是否是第一次 fling/drag,从而允许用户继续向下滚动超过该点。同样,当从底部向上滚动时,我再次在相同的点停止滚动。然后再次允许用户向上滚动。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;
}
}
});
}
ScrollView
处理 fling 操作。只需重写 ScrollView
中的 fling
方法并注释掉 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);
*/
}
}
我实际上正在使用这种方法:
list.post(new Runnable()
{
@Override
public void run()
{
list.smoothScrollToPositionFromTop(arg2, 150);
}
});