SwiftUI如何禁用ScrollView顶部上滑与底部下滑的弹性滚动
问题描述
- 正常滚动视图效果:

- 不希望出现的效果:

我希望禁止用户在ScrollView已处于顶部时继续上滑,或处于底部时继续下滑,请问实现该需求的最佳方案是什么?
分平台实现方案
Android 端
通过自定义ScrollView,重写触摸事件拦截逻辑:
public class CustomScrollView extends ScrollView { private float startY; public CustomScrollView(Context context) { super(context); } public CustomScrollView(Context context, AttributeSet attrs) { super(context, attrs); } public CustomScrollView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override public boolean onTouchEvent(MotionEvent ev) { int scrollY = getScrollY(); int scrollRange = getChildAt(0).getHeight() - getHeight(); switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: startY = ev.getY(); return super.onTouchEvent(ev); case MotionEvent.ACTION_MOVE: float deltaY = ev.getY() - startY; // 顶部状态下拦截上滑操作 if (scrollY == 0 && deltaY > 0) { return true; } // 底部状态下拦截下滑操作 if (scrollY >= scrollRange && deltaY < 0) { return true; } break; } return super.onTouchEvent(ev); } }
使用时直接在布局文件中替换原生ScrollView为该自定义类即可。
iOS 端
自定义UIScrollView,通过手势代理拦截无效滑动:
class CustomScrollView: UIScrollView { override func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool { guard let panGesture = gestureRecognizer as? UIPanGestureRecognizer else { return super.gestureRecognizerShouldBegin(gestureRecognizer) } let translation = panGesture.translation(in: self) // 顶部拦截上滑 if contentOffset.y <= -contentInset.top && translation.y > 0 { return false } // 底部拦截下滑 let bottomOffset = contentSize.height - bounds.height + contentInset.bottom if contentOffset.y >= bottomOffset && translation.y < 0 { return false } return super.gestureRecognizerShouldBegin(gestureRecognizer) } }
替换原生UIScrollView为该自定义类,即可限制边界处的无效滑动。
Web 端
监听触摸事件,拦截边界处的滑动行为:
const scrollContainer = document.querySelector('.scroll-container'); let startY = 0; scrollContainer.addEventListener('touchstart', (e) => { startY = e.touches[0].clientY; }); scrollContainer.addEventListener('touchmove', (e) => { const currentY = e.touches[0].clientY; const deltaY = currentY - startY; // 顶部拦截上滑 if (scrollContainer.scrollTop === 0 && deltaY > 0) { e.preventDefault(); } // 底部拦截下滑 const isAtBottom = scrollContainer.scrollTop + scrollContainer.clientHeight >= scrollContainer.scrollHeight; if (isAtBottom && deltaY < 0) { e.preventDefault(); } });
配合CSS确保事件拦截生效:
.scroll-container { overflow: scroll; touch-action: none; }
内容的提问来源于stack exchange,提问作者Amin Bagheri
相关产品推荐
相关产品推荐

