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 prevent scroll on ScrollView #25594

Open
Aiiros opened this issue Jul 11, 2019 · 53 comments
Open

TextInput prevent scroll on ScrollView #25594

Aiiros opened this issue Jul 11, 2019 · 53 comments
Labels
Bug Component: ScrollView Component: TextInput Related to the TextInput component. Platform: Linux Building on Linux.

Comments

@Aiiros
Copy link

Aiiros commented Jul 11, 2019

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 #15962 which has not yet been answered.

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

@Aiiros Aiiros added the Bug label Jul 11, 2019
@react-native-bot react-native-bot added Component: ScrollView Component: TextInput Related to the TextInput component. Platform: Linux Building on Linux. labels Jul 11, 2019
@RobinCsl
Copy link

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.

@Aiiros
Copy link
Author

Aiiros commented Jul 16, 2019

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

@markus-utke
Copy link

markus-utke commented Jul 16, 2019

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

@markus-utke
Copy link

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

@markus-utke
Copy link

@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

@RobinCsl
Copy link

@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! 🙂

@markus-utke
Copy link

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!

@RobinCsl
Copy link

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!

@markus-utke
Copy link

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

@RobinCsl
Copy link

Okay, I think I found a solution!

I will create a PR later today!

@Aiiros
Copy link
Author

Aiiros commented Aug 19, 2019

Any updates ?

@RobinCsl
Copy link

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

@daveyjones
Copy link

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

#26526

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

@stale
Copy link

stale bot commented Dec 22, 2019

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.

@stale stale bot added the Stale There has been a lack of activity on this issue and it may be closed soon. label Dec 22, 2019
@daveyjones
Copy link

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

@stale stale bot removed the Stale There has been a lack of activity on this issue and it may be closed soon. label Dec 23, 2019
@edreyyo
Copy link

edreyyo commented Feb 27, 2020

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

@RobinCsl
Copy link

RobinCsl commented Mar 1, 2020

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!

#25749

@stale
Copy link

stale bot commented May 30, 2020

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.

@stale stale bot added the Stale There has been a lack of activity on this issue and it may be closed soon. label May 30, 2020
@daveyjones
Copy link

This is an important issue and still needs attention.

@stale stale bot removed the Stale There has been a lack of activity on this issue and it may be closed soon. label May 31, 2020
@fabOnReact
Copy link
Contributor

fabOnReact commented Jun 1, 2020

I am working on a pull request #25749 (comment)

@edreyyo
Copy link

edreyyo commented Dec 15, 2020

@fabriziobertoglio1987 Alright, thanks for the update. Hopefully there's a fix available soon.

@PoLePanda
Copy link

PoLePanda commented Feb 3, 2021

I fix this temporary with this props (if this can help some one else)

multiline={true} numberOfLines={1} blurOnSubmit={true} returnKeyType={"done"}

@AbhilashZemoso
Copy link

I fix this temporary with this props (if this can help some one else)

multiline={true} numberOfLines={1} blurOnSubmit={true} returnKeyType={"done"}

Thanks a lot, it is working

@SarvaDev-123
Copy link

Does this fix have any predictions for leaving? I tried this temporary fix but to no avail:
multiline={true} numberOfLines={1} blurOnSubmit={true} returnKeyType={"done"}

Edit: I change the height the textinput and solved my problems

height is fail in case of Hebrew language or when you performing rtl activity.

@alimo
Copy link

alimo commented Jul 25, 2021

I had the exact same issue. In my case, the problem was the default vertical padding in text inputs.

This padding takes some space and makes the input content scrollable. This is problematic for the outer ScrollView because it thinks you're trying to scroll the input content.

I fixed the issue by adding a paddingVertical: 0 style to my text inputs.

@AlirezaHadjar
Copy link

AlirezaHadjar commented Oct 29, 2021

Can't we solve this without multiline = true ?

@oyylumo
Copy link

oyylumo commented Feb 13, 2022

has this still not been fixed?

@pdlm95
Copy link

pdlm95 commented May 6, 2022

Any news on this issue?

@TomasSestak
Copy link

still major issue

@rvenky125
Copy link

Can't we solve this without multiline = true ?

I'm still having the issue event if tried all those. Does any one have a better solution

@pdlm95
Copy link

pdlm95 commented Jun 17, 2022

@rvenky125 I figured out that editable prop when is set to false is the cause of the scroll issue, so I solved it (kinda) by adding a readOnly prop and a validation in onChangeText method.

<ChildFieldText editable={true} multiline={true} numberOfLines={2} readOnly {...props} />

And in parent component:

onChangeText = (e: any) => {
    if (this.props.readOnly) return;
   ...
}

It's not the best solution but it works for me

@rvenky125
Copy link

@rvenky125 I figured out that editable prop when is set to false is the cause of the scroll issue, so I solved it (kinda) by adding a readOnly prop and a validation in onChangeText method.

