Voici un GIF (de qualité réduite) sur ce que je veux réaliser.
J'ai un scrollview
, qui est positionné à la moitié de mon écran.
Ce que je veux, c'est faire glisser ce scrollview
vers le haut, puis, quand il atteint une certaine position, envoyer le drag touch event
à scrollview
lui-même, afin qu'il puisse continuer le défilement.
contentContainerStyle
. Cela a bien fonctionné, mais je n'ai pas pu cliquer sur la vue derrière. Existe-t-il un moyen de cliquer dans la zone vide d'une vue de défilement?J'ai également essayé de détecter la position du défilement, afin de déplacer la vue vers le haut en conséquence
<ScrollView onScroll={event => moveScrollViewUpIfNeeded(event)}>
...
</ScrollView>
mais n'a pas fonctionné lorsque je l'ai testé sur le simulateur iOS. L'événement n'est même pas déclenché. React Native Docs indique que onScroll
a besoin de scrollEventThrottle
pour fonctionner. Cependant, scrollEventThrottle
n'est que disponible sur iOS . Et dans mon cas, je le veux sur Android aussi.
.
Alors, pouvez-vous me donner quelques conseils pour y parvenir s'il vous plaît :)?
Merci,
J'ai essayé plusieurs options. C'est ma solution qui fonctionne le mieux en termes de performances. Bien sûr, ce n'est qu'un exemple de travail, vous devrez peut-être l'optimiser un peu plus pour répondre parfaitement à vos besoins.
L'idée de base est de garder la carte tout le temps en arrière-plan de la superposition. La superposition est absolument positionnée et contient deux vues. Une vue est transparente, où nous pouvons toujours voir et contrôler la carte, l'autre vue contient le ScrollView réel. L'astuce consiste à définir pointerEvents="box-none"
de la superposition parent et désactivez pointerEvents avec pointerEvents="none"
de Afficher où nous voulons interagir avec la carte.
Méthode de rendu de base:
<SafeAreaView style={{flex: 1}}>
<MapView
initialRegion={region}
style={{height: HEIGHT, width: WIDTH}}
/>
<View pointerEvents="box-none"style={{height: HEIGHT, width: WIDTH, position: 'absolute'}}>
<View pointerEvents="none" style={{height: this.state.height, backgroundColor: 'transparent'}} />
<View style={{ height: HEIGHT-this.state.height, backgroundColor: 'white'}}>
<ScrollView onScroll={(e) => this._onScroll(e)} scrollEventThrottle={10} >
-- content of scrollview goes here ---
</ScrollView>
</View>
</View>
</SafeAreaView>
Fonction de défilement:
Si nous faisons défiler le ScrollView, nous voulons réduire la vue vide, afin que le ScrollView devienne plein écran. Par conséquent, nous écoutons la méthode onScroll
du ScrollView. Voir code et commentaires ci-dessous:
_onScroll(e){
// from the nativeEvent we can get the contentOffsett
var offset_y = e.nativeEvent.contentOffset.y;
if (offset_y > 0 ) {
if (this.state.height>=0){
// we are scrolling down the list, decrease height of the empty view
this.setState({height: this.state.height-offset_y});
}
}
if (offset_y <0){
if (this.state.height <= this.state.mapHeight){
// we are scrolling up the list, increase size of empty view/map view
this.setState({height: this.state.height-offset_y});
}
}
}
Avec scrollEventThrottle
prop de ScrollView, nous pouvons contrôler la fréquence à laquelle _onScroll
la méthode doit être appelée. (Ici, vous devrez probablement affiner)
Utilisez react-native-reeanimated-bottom-sheet pour y parvenir: https://github.com/osdnk/react-native-reanimated-bottom-sheet
Je pense qu'il vaut mieux placer à la fois MapView et BottomView dans un ScrollView
.
Il enregistrera le comportement de défilement naturel et empêchera les effets secondaires comme les rayures blanches lors du défilement vers le bas ou la vue de dessus disparaissant lors du défilement vers le haut. Le problème principal ici est de savoir comment faire un effet "gel" pour le MapView
.
Il est agréable d'utiliser l'effet de parallaxe en transformant MapView
à l'intérieur de Animated
conteneur relativement à un événement scroll. Je pense que bibliothèque animée avec composants animables sera une bonne solution pour des problèmes comme celui-ci:
scroll = new Animated.Value(0)
render() {
return <Animated.ScrollView ...
onScroll={Animated.event([{nativeEvent: {contentOffset: {y: this.scroll}}}], {useNativeDriver: true})}>
<Animated.View
style={
{ ...transform:
[{translateY: Animated.multiply(this.scroll, 0.8)}]}}>
<MapView />
</Animated.View>
<BottomView />
</Animated.ScrollView>
}
En fait, si vous ne voulez pas d'effet de parallaxe, vous pouvez remplacer Animated.multiply(this.scroll, 0.8)
avec juste this.scroll
Vous pouvez voir un exemple complet ici: exemple de code