移动开发UI组件【免费下载链接】react-native-gesture-handlerDeclarative API exposing platform native touch and gesture system to React Native.项目地址https://gitcode.com/gh_mirrors/re/react-native-gesture-handler点击查看免费下载本文档基于 react-native-gesture-handler 仓库的packages/docs-gesture-handler/versioned_docs/version-2.x/guides/swipe-and-scroll.md编写深入解析在 Web 平台上自定义 swipeable 组件嵌入 ScrollView 后滚动失效的根本原因以及通过GestureDetector的touchAction属性pan-y进行修复的方案。文章结合仓库源码、官方文档与测试用例帮助读者理解touch-actionCSS 属性与手势识别之间的关系掌握在 ScrollView 中实现“既能左右滑动又能上下滚动”的完整实践路径。问题背景自定义 Swipeable 与 ScrollView 的滚动冲突在 React Native Gesture Handler 中我们通常推荐直接使用官方提供的ReanimatedSwipeable组件来实现可滑动的行或类似交互。该组件会在一个可平移的容器中渲染子内容并支持左右滑动滑动过程中可根据用户向左或向右滑动的方向展示左右两侧的“操作容器”通过renderLeftActions或renderRightActions渲染。然而在某些场景下开发者需要自定义自己的 swipeable 组件以获取对行为更多的控制权。例如需要定制滑动阈值、自定义动画、或集成其他手势逻辑。但自定义 swipeable 组件后一个常见的问题是当该组件被放置在 ScrollView 内部时滚动不再工作。问题的本质在于当你的手势处理器如 Pan在 Web 平台上开始拦截触摸事件后浏览器默认的滚动行为即 ScrollView 的滚动会被禁用。这导致用户滑动时页面无法上下滚动。解决方案核心touchAction属性修复该问题的关键是在GestureDetector上添加touchAction属性并将其设置为pan-y如下所示GestureDetector gesture{...} ... touchActionpan-y ... /GestureDetector这样做的原理是touch-action是 CSS 属性它允许开发者指定在触摸屏上如何允许用户操作该元素例如平移、缩放。将其设置为pan-y意味着仅允许垂直方向的平移即上下滚动而水平方向的平移如左右滑动则交由你的手势处理器来处理。这样既保留了 ScrollView 的垂直滚动能力又不影响自定义 swipeable 组件的水平滑动功能。touchAction参数详解在gesture-handlerCommon.ts中touchAction被定义为一个联合类型支持所有 CSStouch-action取值export type TouchAction | auto | none | pan-x | pan-left | pan-right | pan-y | pan-up | pan-down | pinch-zoom | manipulation | inherit | initial | revert | revert-layer | unset;从源码结构看该类型覆盖了 CSStouch-action规范中的全部取值。其中与滚动冲突修复最相关的是取值含义none禁止所有浏览器默认触摸行为默认值pan-y仅允许垂直方向平移保留上下滚动pan-x仅允许水平方向平移auto浏览器自动决定触摸行为manipulation允许平移与缩放但禁用双击缩放GestureDetector的touchAction属性在GestureDetector/index.tsx中被定义注释明确指出该参数用于指定应用于底层视图的touchAction属性支持所有 CSStouch-action值例如none、pan-y默认值为none。这也是为何不设置touchAction时ScrollView 的滚动会被禁用的直接原因手势检测器在 Web 上默认将底层视图的touch-action设置为none从而关闭了浏览器原生的滚动行为。为什么默认值是none源码级原理在 Web 平台上react-native-gesture-handler 通过GestureHandlerWebDelegate将手势处理器的配置应用到 DOM 元素上。其核心逻辑如下private setTouchAction() { const touchAction this.gestureHandler.touchAction; this.ensureView(this.view); const value this.gestureHandler.enabled ? (touchAction ?? DEFAULT_TOUCH_ACTION) : this.defaultViewStyles.touchAction; this.setViewStyle(touchAction, value); this.setViewStyle(WebkitTouchCallout, value); }而当手势处理器处于启用状态enabled且开发者未显式指定touchAction时会使用常量DEFAULT_TOUCH_ACTION none。这意味着默认情况下手势处理器所绑定的 DOM 元素会被设置为touch-action: none浏览器将不再处理任何默认触摸行为——包括 ScrollView 的滚动。这也解释了为什么自定义 swipeable 组件嵌入 ScrollView 后滚动失效Pan 手势处理器启用后其绑定的视图的touch-action变为none水平方向的手势swipeable 的滑动被手势库接管但垂直方向的滚动也被一并禁用了。而NativeViewGestureHandlerNativeViewGestureHandler.ts则会在合适的时机恢复视图样式例如view.style[touchAction] auto以还原默认触摸行为。修复方案的实施细节1. 在GestureDetector上设置touchActionpan-y这是文档推荐的最小修复方案。直接在自定义 swipeable 组件内部的GestureDetector上添加该属性import { GestureDetector, Gesture } from react-native-gesture-handler; function CustomSwipeable({ children }) { const pan Gesture.Pan() .onUpdate((e) { // 处理水平滑动逻辑 }); return ( GestureDetector gesture{pan} touchActionpan-y {children} /GestureDetector ); }这样浏览器仍会保留垂直滚动的默认行为而水平滑动则由 Pan 手势处理。2. 使用官方ReanimatedSwipeable组件推荐如果你不需要完全自定义 swipeable 的行为建议直接使用官方组件import Swipeable from react-native-gesture-handler/ReanimatedSwipeable;在ReanimatedSwipeable.tsx中官方组件内部已经为 Pan 手势和 Tap 手势都设置了touchActionpan-yGestureDetector gesture{panGesture} touchActionpan-y Animated.View ... ... GestureDetector gesture{tapGesture} touchActionpan-y Animated.View style{[animatedStyle, childrenContainerStyle]} {children} /Animated.View /GestureDetector /Animated.View /GestureDetector因此使用官方ReanimatedSwipeable时无需手动处理滚动冲突——该组件在 Web 上已内置了pan-y的touchAction配置。测试验证在仓库的 Web 手势处理器单元测试GestureHandler.test.ts中对touchAction的配置传递与重置行为进行了验证配置传递当检测器detector发送包含touchAction: pan-y的配置更新时handler.touchAction保持为pan-y默认值恢复当检测器重新发送默认值DEFAULT_TOUCH_ACTION即none时handler.touchAction恢复为none。这验证了touchAction属性在 Web 平台上会被完整传递到手势处理器并在未设置时回退到默认值none。其他相关属性userSelect与enableContextMenu除了touchAction之外GestureDetector在 Web 平台上还提供另外两个仅 Web 可用的属性它们与touchAction共同组成“Web 视图行为控制”三件套均定义于GestureDetector/index.tsx属性类型默认值说明touchActionTouchActionnone指定应用于底层视图的touch-actionCSS 属性userSelectnone \| auto \| textnone指定应用于底层视图的user-selectCSS 属性enableContextMenubooleanfalse指定右键点击底层视图后是否启用上下文菜单总结步骤操作说明1创建自定义 swipeable 组件使用Gesture.Pan()实现水平滑动2将组件放入 ScrollView发现垂直滚动失效3在GestureDetector上添加touchActionpan-y恢复垂直滚动保留水平滑动4可选使用官方ReanimatedSwipeable内部已内置pan-y配置核心要点默认touch-action: none手势处理器在 Web 上默认将绑定视图的touch-action设为none见constants.ts这会禁用 ScrollView 的原生滚动pan-y的语义仅允许垂直平移水平滑动交由手势处理器处理从而实现“既能左右滑动又能上下滚动”官方组件已内置ReanimatedSwipeable内部对 Pan 与 Tap 手势均已设置touchActionpan-y无需手动处理仅 Web 生效touchAction是 Web 平台专属属性在 iOS / Android 原生平台上由原生触摸系统直接处理无需也不支持该配置。赞分享移动开发UI组件【免费下载链接】react-native-gesture-handlerDeclarative API exposing platform native touch and gesture system to React Native.项目地址https://gitcode.com/gh_mirrors/re/react-native-gesture-handler点击查看免费下载相关推荐react-native-gesture-handler Web 端自定义 Swipeable 组件在 ScrollView 中滚动失效的修复touchActionpan-y 详解react native gesture handler Web 端自定义 Swipeable 组件在 ScrollView 中滚动失效的修复touchAct移动开发UI组件LogicFlow中滑动组件与自定义节点拖动的冲突解决方案LogicFlow中滑动组件与自定义节点拖动的冲突解决方案 问题背景 在使用LogicFlow进行流程图编辑时开发者可能会遇到两个常见的交互冲突问题 1.前端低代码流程编排上一篇Windows热键冲突终极解决方案Hotkey Detective热键侦探完整指南下一篇如何用Calibre-Douban插件一键获取豆瓣图书元数据告别手动整理的终极指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
阅读完成 · 觉得有帮助?