React-native: TextInput prevent scroll on ScrollView

Created on 11 Jul 2019  路  25Comments  路  Source: facebook/react-native

In a too long form, scroll is only available if the touch start outside the TextInput fields

React Native version:

info Fetching system and libraries information...
System:
    OS: Linux 4.15 Ubuntu 18.04.2 LTS (Bionic Beaver)
    CPU: (4) x64 Intel(R) Core(TM) i7-6500U CPU @ 2.50GHz
    Memory: 1.92 GB / 7.67 GB
    Shell: 5.4.2 - /usr/bin/zsh
  Binaries:
    Node: 8.10.0 - /usr/bin/node
    npm: 3.5.2 - /usr/bin/npm
  SDKs:
    Android SDK:
      API Levels: 22, 23, 26, 27, 28
      Build Tools: 23.0.1, 27.0.3, 28.0.3
      System Images: android-27 | Google APIs Intel x86 Atom, android-28 | Google APIs Intel x86 Atom
  npmPackages:
    react: 16.8.6 => 16.8.6 
    react-native: 0.60.0 => 0.60.0 
  npmGlobalPackages:
    react-native-cli: 2.0.1
    react-native-debugger: 1.1.0
    react-native: 0.59.3

Steps To Reproduce

  1. create a ScrollView with flex: 1
  2. put more TextInputs than your screen can handle
  3. try to scroll with your touch starting on a field

Describe what you expected to happen:

I expect the page to scroll

Snack, code example, or link to a repository:

     <ScrollView style={{ flex: 1, }}>
            <TextInput placeholder="test" textAlign='center'/>
            <TextInput placeholder="test" textAlign='center'/>
            <TextInput placeholder="test" textAlign='center'/>
            <TextInput placeholder="test" textAlign='center'/>
            <TextInput placeholder="test" textAlign='center'/>
            <View style={{ height: 150, }} />
            <TextInput placeholder="test" textAlign='center'/>
            <TextInput placeholder="test" textAlign='center'/>
            <TextInput placeholder="test" textAlign='center'/>
            <TextInput placeholder="test" textAlign='center'/>
        </ScrollView>

snack: https://snack.expo.io/@aiiros/react-native-issue-25594

this is a duplicate of https://github.com/facebook/react-native/issues/15962 which has not yet been answered.

Edit:
Turns out textAlign='center' is causing all of this

Bug ScrollView TextInput Linux

Most helpful comment

All 25 comments

Hi @Aiiros,

I tried to reproduce your issue on Expo Snack: https://snack.expo.io/@robincsl/https:-github.com-facebook-react-native-issues-25594

and it seems to be working as intended: the TextInput components won't respond to touch when scrolling.

Can you provide a Snack/repository where you encounter this issue? This would help to reproduce it.

Hi @RobinCsl , thanks for answering.

After your example i stripped down my code to find out that textAlign="center" was causing all of this.
Of course i need to keep it :/

expo exemple : https://snack.expo.io/@aiiros/react-native-issue-25594

Exact same issue here, without textAlign="center" everything works fine.
I also noticed that it will work if you set multiline={true}, however I need it to be single line

Also I am on a mac, so I guess we can remove the Linux tag?

@RobinCsl
I quickly changed your snack to show the issue. For the textInputs that are centering their text the scrolling doesn't work.

https://snack.expo.io/@markuscosinus/https:-github.com-facebook-react-native-issues-25594

@markuscosinus and this happens only on Android, right?

style={{textAlign: "right"}} shows the same behaviour as style={{textAlign: "center"}}. However, style={{textAlign: "left"}} works fine.

And yes, multiline={true} with style={{textAlign: "center"}} makes it work too.

Might be time to dig into the native code deciding on this behaviour! 馃檪

I don't have an iOS device, but it works fine on the simulator.

Might be time to dig into the native code deciding on this behaviour! 馃檪

That would be amazing. Thanks a lot!

It seems like this would be the place where touch events are handled:
https://github.com/facebook/react-native/blob/master/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.java#L156-L179

