Rich ReactNative TextInput

Любой способ создать "богатый" TextInput in React Native? Возможно, это не полный размытый wysiwyg, но, возможно, просто измените цвет текста различных фрагментов текста; как функция @mention в Twitter или Facebook.

Ответ 1

Решение состоит в том, что вы можете использовать элементы <Text> как дочерние элементы в <TextInput> следующим образом:

<TextInput>
    whoa no way <Text style={{color:'red'}}>rawr</Text>
</TextInput>

Ответ 2

Для достижения этого поведения вам придется использовать регулярное выражение. Кто-то уже создал пакет для просмотра react-native-parsed-text

Эта библиотека позволяет анализировать текст и извлекать детали с использованием RegExp или предопределенных шаблонов. В настоящее время существует 3 предопределенных типа: URL, телефон и электронная почта.

Пример из их github

<ParsedText
          style={styles.text}
          parse={
            [
              {type: 'url',                       style: styles.url, onPress: this.handleUrlPress},
              {type: 'phone',                     style: styles.phone, onPress: this.handlePhonePress},
              {type: 'email',                     style: styles.email, onPress: this.handleEmailPress},
              {pattern: /Bob|David/,              style: styles.name, onPress: this.handleNamePress},
              {pattern: /\[(@[^:]+):([^\]]+)\]/i, style: styles.username, onPress: this.handleNamePress, renderText: this.renderText},
              {pattern: /42/,                     style: styles.magicNumber},
              {pattern: /#(\w+)/,                 style: styles.hashTag},
            ]
          }
        >
          Hello this is an example of the ParsedText, links like http://www.google.com or http://www.facebook.com are clickable and phone number 444-555-6666 can call too.
          But you can also do more with this package, for example Bob will change style and David too. [email protected]
          And the magic number is 42!
          #react #react-native
</ParsedText>

Ответ 3

Взгляните на TokenizedTextExample из интерактивных документов. Я думаю, это приблизит вас к тому, что вы хотите сделать. Соответствующий код следует:

class TokenizedTextExample extends React.Component {
  state: any;

  constructor(props) {
    super(props);
    this.state = {text: 'Hello #World'};
  }
  render() {

    //define delimiter
    let delimiter = /\s+/;

    //split string
    let _text = this.state.text;
    let token, index, parts = [];
    while (_text) {
      delimiter.lastIndex = 0;
      token = delimiter.exec(_text);
      if (token === null) {
        break;
      }
      index = token.index;
      if (token[0].length === 0) {
        index = 1;
      }
      parts.push(_text.substr(0, index));
      parts.push(token[0]);
      index = index + token[0].length;
      _text = _text.slice(index);
    }
    parts.push(_text);

    //highlight hashtags
    parts = parts.map((text) => {
      if (/^#/.test(text)) {
        return <Text key={text} style={styles.hashtag}>{text}</Text>;
      } else {
        return text;
      }
    });

    return (
      <View>
        <TextInput
          multiline={true}
          style={styles.multiline}
          onChangeText={(text) => {
            this.setState({text});
          }}>
          <Text>{parts}</Text>
        </TextInput>
      </View>
    );
  }
}

Ответ 4

Этот вопрос был задан некоторое время назад, но я думаю, что мой ответ может помочь другим людям, ищущим, как закрасить часть @mention строки. Я не уверен, является ли способ, которым я это сделал, "чистый" или "реагирующий", но вот как я это сделал: я беру введенную строку и разделяю ее с пустым пространством в качестве разделителя. Затем я перебираю массив и, если текущий элемент совпадает с шаблоном @subject/@user, он заменяется тегом Text с примененными стилями; остальное вернуть товар. В конце я отображаю массив inputText (содержащий строки и элементы jsx) внутри элемента TextInput. Надеюсь это поможет!

render() {
let inputText = this.state.content;
if (inputText){
  inputText = inputText.split(/(\s)/g).map((item, i) => {
    if (/@[a-zA-Z0-9]+/g.test(item)){
      return <Text key={i} style={{color: 'green'}}>{item}</Text>;
    } 
    return item;
  })
return <TextInput>{inputText}</TextInput>

Result