<ChildFieldText editable={true} multiline={true} numberOfLines={2} readOnly {...props} />

And in parent component:

onChangeText = (e: any) => {
    if (this.props.readOnly) return;
   ...
}

It's not the best solution but it works for me

Thanks for your reply. But in my case, there is no need to change the editable. It's always true to me. Still, I'm having the problem.

@1mehdifaraji
Copy link

1mehdifaraji commented Sep 27, 2022

I solved the issue by including these properties to the TextInput :

multiline
numberOfLines={1}

This issue is only on android devices only . Wish they fix this issue later on .

The pitfall of doing this is you won't be able to apply password hidden characters on input so the prop called secureTextEntry={true} won't work and I did a workaround not to apply multiline when secureTextEntry is a must like this :

  <TextInput
        ...
        multiline={!secureTextEntry}
        secureTextEntry={secureTextEntry}
      />

@AlirezaHadjar
Copy link

Multiline is not a proper solution because the return button on keyboard changes from default and also you wont be able to apply password type

@lucassouza16
Copy link

So far it's serving me well:

#12167 (comment)

@lucassouza16
Copy link

lucassouza16 commented Dec 24, 2022

Thank you, your tip helped me to solve the problem in my case, as on android it does not use the files from the node_modules folder changing the files directly there had no effect, so I tried to build react native from source as instructed on the website: https://reactnative.dev/contributing/how-to-build-from-source to apply the fix, but I wasn't successful, maybe because the page is out of date, so I improvised and encapsulated the entire TextInput component in a module and changed the code snippet in question lucassouza16/react-native-reanimated-textinput@b8c86f9...3b91242#diff-eb7293e9d8fcb1a86324377045b86c30db420d66334740bac6d95401be3a4ac1, the only downside is that the module only works for the react version I extracted it from, but I plan to recreate this component from scratch in case the developers don't solve these bugs in the future, it's sad to think that fixing the problem is so simple, even for me who have little knowledge, but the framework developers neglected it, and even sadder is going to your client and saying that you can't do something t It's not as simple as lining up a text in an input, without leaving usability a tragedy.

@dongCode
Copy link

I fix this temporary with this props (if this can help some one else)

multiline={true} numberOfLines={1} blurOnSubmit={true} returnKeyType={"done"}

cool

@Shahzaib114
Copy link

If ScrollView working fine on Android and creating issue on IOS, then simply use scroll view property automaticallyAdjustKeyboardInsets= {true}

@Assamese-Boy
Copy link

I am using RN 0.71, I have faced the same issue in my textInput, to solve this don't give any height to the textInput instead use extra view to adjust the heights. Thanks

@darimuhittinhey
Copy link

I am using RN 0.71, I have faced the same issue in my textInput, to solve this don't give any height to the textInput instead use extra view to adjust the heights. Thanks

This solved the issue. Just dont give height. Thank you so much dude.

@dibyopra
Copy link

I am using RN 0.71, I have faced the same issue in my textInput, to solve this don't give any height to the textInput instead use extra view to adjust the heights. Thanks

its working, instead use minHeight

@Jolteon18
Copy link

In my case, I noticed I was using import {TextInput} from 'react-native-gesture-handler'; instead import {TextInput} from 'react-native';.

Switching from the react-native-gesture-handler to react-native worked for me

@react-native-bot
Copy link
Collaborator

This issue is stale because it has been open 180 days with no activity. Remove stale label or comment or this will be closed in 7 days.

@react-native-bot react-native-bot added the Stale There has been a lack of activity on this issue and it may be closed soon. label Aug 13, 2024
@AlirezaHadjar
Copy link

Not stale

@react-native-bot react-native-bot removed the Stale There has been a lack of activity on this issue and it may be closed soon. label Aug 14, 2024
@stochmalm
Copy link

This issue still needs to be fixed.

@ouabel
Copy link

ouabel commented Aug 22, 2024

A dirty workaround is to make the input multiline only when it is touched (to scroll)

import { useState } from 'react';
import { TextInput as RNTextInput } from 'react-native';

function TextInput({ multiline, innerRef, ...props }) {
  const [isMultiline, setIsMultiline] = useState(false);

  return (
    <RNTextInput
      ref={innerRef}
      {...props}
      onTouchStart={() => setIsMultiline(true)}
      onTouchEnd={() => setIsMultiline(false)}
      onTouchCancel={() => setIsMultiline(false)}
      onTouchMove={() => setIsMultiline(false)}
      multiline={multiline || isMultiline}
    />
  );
}

export default TextInput;

@hieuminh1810
Copy link

still issue

@ItsaMeTuni
Copy link

5 years later and this is still an issue lmao

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug Component: ScrollView Component: TextInput Related to the TextInput component. Platform: Linux Building on Linux.
Projects
None yet