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

TextInput with TextAlign on iOS does not add ellipsis instead wraps

Open msaqlain opened this issue 3 years ago • 28 comments

import React, { PureComponent } from 'react';
import {Text, TextInput, View} from 'react-native';

const App = () => {
  return (
    <View style={{flex: 1, justifyContent: 'center'}}>
      <View>
        <Text>Text Input without alignment</Text>
        <TextInput style={{padding: 10, margin: 20, borderColor: 'grey', borderWidth: 1}}/>
        <Text>Text Input with right alignment</Text>
        <TextInput textAlign={'right'} style={{padding: 10, margin: 20, borderColor:  'grey', borderWidth: 1}}/>
      </View>
      <TextInput/>
    </View>);
};

export default App;

Write some long text into the first field with spaces. image

Write similar text into the second field. image

Unfocus second input Expected: both fields will have ellipsis at the end Actual: second input with textAlign doesn't have ellipsis.

Android app works in a different way: It never shows ellipsis but if you type a long string it always shows the end of it and never beginning. I guess it should move to begin when unfocused.

react: 16.11.0 => 16.11.0 react-native: 0.62.1 => 0.62.1

msaqlain avatar Jun 05 '20 11:06 msaqlain

:warning: Missing Environment Information
:information_source: Your issue may be missing information about your development environment. You can obtain the missing information by running react-native info in a console.

github-actions[bot] avatar Jun 05 '20 11:06 github-actions[bot]

Any Update? Its been 1 month now.

msaqlain avatar Jul 06 '20 08:07 msaqlain

Comment. Just to keep this thread active.

msaqlain avatar Aug 24 '20 06:08 msaqlain

I am also seeing this issue on "react-native": "0.61.5"

cameronbell avatar Sep 23 '20 17:09 cameronbell

Same on 0.63.3

xanderdeseyn avatar Nov 12 '20 13:11 xanderdeseyn

Any Solution?

JNUfeatherwit avatar Jun 08 '21 03:06 JNUfeatherwit

@JNUfeatherwit Adding VerticalPadding through CSS solves the issue of multiline but still no ellipsis.

shreypdev avatar Jul 04 '21 20:07 shreypdev

@JNUfeatherwit Adding VerticalPadding through CSS solves the issue of multiline but still no ellipsis.

Wow! It Actually works! Thank you

JNUfeatherwit avatar Jul 05 '21 06:07 JNUfeatherwit

This issue is still persisting. Adding the verticalPadding does not ultimately solve the problem. Any updates?

kokiebisu avatar Oct 01 '21 22:10 kokiebisu

@JNUfeatherwit can you elaborate on your vertical padding solution? There is no "CSS" in react-native so that is confusing to me. Applying vertical padding in the style for a TextInput isn't changing any of the wrapping behavior for us.

Having investigated, I believe the issue is in the RCTUITextField (which backs the single-line TextInput component) implementation itself. Text content is being set to the underlying UITextField using attributedText. Attributed text strings in iOS have a default paragraph style that permits wrapping. I was able to patch RCTUITextField with the following to change the default paragraph style to truncate, and this works. We're going to run with this patch for a while to see if it's a good fix, but would love to have additional feedback on this as a solution.

In RCTUITextField.m:

- (void)setDefaultTextAttributes:(NSDictionary<NSAttributedStringKey, id> *)defaultTextAttributes
{    
  if ([_defaultTextAttributes isEqualToDictionary:defaultTextAttributes]) {
    return;
  }

  // limit single-line fields to 1-line (no wrapping)
  if ([self.textInputDelegate isKindOfClass: [RCTSinglelineTextInputView class]]) {
      NSParagraphStyle* ps = defaultTextAttributes[NSParagraphStyleAttributeName];
      NSMutableParagraphStyle* mps = [ps mutableCopy];
      mps.lineBreakMode = NSLineBreakByTruncatingTail;
      NSMutableDictionary<NSAttributedStringKey, id>* mutableDefaultTextAttributes = [defaultTextAttributes mutableCopy];
      mutableDefaultTextAttributes[NSParagraphStyleAttributeName] = [mps copy];
      defaultTextAttributes = [mutableDefaultTextAttributes copy];
  }
    
  _defaultTextAttributes = defaultTextAttributes;
  [super setDefaultTextAttributes:defaultTextAttributes];
  [self _updatePlaceholder];
}

