Last active
November 22, 2017 06:18
-
-
Save BCGen/9ba9f7d96459fd063e42bd53f9839217 to your computer and use it in GitHub Desktop.
Solution for expo SDK 16 and RN 0.43.2, TextInput Multiline={true} issue, In RN 0.46 fixed android onContentSizeChange issue.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { action } from 'mobx'; | |
import React, { PureComponent } from 'react'; | |
import { StyleSheet, TextInputProperties, TextStyle, ViewStyle } from 'react-native'; | |
import MultilineInput from './MultilineInput'; | |
interface State { | |
height: number; | |
} | |
// In RN 0.46 fixed conContentSizeChange problem. | |
export default class AutoExpandingInput extends PureComponent<TextInputProperties, State> { | |
_inputRef; | |
constructor(props) { | |
super(props); | |
this.state = { | |
height: 0, | |
}; | |
} | |
@action | |
componentWillReceiveProps(props) { | |
if (!props.value) { | |
this.setState({ height: 100 }); | |
} | |
} | |
render() { | |
const { | |
onContentSizeChange, | |
style, | |
...otherProps, | |
} = this.props; | |
return ( | |
<MultilineInput | |
{...otherProps} | |
ref={this._ref} | |
onContentSizeChange={this._onContentSizeChange} | |
style={[styles.textInputStyle, style, { height: this.state.height }]} | |
/> | |
); | |
} | |
focus = () => { | |
this._inputRef.focus(); | |
} | |
private _onContentSizeChange = (event): void => { | |
const height = event.nativeEvent.contentSize.height; | |
const { onContentSizeChange } = this.props; | |
this.setState({ height }); | |
if (onContentSizeChange) { | |
onContentSizeChange(event); | |
} | |
} | |
private _ref = ref => { | |
this._inputRef = ref; | |
} | |
} | |
// set textAlignVertical: 'top' make sure text one the top and | |
// not shock when TextInput's height changed. | |
interface Styles { | |
textInputStyle: TextStyle & ViewStyle; | |
} | |
const styles = StyleSheet.create<Styles>({ | |
textInputStyle: { | |
fontSize : 20, | |
paddingHorizontal: 10, | |
paddingVertical : 10, | |
textAlignVertical: 'top', | |
} | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React, { PureComponent } from 'react'; | |
import { TextInput, TextInputProperties } from 'react-native'; | |
interface State { | |
cursorPosition: { | |
end: number, | |
start: number, | |
}; | |
isSubmit: boolean; | |
value: string; | |
} | |
/* | |
* below only test on android, when set TextInput multiline={true}, some | |
* keyboard will blur and call onSubmitEditing when press enter key, | |
* so set blurOnSubmit={false}, and in onSubmitEditing() call onChangeText() | |
* then add one line below value, on android onSubmitEditing will trigger twice, | |
* so check if SubmitEditing already called. | |
*/ | |
export default class MultilineInput extends PureComponent<TextInputProperties, State> { | |
constructor(props) { | |
super(props); | |
this.state = { | |
cursorPosition: { end: 0, start: 0 }, | |
isSubmit : false, | |
value : '', | |
}; | |
} | |
render() { | |
const { | |
blurOnSubmit = false, | |
multiline = true, | |
onChangeText = this._onChangeText, | |
onSubmitEditing, | |
value = this.state.value, | |
...other, | |
} = this.props; | |
const { end, start } = this.state.cursorPosition; | |
return ( | |
<TextInput | |
{...other} | |
blurOnSubmit={blurOnSubmit} | |
multiline={multiline} | |
selection={{ start, end }} | |
onChangeText={onChangeText} | |
onSubmitEditing={this._onSubmitEditing} | |
onSelectionChange={this._onSelectionChange} | |
value={value} | |
/> | |
); | |
} | |
private _onChangeText = (value: string): void => { | |
this.setState({ value }); | |
} | |
private _onSelectionChange = (event): void => { | |
this.setState({ cursorPosition: event.nativeEvent.selection }); | |
} | |
// on android onSubmitEditing trigger twice, not test on ios. | |
// when first time, add new line after value(thanks to nikolay-radkov), | |
// second move cursor to next position (start of new line). | |
private _onSubmitEditing = (event): void => { | |
const { onChangeText, onSubmitEditing, value = this.state.value } = this.props; | |
if (!this.state.isSubmit) { | |
let newValue = value; | |
if (value.length === this.state.cursorPosition.end) { | |
newValue = value + '\n'; | |
} else { | |
const ar = newValue.split(''); | |
ar.splice(this.state.cursorPosition.end, 0, '\n'); | |
newValue = ar.join(''); | |
} | |
if (onChangeText) { | |
onChangeText(newValue); | |
} else { | |
this._onChangeText(newValue); | |
} | |
if (onSubmitEditing) { | |
onSubmitEditing(event); | |
} | |
const newPosition = this.state.cursorPosition.end + 1; | |
this.setState({ | |
cursorPosition: { start: newPosition, end: newPosition }, | |
}); | |
} | |
this.setState({ isSubmit: !this.state.isSubmit }); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I got an error when trying to use it:
Undefined isn't an object evaluation _react.PorpTypes.string