RN:实现一个自适应高度的TextInput组件

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/DeMonliuhui/article/details/89846841

问题

在阅读《React Native跨平台移动应用开发第二版》(阙喜涛)6.9节,实现高度自增的扩展TextInput组件时,按照原书代码运行发现报错。
查阅原书修正第六章时,发现问题所在:

代码6-9-1目前无法运行在RN 0.46之后的版本运行,因为从RN 0.46开始,在onChage属性的回调中不再携带contentSize。如果需要
获取contentSize,新版RN提供了onContentSizeChange回调属性。但在RN 0.47.1环境中调用onContentSizeChange,无法正确获
取到高度。我已经向RN社区反映了这个问题。目前只能等待这个bug的修复。

Giithub上react-native也有人提出了这个问题#issue6552

时至今日,在我当前的版本(0.59.5),onContentSizeChange获取高度的bug问题已经解决。
修改后的代码如下

js实现代码

import React, {Component} from 'react';
import {View, StyleSheet, Text, TextInput} from 'react-native';
class AutoExpandingTextInput extends Component {
    constructor(props) {
        super(props);
        this.state = {
            text: '',
            height: 0
        };
        this.onContentSizeChange = this._onContentSizeChange.bind(this);

        this.onChange = this._onChange.bind(this);
    }

    _onChange(event) {
        this.setState({
            text: event.nativeEvent.text,
        });
    }

    _onContentSizeChange(event) {
        this.setState({
            height: event.nativeEvent.contentSize.height
        });
    }
    render() {
        return (
            <TextInput  {...this.props}
                        multiline={true}
                        onChange={this.onChange}
                        onContentSizeChange={this.onContentSizeChange}
                        style={[styles.textInputStyle, {height: Math.max(35, this.state.height)}]}
                        value={this.state.text}/>
        );
    }
}

export default class App extends Component {
    /*constructor(props) {
        super(props);
    }*/

    _onChangeText = (newText) => {
        console.log('input text:' + newText);
    };

    render() {
        return (
            <View style={styles.container}>
                <AutoExpandingTextInput style={styles.textInputStyle} onChangeText={this._onChangeText}/>
            </View>
        );
    }
}

let styles = StyleSheet.create({
    container: {
        flex: 1,
        justifyContent: 'center',
        alignItems: 'center',
        backgroundColor: '#f5f5f5'
    },
    textInputStyle: {
        fontSize: 20,
        width: 300,
        height: 30,
        backgroundColor: 'grey',
        paddingTop: 0,
        paddingBottom: 0
    }
});

ts实现代码

index.tsx

/**
 * 自定义文本输入框
 */

import React, { useState } from "react";
import {
  TextInput,
  StyleProp,
  TextStyle,
  StyleSheet,
  TextInputProps,
  NativeSyntheticEvent,
  TextInputChangeEventData,
  TextInputContentSizeChangeEventData
} from "react-native";
import defaultStyles from "./styles";

export interface AutoExpandingTextInputProps extends TextInputProps {
  // 文本输入框样式
  textInputStyle?: StyleProp<TextStyle>;
}

const AutoExpandingTextInput = (props: AutoExpandingTextInputProps) => {
  const { textInputStyle, ...rest } = props;
  const [text = '', setText] = useState();
  const [height = 0, setHeight] = useState();
  const myTextInputStyle = StyleSheet.flatten([
    defaultStyles.textInputStyle, textInputStyle
  ]);

  const _onChange = (event: NativeSyntheticEvent<TextInputChangeEventData>) => {
    setText(event.nativeEvent.text);
  }

  const _onContentSizeChange = (event: NativeSyntheticEvent<TextInputContentSizeChangeEventData>) => {
    setHeight(event.nativeEvent.contentSize.height);
  }
  return (
    <TextInput  {...rest}
      style={[myTextInputStyle, { height: Math.max(35, height) }]}
      multiline={true}
      value={text}
      onChange={_onChange}
      onContentSizeChange={_onContentSizeChange} />
  );
};

export default AutoExpandingTextInput;

styles.ts

import { StyleSheet } from "react-native";
const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#f5f5f5'
  },
  textInputStyle: {
    fontSize: 20,
    width: 300,
    height: 30,
    backgroundColor: 'grey',
    paddingTop: 0,
    paddingBottom: 0
  }
});
export default styles;

ts调用

   <View style={styles.container}>
            <AutoExpandingTextInput onChangeText={_onChangeText} textInputStyle={styles.autoExpandTextInput} />
            <AutoExpandingTextInput onChangeText={_onChangeText} />
    </View>

const styles = StyleSheet.create({
    container: {
        flex: 1,
        alignItems: 'center',
        backgroundColor: '#f5f5f5'
    },
    autoExpandTextInput: {
        backgroundColor: 'blue'
    },
});

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/DeMonliuhui/article/details/89846841