Veuillez consulter mon Expo Snack .
Les éléments de liste déroulante sont accessibles sous iOS mais pas sous Android. La hauteur fixe du conteneur (boîte grise) cause ce problème, mais je dois garder la hauteur fixe pour ma barre d'outils.
J'ai essayé d'utiliser le package react-native-view-overflow
mais pas de chance. Il nécessite un lien react-native
, en attendant, je ne peux pas éjecter mon projet car j'utilise des packages Expo qui seront cassés si j'éjecte.
Avez-vous des suggestions pour rendre les éléments du menu déroulant accessibles sous Android?
3 Réponses :
J'ai changé votre code, vérifiez ceci: Lien Snack
Cela résout votre problème, mais vous pouvez mettre à jour votre version native de réaction pour inclure ce commit qui ajoute la prise en charge de la propriété de style overflow
sur React Native pour Android.
Vous créez un conteneur externe dont la hauteur est dynamique. J'ai besoin d'une hauteur fixe pour créer une barre d'outils. Une barre d'outils ne doit pousser aucun contenu en dessous.
Je n'utiliserais pas de dépendance à la place, je la gérerais moi-même.
DropDown
qui couvre tout l'écran avec une position absolue (afin qu'il n'affecte pas la position des autres éléments sur l'écran). Ce composant est invisible lorsqu'il est inactif. DropDown
. DropDown
est de nouveau rendu et un petit menu s'affiche à proximité du bouton d'origine qui a été enfoncé. Voici le code, mais je l'ai également mis dans une collation pour que vous puissiez jouer avec https://snack.expo.io/@andypandy/dropdownmenu
Il y a beaucoup de possibilités que vous pouvez faire avec cela. Vous pouvez passer des enfants comme accessoires, vous pouvez le connecter à redux et le définir à la racine de votre application afin qu'il puisse être utilisé n'importe où. Les styles peuvent être facilement modifiés. Il est vraiment assez flexible dans ce que vous pouvez en faire. Je l'ai utilisé dans de nombreuses applications qui sont actuellement en ligne dans les deux magasins d'applications.
import React from 'react'; import { Text, View, StyleSheet, TouchableOpacity } from 'react-native'; export default class App extends React.Component { render() { return ( <TouchableOpacity onPress={this.props.onPress}> <View style={styles.button}> <Text style={{color: 'white'}}>{this.props.title}</Text> </View> </TouchableOpacity> ) } } const styles = StyleSheet.create({ button: { backgroundColor: '#336699', padding: 10, borderRadius: 5 } });
import React from 'react'; import { Text, View, StyleSheet, TouchableWithoutFeedback, TouchableOpacity} from 'react-native'; export default class DropDown extends React.Component { render() { if (this.props.show) { const { y: top, x: left } = this.props.position; const width = 100; return ( <TouchableWithoutFeedback onPress={() => this.props.hide('background pressed')}> <View style={styles.container}> <View style={[styles.menu, { top, left: left - width/2, width}]}> <TouchableOpacity style={{width, alignItems: 'center', paddingTop: 5}} onPress={() => this.props.hide('Item 1')}> <Text>Item 1</Text> </TouchableOpacity> <TouchableOpacity style={{width, alignItems: 'center', paddingTop: 5}} onPress={() => this.props.hide('Item 2')}> <Text>Item 2</Text> </TouchableOpacity> <TouchableOpacity style={{width, alignItems: 'center', paddingTop: 5}} onPress={() => this.props.hide('Item 3')}> <Text>Item 3</Text> </TouchableOpacity> <TouchableOpacity style={{width, alignItems: 'center', paddingVertical: 5}} onPress={() => this.props.hide('Item 4')}> <Text>Item 4</Text> </TouchableOpacity> </View> </View> </TouchableWithoutFeedback> ); } else { return null } } } const styles = StyleSheet.create({ container: { position: 'absolute', top: 0, left: 0, right: 0, bottom: 0 }, menu: { position: 'absolute', backgroundColor: 'white', alignItems: 'center', shadowColor: "#000", shadowOffset: { width: 0, height: 5, }, shadowOpacity: 0.36, shadowRadius: 6.68, elevation: 11, } });
import React from 'react'; import { Text, View, StyleSheet, UIManager, findNodeHandle, TouchableOpacity } from 'react-native'; // import components import DropDown from './DropDown'; import MyButton from './MyButton'; export default class App extends React.Component { state = { show: false, position: {} } // handle showing the dropdown showDropDown = () => { if (this.button) { // use the uimanager to measure the button's position in the window UIManager.measure(findNodeHandle(this.button), (x, y, width, height, pageX, pageY) => { const position = { left: pageX, top: pageY, width: width, height: height }; // setState, which updates the props that are passed to the DropDown component this.setState({show: true, position: { x: pageX + (width / 2), y: pageY + (2 * height / 3) }}) }); } } // hide the dropdown hideDropDown = (item) => { alert(item) this.setState({show: false, position: {}}) } render() { return ( <View style={styles.container}> <View style={{height: 100, width: 300, backgroundColor: 'yellow', alignItems: 'center', justifyContent: 'center'}}> <MyButton ref={ref => {this.button = ref}} onPress={this.showDropDown} title={'Menu'} /> </View> {/* Anything to be rendered below the DropDown should appear before the DropDown. So for best performance all components should go here. */} <DropDown show={this.state.show} position={this.state.position} hide={this.hideDropDown}/> {/* If you place a component here, it will appear above the DropDown and may interfere with how the DropDown works. You should not put anything here. */} </View> ) } } const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', alignItems: 'center', backgroundColor: 'white' } });
Il semble que lorsque j'appuie sur la liste déroulante, le composant parent se déplace / pousse vers le bas. Pousse-t-il un contenu sous le conteneur parent déroulant?
Il ne doit pousser aucun contenu car le composant DropDown est absolument positionné au-dessus de tous les composants. Le composant DropDown doit être le dernier composant ajouté à la vue afin que tous les composants soient en dessous.
Considérez le composant DropDown comme une superposition sur votre écran. Cela signifie également que, comme il s'agit d'une superposition, tout ce qui y est rendu n'affectera pas la position de quoi que ce soit en dessous. J'utilise généralement DropDown avec redux et je mets le menu DropDown à la racine de mon application pour que tout soit terminé. Cela dépend vraiment de la façon dont vous l'utilisez. Placez le composant DropDown au mauvais endroit et il ne fonctionnera pas comme prévu. Il doit s'agir de la dernière vue rendue. Si vous regardez mon App.js
, vous verrez que c'est la dernière vue rendue.
Donc, si mon contenu ci-dessous est rendu à la demande, la barre d'outils doit également être rendue pour être le dernier rendu?
La valeur de retour par défaut de DropDown est null
donc il ne rendra pas quelque chose à moins que vous ne le lui disiez. Il vous suffit de l'avoir comme dernier élément de la vue. Comme je l'ai fait dans App.js
. Si vous voulez voir plus clairement comment cela fonctionne, ajoutez un backgroundColor au conteneur dans le DropDown.js
cela couvrira tout l'écran lorsque le DropDown sera affiché. Ensuite, dans App.js
, ajoutez quelque chose après le composant DropDown. Vous devriez voir qu'il apparaîtra au-dessus du composant DropDown. L'ordre dans lequel vous spécifiez les composants dans App.js
est important. J'ai ajouté quelques commentaires à mon App.js
@JeafGilbert Comment ça va?
Désolé, Andrew ne l'a pas encore appliqué, je vais l'essayer ce soir.
@JeafGilbert comment ça s'est passé?
Il semble que lorsque la liste déroulante se développe, elle s'écoule hors de la vue car vous avez donné une hauteur fixe.
Donc, pour contourner le problème, vous pouvez utiliser la propriété minHeight
au lieu de height .
cela garantira qu'au moins vous obtenez votre taille minimale et si nécessaire, il peut utiliser plus de hauteur, comme lorsque vous développez la liste déroulante.
la correction est donnée ci-dessous,
dropdownContainer: { width:340, minHeight:115,// changed this from height:115 ... ... },
Je dois avoir une hauteur fixe, une barre d’outils ne doit pas pousser de contenu en dessous.