Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

textInput renders invisible text when inner height is large #9077

Closed
offsky opened this issue Jul 28, 2016 · 7 comments
Closed

textInput renders invisible text when inner height is large #9077

offsky opened this issue Jul 28, 2016 · 7 comments
Labels
Platform: iOS iOS applications. Resolution: Locked This issue was locked by the bot.

Comments

@offsky
Copy link

offsky commented Jul 28, 2016

We are trying to use a textInput to edit a large blob of text. We are running into an issue where the text becomes invisible (but still editable and selectable) when the length reaches a certain point.

screen shot 2016-07-28 at 1 59 36 pm

The sample code below is enough to reproduce the problem. If you run this on an iPhone 6, the text will be invisible, but you can still scroll, edit and select text. There are three ways to make the text visible again:

  1. Shorten the length of the text (by changing 48 to 47 in the sample code)
  2. Rotate to landscape. (note that rotating back to portrait makes it invisible again)
  3. Decreasing the font size (by changing 13 to 12 in the sample code)

All three of the above actions will make the scroll height smaller. Based on this, we have determined that the length of the string is not problem, but rather the height of the internal scroll area. If you run this on something other than an iPhone 6, the same problem will occur, but with slightly different parameters since the width of the device may be different, which affects the height.

import React, { Component } from 'react';
import { AppRegistry, StyleSheet, Text, View } from 'react-native';
var TextInput = require('react-native').TextInput;

class LongNoteProject extends Component {
  render() {
    var text;
    for (var i = 0; i < 48; i++) {
      text += "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse a viverra nunc, et dictum lacus. Praesent fermentum mattis lectus sit amet porttitor. Sed porttitor dui vel magna lobortis interdum. Nullam accumsan elementum lacus eget molestie. Mauris tristique enim erat, non bibendum magna vestibulum a. Nullam fermentum facilisis magna eu tincidunt. Quisque tristique ornare semper. Phasellus sed efficitur libero. Aliquam tristique erat eu nulla scelerisque, sed eleifend elit ultricies. Nullam risus augue, imperdiet vitae sagittis nec, tristique at mi. Aliquam sed cursus dui. Etiam id orci eu ligula gravida mattis a interdum sapien.";
    }

    return (
      <View style={styles.container}>
        <TextInput
          style         = {styles.textstyle}
          multiline     = {true}
          value         = {text}
        />
      </View>
    );
  }
}

const styles = StyleSheet.create({
  textstyle: {
    flex: 1,
    fontSize: 13,
    padding: 4
  },
  container: {
    flex: 1
  }
});

AppRegistry.registerComponent('LongNoteProject', () => LongNoteProject);

ReactNative 0.30.0
React 15.2.1
Xcode 7.3.1 on macOS 10.11.5
iOS 9.3

@offsky
Copy link
Author

offsky commented Jul 28, 2016

By logging the height of the textView inside RCTTextView.m:updateContentSize I have determined that 8192px (exactly 2^11) in height is the breakpoint where text starts rendering as invisible.

@offsky
Copy link
Author

offsky commented Jul 28, 2016

In testing, I found another way to reproduce the problem which narrows down the problem a bit.

screen shot 2016-07-28 at 3 14 52 pm

Hard coding the height of the _textView.frame to 8193 causes the text to be invisible. Reducing this to 8192 causes it to display correctly.

@offsky
Copy link
Author

offsky commented Jul 28, 2016

So, I'm continuing to go down the rabbit hole and I discovered this stackOverflow question which has a lot of insight into the problem and makes me think that react-native is using a UITextView incorrectly.

It seems the issue is that when you are using a UITextView, Apple is expecting you to set the frame to be less than the size of the screen and then use it's internal scrolling abilities. This way, the UITextView can intelligently clip non rendered text. The way react-native is doing it, is to make the UITextView super large and then put this inside another UIScrollView. I am sure there were reasons for going this route and I dont know the implications for rewriting the react-native textInput to not use a wrapper UIScrollView.

@lacker
Copy link
Contributor

lacker commented Oct 28, 2016

From reading that stack overflow link it seems like maybe the best solution is just to use the workaround of not having TextInput that is this large. It doesn't seem like a bunch of people are running into this now though. I feel like I should close this issue, unless offsky you have more insights for what is going on here and what sort of fix might be useful.

@lacker lacker closed this as completed Oct 28, 2016
@offsky
Copy link
Author

offsky commented Oct 29, 2016

I would like to respectfully request that this issue remain open. This bug will be an issue for any app that allows the user to edit large blocks of text (note taking, messaging, email, document editing, etc).

There is no good workaround. The naive workaround is to limit the number of characters the user is allowed to type into the textInput, but this will not work because the bug depends little on the number of characters typed. It appears based on the height of the view, which depends on the screen dimensions, font size, character set, and actual text. In the worst case scenario (1 character per line) the bug will occur with only a few hundred characters typed.

The solution seems straight forward to me. A UITextView can scroll on its own. In fact, this is how Apple intends for it to be used, since a UITextView inherits from UIScrollView. However, this is not how ReactNative is using the UITextView. Instead, RN is setting the UITextView to be super tall, and then wrapping this inside another UIScrollView. This double wrapping of scroll containers is what is causing the problem because a UITextView was not design by Apple to be taller than the height of the screen.

I suggest that the UIScrollView be removed from RCTTextView.m and then reengineered so that the UITextView does the scrolling itself. Since it inherits from UIScrollView, it should be able to do everything that its wrapper UIScrollView did before. If I was a better Obj-C developer I would try this myself, but I am a JS developer so I'm hoping that someone else can take a stab at this.

@lacker lacker reopened this Oct 29, 2016
@lacker
Copy link
Contributor

lacker commented Oct 29, 2016

OK, I will reopen this. I'm not sure what the right thing to do is here though. What you propose seems like a fairly complex fix that is likely to break other things. If more people run into this issue it would be great if they could 👍 the original post so we can see how many people this hits, because if it's touching a small number of people then it might not be worth this disruption. I'm hoping there's some other sort of workaround here, though.

@shergin shergin added the Platform: iOS iOS applications. label Mar 16, 2017
@hramos
Copy link
Contributor

hramos commented Jul 21, 2017

Hi there! This issue is being closed because it has been inactive for a while. Maybe the issue has been fixed in a recent release, or perhaps it is not affecting a lot of people. Either way, we're automatically closing issues after a period of inactivity. Please do not take it personally!

If you think this issue should definitely remain open, please let us know. The following information is helpful when it comes to determining if the issue should be re-opened:

  • Does the issue still reproduce on the latest release candidate? Post a comment with the version you tested.
  • If so, is there any information missing from the bug report? Post a comment with all the information required by the issue template.
  • Is there a pull request that addresses this issue? Post a comment with the PR number so we can follow up.

If you would like to work on a patch to fix the issue, contributions are very welcome! Read through the contribution guide, and feel free to hop into #react-native if you need help planning your contribution.

@hramos hramos closed this as completed Jul 21, 2017
@hramos hramos added the Icebox label Jul 21, 2017
@facebook facebook locked as resolved and limited conversation to collaborators Jul 21, 2018
@react-native-bot react-native-bot added the Resolution: Locked This issue was locked by the bot. label Jul 21, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Platform: iOS iOS applications. Resolution: Locked This issue was locked by the bot.
Projects
None yet
Development

No branches or pull requests

5 participants