react-native - ReactNative ScrollView onScroll 适用于 IOS 但不适用于 Android
问题描述
我试图通过使用onScroll函数使 Animated.ScollView 在Reactnative中表现得像一个 bottomSheet,在该函数中我得到 contentOffsetY 并基于此我使 scrollView 卸载/向下拖动(适用于 IOS)。但对于 Android,它不是触发 onScroll 的事件。
import * as React from 'react';
import { StyleSheet, Dimensions, Animated, View } from 'react-native';
const { width, height } = Dimensions.get('window');
import { Icon } from 'react-native-elements';
export const BottomSheet = ({
indicatorMargin,
heightFactor,
children,
gmRef,
dragging = true,
}) => {
const [alignment] = React.useState(new Animated.Value(height));
const [onAnimate, setOnAnimate] = React.useState(false);
const [isOpen, setIsOpen] = React.useState(false);
const scrollRef = React.useRef();
React.useEffect(
() => dragSheetUp(),
// eslint-disable-next-line react-hooks/exhaustive-deps
[]
);
const dragSheetUp = React.useCallback(() => {
setOnAnimate(true);
setIsOpen(true);
Animated.timing(alignment, {
toValue: 0,
duration: 500,
useNativeDriver: false,
}).start(() => setOnAnimate(false));
scrollRef?.current?.scrollTo({
y: 0,
animated: true,
});
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
const dragSheetDown = React.useCallback(() => {
setOnAnimate(true);
Animated.timing(alignment, {
toValue: height,
duration: 500,
useNativeDriver: false,
}).start(() => {
setOnAnimate(false);
setIsOpen(false);
});
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
React.useImperativeHandle(
gmRef,
() => ({
open: () => dragSheetUp(),
close: () => dragSheetDown(),
}),
[dragSheetDown, dragSheetUp]
);
const actionSheetBottomStyle = {
top: alignment,
marginTop: height * (heightFactor - 1),
};
const gestureHandler = (e) => {
if (onAnimate) return;
if (e.nativeEvent.contentOffset.y < -40 && dragging) {
dragSheetDown();
}
};
const calculatedHeight = height * (heightFactor - 1) - 100;
return (
<Animated.ScrollView
ref={scrollRef}
style={[styles.bottomSheetContainer, actionSheetBottomStyle]}
scrollEventThrottle={12}
showsVerticalScrollIndicator={false}
onScroll={(e) => {
gestureHandler(e);
}}
>
{isOpen && dragging ? (
<View
style={styles.closeBtn}
onStartShouldSetResponder={() => {
dragSheetDown();
}}
>
<Icon name="chevron-down" type="feather" color="black" size={28} />
</View>
) : (
<View
style={[
styles.indicator,
{
marginBottom: indicatorMargin ? indicatorMargin : 10,
},
]}
/>
)}
{children}
<View style={[styles.bottomSpace, { height: calculatedHeight }]} />
</Animated.ScrollView>
);
};
const styles = StyleSheet.create({
bottomSheetContainer: {
backgroundColor: '#fff',
position: 'absolute',
left: 0,
right: 0,
bottom: 0,
height: height / 1.2,
width: width / 1,
borderTopRightRadius: 20,
borderTopLeftRadius: 20,
paddingVertical: 10,
},
indicator: {
width: 30,
borderTopColor: 'black',
borderRadius: 15,
borderTopWidth: 4,
alignSelf: 'center',
},
bottomSpace: {
backgroundColor: '#fff',
},
closeBtn: {
width: 40,
alignSelf: 'center',
},
});
(注意:即使我们在 ScrollView 的顶部,我也想处理 onScroll,它适用于 IOS 但不适用于 android)
解决方案
推荐阅读
- php - PHP 内部操作码缓存
- sql - 如何在 PostgreSQL 中使用数组进行批量更新?
- javascript - 你能在javascript中创建一个check_box_tag吗
- css - 3个粘盒一盒,最后一个不浮出主盒
- azure - 如何使用 Istio Ingress 在 AKS 中公开服务?
- javascript - 更改滚动方向时使 div 旋转 180 度
- python - 在 python 中,是否有一个函数可以在说明时间范围的同时增加日期和时间?
- microsoft-teams - MS Teams 应用程序“转到网站”按钮功能不起作用
- java - 使用API查找两个日期之间的差异的方法
- java - 如何使 uiscrollable 查找 content-desc 而不是文本