Craigson
Craigson

Reputation: 131

react-native TextInput clips text

I'm trying to create an expandable text view. I've tried using the onChangeContentSize property of TextInput, but it doesn't update the width. If I don't explicitly set the width, the content TextInput expands as I type, which is the desired behavior, but it starts to clip/obscure the text as it grows.

Hopefully the issue can be fixed with styling, but so far I haven't been able to. It's almost like I need be able to set an overflow prop that doesn't exist.

Code is:

  render() {

    console.log(this.state.width)
    let inputStyle = {
        color: '#fff',
        // width: this.state.width,
        fontSize: 60,
        lineHeight: 60,
        fontFamily: 'GT-Walsheim-Bold'
    }

      return (
        <View style={styles.containerStyle}>
          <Text style={styles.labelStyle}>{this.props.label}</Text>
          <TextInput
            secureTextEntry={this.props.secureTextEntry}
            placeholder={this.props.placeholder}
            autoCorrect={false}
            style={inputStyle}
            value={this.props.value}
            onChangeText={this.props.onChangeText}
            autoFocus={true}
            autoCapitalize={this.props.capitalize}
          />
        </View>
      );
  }

const styles = {

  labelStyle: {
    fontSize: 36,
    fontFamily: 'GT-Walsheim-Bold'
  },
  containerStyle: {
    height: 200,
    flex: 1,
    alignItems: 'center',
    justifyContent: 'center',
    textAlign: 'center'
  }
};

Dev Env: OSX 10.12 react-native: 16.3.1 react: 0.55.4 platform: Android

See images attached:

Before typing: enter image description here

After typing: enter image description here

Upvotes: 4

Views: 3041

Answers (3)

mackwerk
mackwerk

Reputation: 1687

I just ran into the same problem, and if you pass a <Text /> (with your styling + font of course) component as the child of <TextInput /> it should work.

class MyComponent extends React.PureComponent {
  render () {

    console.log(this.state.width)
    let textStyle = {
        color: '#fff',
        // width: this.state.width,
        fontSize: 60,
        lineHeight: 60,
        fontFamily: 'GT-Walsheim-Bold'
    }

    return (
      <View style={styles.containerStyle}>
        <Text style={styles.labelStyle}>{this.props.label}</Text>
        <TextInput
          secureTextEntry={this.props.secureTextEntry}
          placeholder={this.props.placeholder}
          autoCorrect={false}
          style={inputStyle}
          onChangeText={this.props.onChangeText}
          autoFocus={true}
          autoCapitalize={this.props.capitalize}
        >
          <Text>{this.props.value}</Text>
        </TextInput>
      </View>
    );
  }
}

const styles = {
  labelStyle: {
    fontSize: 36,
    fontFamily: 'GT-Walsheim-Bold'
  },
  containerStyle: {
    height: 200,
    flex: 1,
    alignItems: 'center',
    justifyContent: 'center',
    textAlign: 'center'
  }
};

Upvotes: 0

Craigson
Craigson

Reputation: 131

After much tinkering, it turns out the clipping is related to the custom font. Substituting the font solves the problem. It seems the expanding TextInput's default behavior when no width is set is doing exactly what I need it to.

Upvotes: 1

Rajat Gupta
Rajat Gupta

Reputation: 1954

So one of the hackish ways is to set width via the state, suppose initially width is around 20 pixel(depending upon your font) and then for each addition of character, you will add 16px(depending upon your font) to the width.

Example:-

          <TextInputCustom
              style={[{
                fontSize: 34,
                width:this.state.flexibleWidth// intially 27px
                textAlign: 'center',
                fontWeight: "bold",
                fontStyle: "normal",
                letterSpacing: -0.31,
                color: Colors.BLACK}]}
              isUnderlineRequired={false}
              onChangeText={(text) => this.checkInteger(text)}
              placeholder={"0"}
              returnKeyLabel="done"
              keyboardType="numeric"
              maxLength={10}
              value={this.state.amount + ""}
              ref={"input"}
            />

checkInteger function

  checkInteger = (text) => {
    let len = text.length
  
    this.setState((state) => {
        return {
          amount: text,
          flexibleWidth: (len * 16) + 27
          error:'
        }
    })
  }

Upvotes: 0

Related Questions