问题
在阅读《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'
},
});