Masquer / Afficher les composants dans react native
Je suis vraiment nouveau pour réagir natif et je me demande Comment puis-je cacher/afficher un composant.
Voici mon cas de test:
<TextInput
onFocus={this.showCancel()}
onChangeText={(text) => this.doSearch({input: text})} />
<TouchableHighlight
onPress={this.hideCancel()}>
<View>
<Text style={styles.cancelButtonText}>Cancel</Text>
</View>
</TouchableHighlight>
J'ai un TextInput
du composant, ce que je veux, c'est montrer le TouchableHighlight
lorsque l'entrée reçoit le focus, puis se cacher la TouchableHighlight
lorsque l'utilisateur presse le bouton annuler.
Je ne sais pas comment "accéder" au composant TouchableHighlight
afin de le cacher/l'afficher dans mes fonctions showCancel/hideCancel
.
Aussi, comment puis-je cacher le bouton dès le début?
13 réponses
Je ferais quelque chose comme ceci:
var myComponent = React.createComponent({
getInitialState: function () {
return {
showCancel: false,
};
},
toggleCancel: function () {
this.setState({
showCancel: !this.state.showCancel
});
}
_renderCancel: function () {
if (this.state.showCancel) {
return (
<TouchableHighlight
onPress={this.toggleCancel()}>
<View>
<Text style={styles.cancelButtonText}>Cancel</Text>
</View>
</TouchableHighlight>
);
} else {
return null;
}
},
render: function () {
return (
<TextInput
onFocus={this.toggleCancel()}
onChangeText={(text) => this.doSearch({input: text})} />
{this._renderCancel()}
);
}
});
Dans votre fonction de rendu:
{ this.state.showTheThing &&
<TextInput/>
}
Alors faites simplement:
this.setState({showTheThing: true}) // to show it
this.setState({showTheThing: false}) // to hide it
Dans react ou react native, le composant way hide / show ou add / remove ne fonctionne pas comme dans android ou iOS. La plupart d'entre nous pensent qu'il y aurait la stratégie similaire comme
View.hide = true or parentView.addSubView(childView)
Mais la façon dont react native work est complètement différente. La seule façon d'obtenir ce type de fonctionnalité est d'inclure votre composant dans votre DOM ou retirer de DOM.
Ici, dans cet exemple, je vais définir la visibilité de la vue texte en fonction du clic du bouton.
L'idée derrière cette tâche est la création d'une variable d'état appelée state ayant la valeur initiale définie sur false lorsque l'événement de clic de bouton se produit, alors sa valeur bascule. Nous allons maintenant utiliser cette variable d'état lors de la création du composant.
import renderIf from './renderIf'
class FetchSample extends Component {
constructor(){
super();
this.state ={
status:false
}
}
toggleStatus(){
this.setState({
status:!this.state.status
});
console.log('toggle button handler: '+ this.state.status);
}
render() {
return (
<View style={styles.container}>
{renderIf(this.state.status)(
<Text style={styles.welcome}>
I am dynamic text View
</Text>
)}
<TouchableHighlight onPress={()=>this.toggleStatus()}>
<Text>
touchme
</Text>
</TouchableHighlight>
</View>
);
}
}
La seule chose à remarquer dans cet extrait de code est renderIf
, qui est en fait une fonction qui renvoie le composant est passé basé sur la valeur booléenne est passé.
renderIf(predicate)(element)
Renderif.js
'use strict';
const isFunction = input => typeof input === 'function';
export default predicate => elemOrThunk =>
predicate ? (isFunction(elemOrThunk) ? elemOrThunk() : elemOrThunk) : null;
Dans render (), vous pouvez afficher conditionnellement le JSX ou renvoyer null comme dans:
render(){
return({yourCondition ? <yourComponent /> : null});
}
J'avais besoin de basculer entre deux images. Avec la commutation conditionnelle entre eux, il y avait un délai de 5 secondes sans image affichée.
J'utilise l'approche de la réponse Amos downvoted. Poster comme nouvelle réponse car il est difficile de mettre du code dans un commentaire avec un formatage correct.
Fonction de rendu:
<View style={styles.logoWrapper}>
<Image
style={[styles.logo, loading ? styles.hidden : {}]}
source={require('./logo.png')} />
<Image
style={[styles.logo, loading ? {} : styles.hidden]}
source={require('./logo_spin.gif')} />
</View>
Styles:
var styles = StyleSheet.create({
logo: {
width: 200,
height: 200,
},
hidden: {
width: 0,
height: 0,
},
});
La plupart du temps, je fais quelque chose comme ceci:
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.state = {isHidden: false};
this.onPress = this.onPress.bind(this);
}
onPress() {
this.setState({isHidden: !this.state.isHidden})
}
render() {
return (
<View style={styles.myStyle}>
{this.state.isHidden ? <ToHideAndShowComponent/> : null}
<Button title={this.state.isHidden ? "SHOW" : "HIDE"} onPress={this.onPress} />
</View>
);
}
}
Si vous êtes un peu nouveau dans la programmation, cette ligne doit vous être étrange:
{this.state.isHidden ? <ToHideAndShowComponent/> : null}
Cette ligne est équivalente à
if (this.state.isHidden)
{
return ( <ToHideAndShowComponent/> );
}
else
{
return null;
}
Mais vous ne pouvez pas écrire une condition if/else dans le contenu JSX (par exemple la partie return () d'une fonction de rendu), vous devrez donc utiliser cette notation.
Cette petite astuce peut être très utile dans de nombreux cas, et je vous suggère de l'utiliser dans vos développements, car vous pouvez consulter rapidement un condition.
Cordialement,
Une option supplémentaire consiste à appliquer positionnement absolu via styling , en définissant le composant masqué en coordonnées hors écran:
<TextInput
onFocus={this.showCancel()}
onChangeText={(text) => this.doSearch({input: text})}
style={this.state.hide ? {position: 'absolute', top: -200} : {}}
/>
Contrairement à certaines des suggestions précédentes, cela masquerait votre composant de la vue mais le rendrait également (le garderait dans le DOM), le rendant ainsi vraiment invisible .
J'ai eu le même problème où je voudrais afficher / masquer les vues, mais je ne voulais vraiment pas que l'interface utilisateur Saute quand des choses ont été ajoutées/supprimées ou nécessairement pour faire face au re-rendu.
J'ai écrit un composant simple pour y faire face pour moi. Animé par défaut, mais facile à basculer. Je l'ai mis sur GitHub et MNP avec un readme, mais tout le code est ci-dessous.
npm install --save react-native-hideable-view
import React, { Component, PropTypes } from 'react';
import { Animated } from 'react-native';
class HideableView extends Component {
constructor(props) {
super(props);
this.state = {
opacity: new Animated.Value(this.props.visible ? 1 : 0)
}
}
animate(show) {
const duration = this.props.duration ? parseInt(this.props.duration) : 500;
Animated.timing(
this.state.opacity, {
toValue: show ? 1 : 0,
duration: !this.props.noAnimation ? duration : 0
}
).start();
}
shouldComponentUpdate(nextProps) {
return this.props.visible !== nextProps.visible;
}
componentWillUpdate(nextProps, nextState) {
if (this.props.visible !== nextProps.visible) {
this.animate(nextProps.visible);
}
}
render() {
if (this.props.removeWhenHidden) {
return (this.visible && this.props.children);
}
return (
<Animated.View style={{opacity: this.state.opacity}}>
{this.props.children}
</Animated.View>
)
}
}
HideableView.propTypes = {
visible: PropTypes.bool.isRequired,
duration: PropTypes.number,
removeWhenHidden: PropTypes.bool,
noAnimation: PropTypes.bool
}
export default HideableView;
Masquer Et Afficher parent vue de Activity Indicator
constructor(props) {
super(props)
this.state = {
isHidden: false
}
}
Masquer et Afficher comme suit
{
this.state.isHidden ? <View style={style.activityContainer} hide={false}><ActivityIndicator size="small" color="#00ff00" animating={true}/></View> : null
}
Référence Complète
render() {
return (
<View style={style.mainViewStyle}>
<View style={style.signinStyle}>
<TextField placeholder='First Name' keyboardType='default' onChangeFirstName={(text) => this.setState({firstName: text.text})}/>
<TextField placeholder='Last Name' keyboardType='default' onChangeFirstName={(text) => this.setState({lastName: text.text})}/>
<TextField placeholder='Email' keyboardType='email-address' onChangeFirstName={(text) => this.setState({email: text.text})}/>
<TextField placeholder='Phone Number' keyboardType='phone-pad' onChangeFirstName={(text) => this.setState({phone: text.text})}/>
<TextField placeholder='Password' secureTextEntry={true} keyboardType='default' onChangeFirstName={(text) => this.setState({password: text.text})}/>
<Button style={AppStyleSheet.buttonStyle} title='Sign up' onPress={() => this.onSignupPress()} color='red' backgroundColor='black'/>
</View>
{
this.state.isHidden ? <View style={style.activityContainer}><ActivityIndicator size="small" color="#00ff00" animating={true}/></View> : null
}
</View>
);
}
Sur le bouton appuie sur Définir l'état comme suit
onSignupPress() {
this.setState({isHidden: true})
}
Quand vous devez cacher
this.setState({isHidden: false})
Vous pouvez utiliser mon module réagir-native-affichage pour afficher/masquer des composants.
Très Facile. Il suffit de changer d' () => cette.showCancel () comme ci-dessous:
<TextInput
onFocus={() => this.showCancel() }
onChangeText={(text) => this.doSearch({input: text})} />
<TouchableHighlight
onPress={this.hideCancel()}>
<View>
<Text style={styles.cancelButtonText}>Cancel</Text>
</View>
</TouchableHighlight>
Si vous avez besoin que le composant reste chargé mais caché, vous pouvez définir l'opacité à 0. (J'en avais besoin pour la caméra expo par exemple)
//in constructor
this.state = {opacity: 100}
/in component
style = {{opacity: this.state.opacity}}
//when you want to hide
this.setState({opacity: 0})