问题描述
目标
当用户的手指移开自定义按钮的onResponderRelease()
时,取消该按钮。有没有在网上找不到的标准方法?
我尝试过的事情
使用onLayout
来获取组件的位置,并使用onResponderMove
的{{1}}的pageX / pageY来计算单击区域。但是,onLayout仅获得相对于父级的位置,因此不适用于模态。
GestureResponderEvent
其他想法
我还考虑过使用 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>
)
和裁判的useRef
。这可能有效。我正在使用的另一个库中的某个组件的引用中似乎没有measure
,所以我担心的是这可能不是最灵活的解决方案。
measure
解决方法
以下列方式使用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。
最后我得到了一个简单的钩子,只需将其放置在组件的引用上
const useMeasurement = (buffer = 0) => {
const ref = useRef<View | null>(null)
const [dimensions,})
/* 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,width,height,py) => {
setDimensions({
minX: px - buffer,maxX: px + width + buffer,minY: py - buffer,maxY: py + height + buffer,})
})
}
},[ref.current])
return { dimensions,setRef }
}