TomSwift avatar Dec 03 '21 17:12 TomSwift

any updates ? any solution ?

mohamedanwer123 avatar Jan 17 '22 10:01 mohamedanwer123

This is the workaround mentioned above:

StyleSheet.create({
 textInput: {
  ...Platform.select({
      ios: {
        paddingVertical: 0.001, // fix line wrap issue
      },
      android: {},
    }),
 }
});

osmyn avatar Mar 11 '22 20:03 osmyn

Any updates?

thiagobutignon avatar Apr 29 '22 16:04 thiagobutignon

Just found out this bug, because I'm using react-native-paper and due to this https://github.com/callstack/react-native-paper/issues/2684 issue and was able to find a solution inside the downstream issue

Shame that this issue is now 2 years old, and to me it seems critical to be resolved as beginners could stumble on this and get their frustration level rising

tiagomsmagalhaes avatar Jun 30 '22 15:06 tiagomsmagalhaes

To clarify, adding a slight vertical padding to the TextInput element does not always work, you've got to experiment and figure out what works without overflowing the text input.

Solution below:

const styles = new StyleSheet.create({
    textInput: {
        ...(Platform.OS === 'ios' ? {paddingVertical: 10} : {})
    }
})
const Element = () => <TextInput style={styles.textInput}>

GameraCC avatar Aug 22 '22 22:08 GameraCC

Oh... crap It needs to be fixed

riledv avatar Aug 26 '22 21:08 riledv

@JNUfeatherwit can you elaborate on your vertical padding solution? There is no "CSS" in react-native so that is confusing to me. Applying vertical padding in the style for a TextInput isn't changing any of the wrapping behavior for us.

Having investigated, I believe the issue is in the RCTUITextField (which backs the single-line TextInput component) implementation itself. Text content is being set to the underlying UITextField using attributedText. Attributed text strings in iOS have a default paragraph style that permits wrapping. I was able to patch RCTUITextField with the following to change the default paragraph style to truncate, and this works. We're going to run with this patch for a while to see if it's a good fix, but would love to have additional feedback on this as a solution.

In RCTUITextField.m:

- (void)setDefaultTextAttributes:(NSDictionary<NSAttributedStringKey, id> *)defaultTextAttributes
{    
  if ([_defaultTextAttributes isEqualToDictionary:defaultTextAttributes]) {
    return;
  }

  // limit single-line fields to 1-line (no wrapping)
  if ([self.textInputDelegate isKindOfClass: [RCTSinglelineTextInputView class]]) {
      NSParagraphStyle* ps = defaultTextAttributes[NSParagraphStyleAttributeName];
      NSMutableParagraphStyle* mps = [ps mutableCopy];
      mps.lineBreakMode = NSLineBreakByTruncatingTail;
      NSMutableDictionary<NSAttributedStringKey, id>* mutableDefaultTextAttributes = [defaultTextAttributes mutableCopy];
      mutableDefaultTextAttributes[NSParagraphStyleAttributeName] = [mps copy];
      defaultTextAttributes = [mutableDefaultTextAttributes copy];
  }
    
  _defaultTextAttributes = defaultTextAttributes;
  [super setDefaultTextAttributes:defaultTextAttributes];
  [self _updatePlaceholder];
}

Hey @TomSwift are you still using this patch or did you find any problems with it?

frenberg avatar Nov 30 '22 07:11 frenberg

Issue still open in react-native 0.70.6 😢

projectnatz avatar Feb 07 '23 09:02 projectnatz

Still an issue.

mikekreeki avatar Jul 13 '23 07:07 mikekreeki

