Vraag een multiline maken, TextInput uitbreiden met React-Native


Ik werk aan een react native-app en heb een TextInput nodig die qua functionaliteit vergelijkbaar is met de tekstweergave in de app "messages" op iOS. Het moet als één regel beginnen en daarna sierlijk uitbreiden naar meer regels tot een bepaalde limiet (zoals 5 tekstregels) en ga dan naar waar nodig naar de laatste regel scrollen.

Heb een kijkje genomen naar de SlackTextViewController maar a) het lijkt erop dat het een heleboel dingen heeft die ik niet wil en b) Ik zou graag proberen om zoveel mogelijk code in React (en uit doelstelling-C / swift) als mogelijk te houden.

Bewerken: Ik wil alleen benadrukken dat ik REACT (JAVASCRIPT) -code prefereer, zoals hierboven vermeld, in plaats van Objective-C of Swift.


24
2017-07-17 11:50


oorsprong


antwoorden:


Ik heb dit vandaag op twee verschillende manieren geprobeerd. Noch zijn de beste, maar ik dacht dat ik mijn inspanningen zou vastleggen voor het geval ze nuttig zouden zijn. Ze hadden allebei zeker het effect waarnaar je op zoek was, hoewel soms uitgesteld met alle async communicatie.

1) Offscreen Teksthoogte

Dus net onder de TextInput heb ik een gewoon tekstveld toegevoegd met hetzelfde lettertype en opvulling en dergelijke. Ik heb het geregistreerd onChange luisteraar op de invoer en gebeld setState({text: event.nativeEvent.text}). De ingediende tekst kreeg zijn waarde van de staat. Beide hadden onLayout Luisteraars. Kortom, het doel was om de hoogte voor de TextInput te krijgen uit de (onbeperkte) tekst. Daarna heb ik de tekst weggegooid

https://gist.github.com/bleonard/f7d748e89ad2a485ec34

2) Oorspronkelijke module

Echt, ik had alleen de hoogte van de inhoud nodig in de echt UITextView. Dus ik heb een categorie toegevoegd aan RCTUIManager omdat er al verschillende methoden zijn die nuttig zijn. Ik heb de verborgen tekstweergave verwijderd. Zo onChange, Vraag ik naar de hoogte en gebruik dat op dezelfde manier via de staat.

https://gist.github.com/bleonard/6770fbfe0394a34c864b

3) Github PR

Wat ik echt hoop is dat deze PR wordt geaccepteerd. Het ziet ernaar uit om zoiets automatisch te doen.

https://github.com/facebook/react-native/pull/1229


19
2017-08-01 06:43



Het toevoegen multiline={true} naar een TextInput maakt scrollen mogelijk als de hoeveelheid tekst groter is dan de beschikbare ruimte. U kunt vervolgens de hoogte van de TextInput wijzigen door toegang te krijgen tot de nativeEvent.contentSize.hoogte van de gebeurtenis via de onChange-prop.

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}
         />
      );
   }
}

10
2017-11-06 08:27



Implementeer de UITextViewde gedelegeerde methode textViewDidChange en speel met de 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;
}

1
2017-07-28 11:45



Vanaf oktober 17 is er een leuk component van Wix om dit te doen:

https://github.com/wix/react-native-autogrow-textinput

Het gebruik kan heel eenvoudig zijn:

<AutoGrowingTextInput
  style={styles.textInput}
  placeholder="Enter text"
  value={this.state.text}
  onChangeText={this._handleChangeText}
/>

En er zijn enkele extra rekwisieten zoals minHeight en maxHeight bijvoorbeeld.

Ik gebruik het op RN 0.47.2


1
2017-10-01 20:02



Een andere oplossing is om te controleren '\n' symbolen en stel de numberOfLines eigendom. Werkt voor mij.

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,
};

0
2018-06-21 17:18