Celem jest opracowanie niestandardowej listy powiększania przy użyciu react-native-gesture-handler i react-native-reanimated (lub Animated z React Native) bez polegania na dodatkowych zewnętrznych pakietach. Funkcjonalność powiększania powinna być zaimplementowana przy użyciu gestu szczypania z react-native-gesture-handler lub podobnego niestandardowego podejścia.
Wymagania:
- Lista musi być zawarta w ScrollView i nie powinna wychodzić poza jej granice podczas lub po powiększaniu. Oczekiwane zachowanie powinno ściśle odpowiadać funkcjonalności powiększania w kalendarzu Apple i Google na urządzeniach mobilnych.
- Implementacja musi zapewnić płynne działanie zarówno na iOS, jak i Androidzie.
- Po powiększeniu zawartość powinna pozostać w poprawnej pozycji i być gotowa do dalszego powiększania z ostatniego stanu.
- Wysokość poszczególnych elementów listy musi pozostać niezmieniona—tylko wysokość kontenera nadrzędnego powinna się skalować.
- Metody przewijania nie powinny być używane podczas powiększania, aby uniknąć nieoczekiwanego zachowania i niepotrzebnej złożoności.
Poniżej przykład uruchomienia:
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(() => {
//... jakieś zmiany
})
.onUpdate((e) => {
//... jakieś zmiany
})
.onFinalize(() => {
//... jakieś zmiany
})
.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",
},
});