Je travaille sur une application native native et j'ai besoin d'un objet TextInput doté d'une fonctionnalité similaire à celle de la vue texte de l'application "messages" sur iOS. Elle devrait commencer par une ligne, puis se développer gracieusement en plusieurs lignes jusqu'à ce que lignes de texte), puis commencez à faire défiler la dernière ligne si nécessaire.
J'ai jeté un œil à la variable SlackTextViewController
mais a) semble contenir beaucoup de choses que je ne veux pas et b) j'aimerais essayer de garder autant de code dans React (et en dehors de son objectif-C/Swift) possible.
Edit: Je veux juste souligner que je préférerais le code REACT (JAVASCRIPT), comme indiqué ci-dessus, plutôt que Objective-C ou Swift.
J'ai essayé deux façons différentes de le faire aujourd'hui. Ni sont les meilleurs, mais j'ai pensé enregistrer mes efforts au cas où ils seraient utiles. Ils ont tous les deux certainement eu l'effet que vous recherchiez, bien que parfois retardé par toute la communication asynchrone.
Donc, juste sous l’entrée TextInput, j’ai ajouté un champ de texte standard avec la même police et le même remplissage, etc. J'ai enregistré l'auditeur onChange
sur l'entrée et appelé setState({text: event.nativeEvent.text})
. Le texte déposé tire sa valeur de l'État. Les deux avaient onLayout
auditeurs. Fondamentalement, l'objectif était d'obtenir la hauteur de TextInput à partir du texte (non restreint). Puis j'ai caché la manière de texte hors écran
https://Gist.github.com/bleonard/f7d748e89ad2a485ec34
Vraiment, j'avais juste besoin de la hauteur du contenu dans real UITextView. J'ai donc ajouté une catégorie à RCTUIManager car il existe déjà plusieurs méthodes utiles. Je me suis débarrassé de la vue masquée du texte. Alors onChange
, je demande la hauteur et l’utilise de la même manière via l’État.
https://Gist.github.com/bleonard/6770fbfe0394a34c864b
Ce que j’espère vraiment, c’est que cette communication soit acceptée. Il semble faire quelque chose comme ça automatiquement.
Ajouter multiline={true}
à un TextInput permettra le défilement si la quantité de texte dépasse l’espace disponible. Vous pouvez ensuite changer la hauteur de TextInput en accédant à nativeEvent.contentSize.height de l'événement à partir de la propriété onChange.
class Comment extends Component {
state = {
text: '',
height: 25
}
onTextChange(event) {
const { contentSize, text } = event.nativeEvent;
this.setState({
text: text,
height: contentSize.height > 100 ? 100 : contentSize.height
});
}
render() {
return (
<TextInput
multiline
style={{ height: this.state.height }}
onChange={this.onTextChange.bind(this)}
value={this.state.text}
/>
);
}
}
A partir du 17 octobre, un composant Nice de Wix a été créé:
https://github.com/wix/react-native-autogrow-textinput
L'utilisation peut être très simple:
<AutoGrowingTextInput
style={styles.textInput}
placeholder="Enter text"
value={this.state.text}
onChangeText={this._handleChangeText}
/>
Et il y a quelques accessoires supplémentaires comme minHeight
et maxHeight
par exemple.
Je l'utilise sur RN 0.47.2
Implémentez la méthode déléguée UITextView
textViewDidChange
et jouez avec le rect
- (void)textViewDidChange:(UITextView *)textView {
CGSize constraintSize = CGSizeMake(textView.frame.size.width, MAXFLOAT);
CGRect textRect = [textView.text boundingRectWithSize:constraintSize
options:NSStringDrawingUsesLineFragmentOrigin
attributes:@{NSFontAttributeName:textView.font}
context:nil];
NSLog(@"Frame:%@", NSStringFromCGRect(textRect));
CGRect newRect = textView.frame;
newRect.size.height = textRect.size.height;
textView.frame = newRect;
}
Une autre solution consiste à vérifier les symboles '\n'
et à définir la propriété numberOfLines
. Fonctionne pour moi.
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import {TextInput} from 'react-native';
export default class TextInputAutogrow extends Component {
constructor(props) {
super(props);
this._ref = null;
this.bindRef = this.bindRef.bind(this);
this.onChangeText = this.onChangeText.bind(this);
this.state = {
numberOfLines: this.getNumberOfLines()
};
}
bindRef(c) {
this._ref = c;
this.props.innerRef && this.props.innerRef(c);
}
getText() {
return typeof this.props.value === 'string' ?
this.props.value :
(
typeof this.props.defaultValue === 'string' ?
this.props.defaultValue :
''
);
}
getNumberOfLines(value) {
if (value === undefined) {
value = this.getText();
}
return Math.max(this.props.numberOfLines, value.split('\n').length - 1) + 1;
}
onChangeText(value) {
this.setState({numberOfLines: this.getNumberOfLines(value)})
}
render() {
return (
<TextInput
{...this.props}
ref={this.bindRef}
numberOfLines={this.state.numberOfLines}
onChangeText={this.onChangeText}
/>
)
}
}
TextInputAutogrow.propTypes = {
...TextInput.propTypes,
innerRef: PropTypes.func,
};
TextInputAutogrow.defaultProps = {
numberOfLines: 4,
};