react-native-paper icon indicating copy to clipboard operation
react-native-paper copied to clipboard

TextInput multiline text does not appear centered if only one line

Open paperskyline opened this issue 1 year ago • 14 comments

Current behaviour

When TextInput has multiline prop, the text is vertically aligned towards the top if the input field contains only one line (screenshot 1). If the text is longer and shows two or more lines, then everything appears fine and the content is centered accordingly. (screenshot 2). You can see from the image below where i marked the spacings in red

Expected behaviour

Text Should be centered inside the the TextInput even if it contains text which takes up only a single line.

How to reproduce?

<TextInput multiline mode='outlined' style={{ paddingRight: 10, paddingLeft: 10, fontSize: 16, color: 'black', backgroundColor: 'grey' }} dense />

Preview

Screenshot 2023-03-14 at 1 41 01 PM Screenshot 2023-03-14 at 1 41 19 PM

What have you tried so far?

textAlignVertical="center" did not work. Couldn't find other issues similar to this.

Your Environment

software version
ios 16
android 11
react-native 0.66.5
react-native-paper 4.11.2
node 16.17.0
npm or yarn 1.22.19

paperskyline avatar Mar 14 '23 06:03 paperskyline

Hey, thanks for Commenting! In My Opinion, Your issue could be solved by adjusting the Height of your text input and then Passing the textAlignVertical="center" prop This Should Work: <TextInput multiline mode="outlined" style={{ paddingRight: 10, paddingLeft: 10, fontSize: 16, color: "black", backgroundColor: "grey", height: 40, }} dense textAlignVertical="center" /> If you also Want to Check previous lines, you Could use a ScrollView. Hope this Helps!

AmrouKourchid avatar Mar 29 '23 21:03 AmrouKourchid

Hey, thanks for Commenting! In My Opinion, Your issue could be solved by adjusting the Height of your text input and then Passing the textAlignVertical="center" prop This Should Work: <TextInput multiline mode="outlined" style={{ paddingRight: 10, paddingLeft: 10, fontSize: 16, color: "black", backgroundColor: "grey", height: 40, }} dense textAlignVertical="center" /> If you also Want to Check previous lines, you Could use a ScrollView. Hope this Helps!

If you set the height, you are pretty much taking away the point of multiline. as for using scrollview to view the previous text, the UX is horrible.

paperskyline avatar Mar 30 '23 05:03 paperskyline

The TextInput from react-native has the exact same issue, so I don't think it's specific to react-native-paper

nathantew14 avatar Oct 24 '23 01:10 nathantew14

Adding the following would make it work properly

       contentStyle={{
              minHeight: 48,
              textAlignVertical: 'center',
            }}

andyto avatar Oct 31 '23 02:10 andyto

@andyto textAlignVertical is only for android.

nathantew14 avatar Oct 31 '23 02:10 nathantew14

I ended up making a component that adjusts paddingTop in the TextInput style based on whether it currently has a single line or multiple lines, which I detect using onLayout to track the height of the component. It was a lot of work just to make the text centered...

nathantew14 avatar Oct 31 '23 02:10 nathantew14

Encountered the same issue, ended up doing the following: Do not specify the height of the TextInput explicitly, instead wrap your TextInput inside a Pressable element, and center it vertically. You can propagate the press events from the Pressable element and focus the TextInput.

import React, { useRef } from 'react';
import { Pressable, TextInput, View } from 'react-native';

const YourComponent = () => {
  const textInputRef = useRef(null);
  const [message, setMessage] = React.useState<string>("")

  const handlePress = () => {
    if (textInputRef.current) {
      textInputRef.current.focus();
    }
  };

  return (
    <Pressable onPress={handlePress} style={styles.textInputView}>
      <TextInput
        ref={textInputRef}
        style={styles.messageInput}
        placeholder="Type your message..."
        placeholderTextColor="#999"
        value={message}
        onChangeText={setMessage}
        selectionColor="#1D1B1D"
        multiline
      />
    </Pressable>
  );
};


const styles = StyleSheet.create({
  textInputView: {
    minHeight: 40,
    justifyContent: 'center',
    paddingBottom: 8,
    flex: 1,
  },
  messageInput: {
    color: '#1D1B1D',
    fontSize: 15,
    lineHeight: 20,
    fontStyle: 'normal',
    letterSpacing: -0.075,
    paddingLeft: 10,
  }
});

tothp5991 avatar Jan 31 '24 11:01 tothp5991

This the best I could come up with: multiline={value.length > 35}; dynamically setting multiline based off number of characters.

alexkev avatar Mar 20 '24 21:03 alexkev

This the best I could come up with: multiline={value.length > 35}; dynamically setting multiline based off number of characters.

Very bad approach

segun-flexible avatar Mar 25 '24 10:03 segun-flexible

You got a better idea or a good reason?

alexkev avatar Mar 25 '24 17:03 alexkev

You got a better idea or a good reason?

For me this clears the value.

Setting paddingTop and paddingBottom to 8 on the TextInput seems to work fine

bogdanblazhkevych avatar Mar 28 '24 18:03 bogdanblazhkevych