@Override
  public boolean onTouchEvent(MotionEvent ev) {
    switch (ev.getAction()) {
      case MotionEvent.ACTION_DOWN:
        mDetectScrollMovement = true;
        // Disallow parent views to intercept touch events, until we can detect if we should be
        // capturing these touches or not.
        this.getParent().requestDisallowInterceptTouchEvent(true);
        break;
      case MotionEvent.ACTION_MOVE:
        if (mDetectScrollMovement) {
          if (!canScrollVertically(-1)
              && !canScrollVertically(1)
              && !canScrollHorizontally(-1)
              && !canScrollHorizontally(1)) {
            // We cannot scroll, let parent views take care of these touches.
            this.getParent().requestDisallowInterceptTouchEvent(false);
          }
          mDetectScrollMovement = false;
        }
        break;
    }
    return super.onTouchEvent(ev);
  }

I don't know Java enough, but my guess is that setting the alignment to center or right somehow makes the component think that it can scroll vertically or horizontally. I'm referring to this block:
https://github.com/facebook/react-native/blob/master/ReactAndroid/src/main/java/com/facebook/react/views/textinput/ReactEditText.java#L167-L173

          if (!canScrollVertically(-1)
              && !canScrollVertically(1)
              && !canScrollHorizontally(-1)
              && !canScrollHorizontally(1)) {
            // We cannot scroll, let parent views take care of these touches.
            this.getParent().requestDisallowInterceptTouchEvent(false);
          }

and searching the whole codebase for canScrollVertically or for canScrollHorizontally does not yield anything apart from the occurrences in this file.

I must say I'm a bit confused!

I don't know Java enough, but my guess is that setting the alignment to center or right somehow makes the component think that it can scroll vertically or horizontally.

That sounds logical.

and searching the whole codebase for canScrollVertically or for canScrollHorizontally does not yield anything apart from the occurrences in this file

canScrollHorizontally seems to be an method provided by android:
https://developer.android.com/reference/android/view/View.html#canScrollHorizontally(int)

But I have no idea, why it would return true just because of the text alignment

Okay, I think I found a solution!

I will create a PR later today!

Any updates ?

I created a PR 30 days ago and it hasn鈥檛 been reviewed yet. I don鈥檛 know if I should tag someone specifically to review it?

@RobinCsl Would your PR also fix this issue I opened a couple days ago?

https://github.com/facebook/react-native/issues/26526

If so, I can close that issue and include my snack.io examples in the comments here.

Hey there, it looks like there has been no activity on this issue recently. Has the issue been fixed, or does it still require the community's attention? This issue may be closed if no further activity occurs. You may also label this issue as a "Discussion" or add it to the "Backlog" and I will leave it open. Thank you for your contributions.

Don't close this issue. It's a major one and definitely deserves attention.

@RobinCsl Do you know if your fix ever found its way into a release?

Hi @edreyyo, as you can see, my PR is still open and I did not update it in a while since I've been busy. Feel free to push it further!

https://github.com/facebook/react-native/pull/25749

Hey there, it looks like there has been no activity on this issue recently. Has the issue been fixed, or does it still require the community's attention? This issue may be closed if no further activity occurs. You may also label this issue as a "Discussion" or add it to the "Backlog" and I will leave it open. Thank you for your contributions.

This is an important issue and still needs attention.

<TextInput
      multiline={true}
      numberOfLines={1}
    />

Set multiline=true and limit the numberOfLines can solve this problem temporarily

Hey there, it looks like there has been no activity on this issue recently. Has the issue been fixed, or does it still require the community's attention? This issue may be closed if no further activity occurs. You may also label this issue as a "Discussion" or add it to the "Backlog" and I will leave it open. Thank you for your contributions.

This is an important issue and still needs attention.

Any progress with your PR, @fabriziobertoglio1987?

@edreyyo I found a solution to this issue and included it in pr https://github.com/facebook/react-native/pull/29025

The problem is that my solution is a workaround, I have to disable the textAlign Center when editing the input field as some Android callbacks do not work with gravity Center on Android.

For this reason, my pr could cause rather then solve issues. Thanks.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

arunabha picture arunabha  路  3Comments

axelg12 picture axelg12  路  3Comments

lazywei picture lazywei  路  3Comments

josev55 picture josev55  路  3Comments

DreySkee picture DreySkee  路  3Comments