1
votes

I am trying to center a text input with a width that is the length of the text input. However when I use alignSelf: 'center', or alignItems: 'center', the text input is not visible without a width.

For example:

render() {
  return <View style={{flex: 1}}>
    <TextInput style={{alignSelf: 'center', minWidth: 1}}>
  <View/> 
}

Here the minWidth ensures that the textInput can be seen but it does not expand when you type in it. And without a width / minWidth the textInput would not be seen unless the centering style was removed.

Example with almost workable workaround:

constructor(props) {
  super(props)

  this.state = {
    txt: ""
    txtWidth: 0
  }
}

render() {
  return <View style={{flex: 1}}>
    <TextInput
      style={{minWidth: 1, alignSelf: 'center', width: this.state.txtWidth}}
      value={this.state.txt}
      onChange={txt=>this.setState({txt: txt.nativeEvent.text})}
    />
    <Text
      style={{position: 'absolute', right: 100000}}
      onLayout={e=>this.setState({txtWidth:e.nativeEvent.layout.width})}
    >
      {this.state.txt}
    </Text>
  <View/>
}

As the text input receives input, it grows in size and works great. However, one thing prevents it from being full proof. The e.nativeEvent.layout.width value for emoji is always 20. And the actual width of the given emoji is not 20. Thus the txtWidth is no longer the correct width for the textInput and pieces of the textInput are now cut off.

Has anyone come up with a good solution for a centered text input with a dynamic width. I have been stumped on this for way too long. Would be happy to provide clarity if needed as well.

Thanks!

1
regex emoji and calc your input width - Josh Lin
I still want to be able to allow emoji so regexing (and removing I assume) wouldn't quite fix my solution. But good suggestion! - RollinRight
I mean to keep your emoji, later I will post an answer - Josh Lin
I need to manage the cusor, so maybe not so soon. - Josh Lin

1 Answers

1
votes

Sorry kept you waiting, fininally got time to finish this. Use View,Image and Text to fake TextInput.

  • 1st step: format text when changed

you still need a TextInput. emoji in text might look like :fire: or 🔥, I choose the later. when text changes use regexp replace all emoji expressions to emoji character. then you move cursor it will not stop inside an emoji

  • 2nd setp: faked TextInput

it should look like

<View style={{flexDirection: 'row', flexWrap: 'wrap'}}>
  <Image style={styles.img} source={{uri: some_emoji}} />
  <Text>
    {"s"}
  </Text>
  <Text>
    {"s"}
  </Text>
  <MyCursor />
</View>

the emoji images should be within the same width, and to get width of Text might look like

<Text onLayout={(event) => {
  var {x, y, width, height} = event.nativeEvent.layout;
}} />

then you can get the total length and resize your View and hide your real TextInput and manage cursor, It worked in the web though not that smooth. this is why i use Text for every char like <Text>{"s"}</Text> cursor index should change when you click on each of them, and when focus, blur and keypress happens. you may refer https://github.com/postor/react-input-emoji/blob/master/pages/index.js for a web version fake input I've tried, yet cut, paste and lot's of things remain unhandled