Sometimes textAlign works, sometimes not.

yourjhay avatar Oct 28 '23 13:10 yourjhay

Hello,

Thanks for the issue. I have been contributing to facebook/react-native for 4 years and specialize in the Text/TextInput components. I currently have 58 facebook/react-native PRs:

https://github.com/facebook/react-native/pulls?q=is%3Apr+author%3Afabriziobertoglio1987+

This is the suggested approach from the react-native core team (see this discussion):

I'm publishing several fixes for Text and TextInput component in a separate library react-native-improved.

  • The Component is based on ReactTextView, it is the same implementation from react-native.
  • It will include several bug fixes.
  • You can use the library until the PR is merged and released with react-native.
  • You can use side by side both components from react-native and react-native-improved, depending on where you need the fix.
  • I will also publish the PR to facebook/react-native (daily fixes and releases).

The advantages would be:

  • Increased engagement with the community, issues are quickly fixed.
  • No limitations when merging PRs (react-native main branch is used on facebook marketplace).
  • Only Meta employees can merge and review facebook/react-native PRs.
  • Allows us to further experiment and develop react-native.

What do you think about this? Should I keep working on this? Thanks

fabOnReact avatar Jan 18 '24 08:01 fabOnReact

any updates?

sieeniu avatar Mar 25 '24 15:03 sieeniu

Would like to see this resolved as well. It's quite pesky that even with multiline={false} there is text that is able to wrap to the next line if a TextInput is not focused.

seanmaisch avatar Apr 03 '24 01:04 seanmaisch

Still doesn't work.

fix for me: Fixed height

MateuszBukowski93 avatar Apr 04 '24 08:04 MateuszBukowski93

would be nice to have this working

TomasSestak avatar Apr 15 '24 14:04 TomasSestak

Almost 4 years without a solution!

thiagobutignon avatar Apr 15 '24 15:04 thiagobutignon

This seems like a very core issue. Basic inputs like a text field is something I think everyone would expect to work in its basic form (i.e. just input long text).

tibbe avatar May 02 '24 13:05 tibbe

@JNUfeatherwit can you elaborate on your vertical padding solution? There is no "CSS" in react-native so that is confusing to me. Applying vertical padding in the style for a TextInput isn't changing any of the wrapping behavior for us.

Having investigated, I believe the issue is in the RCTUITextField (which backs the single-line TextInput component) implementation itself. Text content is being set to the underlying UITextField using attributedText. Attributed text strings in iOS have a default paragraph style that permits wrapping. I was able to patch RCTUITextField with the following to change the default paragraph style to truncate, and this works. We're going to run with this patch for a while to see if it's a good fix, but would love to have additional feedback on this as a solution.

In RCTUITextField.m:

- (void)setDefaultTextAttributes:(NSDictionary<NSAttributedStringKey, id> *)defaultTextAttributes
{    
  if ([_defaultTextAttributes isEqualToDictionary:defaultTextAttributes]) {
    return;
  }

  // limit single-line fields to 1-line (no wrapping)
  if ([self.textInputDelegate isKindOfClass: [RCTSinglelineTextInputView class]]) {
      NSParagraphStyle* ps = defaultTextAttributes[NSParagraphStyleAttributeName];
      NSMutableParagraphStyle* mps = [ps mutableCopy];
      mps.lineBreakMode = NSLineBreakByTruncatingTail;
      NSMutableDictionary<NSAttributedStringKey, id>* mutableDefaultTextAttributes = [defaultTextAttributes mutableCopy];
      mutableDefaultTextAttributes[NSParagraphStyleAttributeName] = [mps copy];
      defaultTextAttributes = [mutableDefaultTextAttributes copy];
  }
    
  _defaultTextAttributes = defaultTextAttributes;
  [super setDefaultTextAttributes:defaultTextAttributes];
  [self _updatePlaceholder];
}

This worked for me, thank you @TomSwift

ilight avatar May 09 '24 10:05 ilight