react-native - 拖动手指时取消按钮单击
问题描述
目标
onResponderRelease()
当用户的手指离开它时取消自定义按钮。有没有我在网上找不到的标准方法?
我试过的
onLayout
用于抓取组件的位置和onResponderMove
的GestureResponderEvent
pageX/pageY 来计算点击区域。但是,onLayout 仅获取相对于父级的位置,因此这不适用于模态。
const handleMove = (e: GestureResponderEvent) => {
const { pageX, pageY } = e.nativeEvent
if (pageX < minX || pageX > maxX || pageY < minY || pageY > maxY) {
setCancelClick(true)
setLongPressed(false)
setPressed(false)
}
}
const setComponentDimensions = ({ nativeEvent }: LayoutChangeEvent) => {
const { x, y, width, height } = nativeEvent.layout
setMinX(x - BUFFER)
setMaxX(x + width + BUFFER)
setMinY(y - BUFFER)
setMaxY(y + height + BUFFER)
}
return (
<View
style={[style, pressed && pressedStyle]}
onStartShouldSetResponder={() => true}
onResponderGrant={() => setPressed(true)}
onResponderRelease={handleRelease}
onResponderMove={handleMove}
onLayout={setComponentDimensions}
onResponderTerminationRequest={() => false}
{...ViewProps}>
{children}
</View>
)
其他想法
我也考虑过使用 auseRef
和 ref's measure
。这可能会奏效。我正在使用的另一个库中的组件似乎没有measure
它的引用,所以我担心这可能不是最灵活的解决方案。
const viewRef = useRef(null as View | null)
useEffect(() => {
if (viewRef.current) {
// TODO: base calculations off of measure
console.log(viewRef.current.measure)
}
}, [viewRef.current])
...
return (
<View
ref={(view) => (viewRef.current = view)}
...
{children}
</View>
)
解决方案
以measure()
下列方式使用似乎对我有用。
const viewRef = useRef(null as View | null)
const [dimensions, setDimensions] = useState({
minX: 0,
maxX: 0,
minY: 0,
maxY: 0,
})
const handleMove = (e: GestureResponderEvent) => {
const { pageX, pageY } = e.nativeEvent
const { minX, maxX, minY, maxY } = dimensions
if (pageX < minX || pageX > maxX || pageY < minY || pageY > maxY) {
setLongPressed(false)
setPressed(false)
}
}
const setComponentDimensions = ({ nativeEvent }: LayoutChangeEvent) => {
const { width, height } = nativeEvent.layout
if (viewRef.current) {
viewRef.current.measure((_a, _b, _width, _height, px, py) => {
setDimensions({
minX: px - BUFFER,
maxX: px + width + BUFFER,
minY: py - BUFFER,
maxY: py + height + BUFFER,
})
})
}
}
return (
<View
ref={(view) => (viewRef.current = view)}
onStartShouldSetResponder={() => true}
onResponderMove={handleMove}
onLayout={setComponentDimensions}
onResponderTerminationRequest={() => false}
{children}
</View>
)
更新
在稍微重构了我的组件并且之前从未尝试过之后,我决定发布一个包。希望它可以帮助其他人:react-native-better-buttons。
我最终得到了一个更简单的钩子,只需要放在组件的 ref 上
const useMeasurement = (buffer = 0) => {
const ref = useRef<View | null>(null)
const [dimensions, setDimensions] = useState({
minX: 0,
maxX: 0,
minY: 0,
maxY: 0,
})
/* This goes on the view's ref property */
const setRef = (view: View) => (ref.current = view)
/*
Updating ref.current does not cause rerenders, which is fine for us.
We just want to check for ref.current updates when component that uses
us rerenders.
*/
useEffect(() => {
if (ref.current && ref.current.measure) {
ref.current.measure((_a, _b, width, height, px, py) => {
setDimensions({
minX: px - buffer,
maxX: px + width + buffer,
minY: py - buffer,
maxY: py + height + buffer,
})
})
}
}, [ref.current])
return { dimensions, setRef }
}
推荐阅读
- javascript - Javascript/HTML - 如何从数组中随机选择并显示它
- html - css-grid rendering differently on Firefox and Chrome
- c# - AWS SES c# sendmailasync 任务被取消
- xcode - Cylceops Hammer Smart Trainer 的蓝牙编程文档
- git - 如果在提交和推送之后完成签出和合并,Git 不会将更改推送到分支
- angular - 从另一个组件调用时,Angular PatchValue 不起作用
- angular - 如何在angular4中隐藏Html表格
- node.js - 无法在 Angular 项目中使用 rxjs 的 map 运算符
- zurb-foundation-6 - 从头开始创建新项目时,浏览器错误“基础不是功能”
- javascript - 基于条件JS的数组操作