Подводя итог тому, что я пытаюсь достичь sh Я набросал эту диаграмму:
I am trying to build a custom navigation. In this navigation, I have a main page. Above this main page there sits another page, not visible to the user yet (as the main page fills the whole screen). The main page has scrollable content on it.
There is one component at the top of the main page, that the user can drag to swipe the other/upper page down.
What I have tried so far to accomplish this
I already have an implementation, that works but has some drawbacks.
- The most outer
ScrollView
has scrollEnabled=false
- The draggable component is an
Animated.View
to which I applied a PanResponder
to
- Once the user clicks and drags the draggable component down, the PanResponder captures this movement
- I use the captured movement and do
outerScrollView.scrollTo(...)
--> on iOS this works fine but on android I see some small jittering during the scroll movement.
The code:
interface Props extends ScrollViewProps {
draggableHeader: ReactNode;
}
const { width, height } = Dimensions.get("window");
export const SwipingNavigator: React.FC<Props> = (props) => {
const scrollView = useRef<ScrollView>();
const scrollToMainPage = (animated = true): void =>
scrollView.current.scrollTo({ x: 0, y: height, animated });
const scrollToUpperPage = (): void =>
scrollView.current.scrollTo({
y: 0,
x: 0,
animated: true,
});
//when component mounts, scroll to main page
useEffect(() => {
scrollToMainPage(false);
}, []);
const panResponder = useRef(
PanResponder.create({
onMoveShouldSetPanResponder: (e, gestureState) => gestureState.dy > 3,
//move the content as the user drags the header
onPanResponderMove: ({ nativeEvent }) => {
scrollView.current.scrollTo({
y: height - nativeEvent.pageY + 40,
x: 0,
animated: false,
});
},
onPanResponderEnd: ({ nativeEvent }) => {
//detect to which page the user wants to scroll -> snap effect
if (nativeEvent.pageY < height / 3) {
scrollToMainPage();
} else {
scrollToUpperPage();
}
},
})
).current;
//assuming child 1 is the main page, child 0 the upper page
return (
<ScrollView
ref={scrollView}
scrollEnabled={false}
bounces={false}
pagingEnabled={true}
disableScrollViewPanResponder={true}
showsVerticalScrollIndicator={false}
{...props}
style={globalStyles.flex1}>
{props.children[0]}
<View style={styles.fs}>
<Animated.View {...panResponder.panHandlers}>
{props.draggableHeader}
</Animated.View>
{props.children[1]}
</View>
</ScrollView>
);
};
const styles = StyleSheet.create({
fs: {
flex: 1,
width,
height,
},
});
Как уже было сказано: основная проблема в том, что это выглядит не так хорошо на android с точки зрения производительности + это, вероятно, не лучшее решение.
Прокрутка вниз с другой страницы не является проблемой, поскольку на ней будет кнопка «закрыть».
Другие идеи, которые у меня были
Я подумал об использовании Pan / Gesture-Handler перетаскиваемого компонента и «внедрить» его в ScrollView. Так что вид прокрутки будет обнаруживать только движения этого попрошайника.
Я сейчас просто застрял, и я ценю каждый новый ввод, который вы можете мне дать. Заранее благодарим за вашу помощь :)
// Редактировать: вот закуска: https://snack.expo.io/@hannojg / удивленный-бекон К сожалению, на выставке android он выглядит гладко как масло. Однако при рендеринге главной страницы на реальном устройстве с помощью RN прокрутка на android.
выглядит иначе.