Цель состоит в том, чтобы разработать пользовательский список с возможностью масштабирования, используя react-native-gesture-handler и react-native-reanimated (или Animated из React Native), не полагаясь на дополнительные внешние пакеты. Функциональность масштабирования должна быть реализована с использованием жеста сжатия из react-native-gesture-handler или аналогичного пользовательского подхода.
Требования:
- Список должен находиться внутри ScrollView и не должен выходить за его пределы во время или после масштабирования. Ожидаемое поведение должно максимально соответствовать функциональности масштабирования в Apple и Google Calendar на мобильных устройствах.
- Реализация должна обеспечивать плавную работу как на iOS, так и на Android.
- После масштабирования содержимое должно оставаться в правильном положении и быть готовым к дальнейшему масштабированию из последнего состояния.
- Высота отдельных элементов списка должна оставаться неизменной — только высота родительского контейнера должна изменяться.
- Методы прокрутки не должны использоваться во время масштабирования, чтобы избежать неожиданного поведения и ненужной сложности.
Ниже приведен пример запуска:
import React from "react";
import { View, ScrollView, Text, StyleSheet, Dimensions } from "react-native";
import {
GestureHandlerRootView,
GestureDetector,
Gesture,
} from "react-native-gesture-handler";
const elementHeight = 50;
const list = Array.from({length: 50});
export default function PinchToZoomList() {
const pinchRef = useRef(Gesture.Pinch())
const pinchGesture = Gesture.Pinch()
.onBegin(() => {
//... некоторые изменения
})
.onUpdate((e) => {
//... некоторые изменения
})
.onFinalize(() => {
//... некоторые изменения
})
.runOnJS(true)
.withRef(pinchRef);
return (
<GestureHandlerRootView>
<GestureDetector gesture={pinchGesture}>
<ScrollView simultaneousHandlers={pinchRef}>
{list.map((_, index) => (
<View key={index} style={styles.item}>
<Text>{index}</Text>
</View>
))}
</ScrollView>
</GestureDetector>
</GestureHandlerRootView>
);
}
const styles = StyleSheet.create({
item: {
height: elementHeight,
justifyContent: "center",
alignItems: "center",
borderBottomWidth: 1,
borderColor: "#ccc",
},
});