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 with textAlign='right' inside a ScrollView gets focused on scroll (Android only) #12167

Closed
mmazzarolo opened this issue Feb 2, 2017 · 66 comments
Labels
Bug Component: TextInput Related to the TextInput component. Platform: Android Android applications. Ran Commands One of our bots successfully processed a command. Stale There has been a lack of activity on this issue and it may be closed soon.

Comments

@mmazzarolo
Copy link

mmazzarolo commented Feb 2, 2017

Description

Hello there,
I've found a small issue on Android.
When a TextInput with has textAlign: 'right' inside a ScrollView and you press on it for scrolling it will focus instead (only on Android).
The correct behaviour would be to get focused only if you tap on it (without scrolling).
It works perfectly on iOS or if you remove the textAlign style.

EDIT: I'm having the same issue with textAlign: 'center'.
Works correctly with every other prop (left, justify, auto).

Reproduction

You can test it easily:

<ScrollView>
  <TextInput style={{ textAlign: 'right' }} />
  <View style={{ height: 2000 }} />
</ScrollView>

Additional Information

  • React Native version: 0.40
  • Platform: Android (tested on an emulated Nexus 5 and on real Moto G3)
  • Operating System: MacOS
@hoangpham95
Copy link

I just tested with react-native 0.40.0 and cannot reproduce the problem. Which Android version are you running in your devices?
scroll

@mmazzarolo
Copy link
Author

That's weird. Are you starting the scroll by tapping the textinput?
Also, is that a blank project?
I'm on 5.1.0.

Oh, and thank you for trying it man!

@hoangpham95
Copy link

Yes, this is a blank project. I'm starting outside of the TextInput. If you tap the text input then it should be focused, so I think this might not be an issue.

@mmazzarolo
Copy link
Author

mmazzarolo commented Feb 2, 2017

Ah-ha, there it is!
Nope, it should not be focused because:

  1. If you remove the textAlign prop it doesn't get focused
  2. On iOS it doesn't get focused
  3. On many different native apps I tried it doesn't get focused (for example try the form in the new contact screen in Android)

Thank you anyway :)

@hoangpham95
Copy link

You're right, I tried and saw the problem. The textAlign caused the text input to be focused on touch.

@AndyJinSS
Copy link

I have the same problem on react-native 0.45.1

@igofind
Copy link

igofind commented Jul 11, 2017

+1
No one can solve this problem?

@yangthen
Copy link

yangthen commented Jul 11, 2017

+1
multiline={true}
keyboardType={"default"}
and limit the maxLength can solve this problem temporarily @igofind

@turlac
Copy link

turlac commented Jul 13, 2017

+1
@pecopeco just made my day. thank you for the workaround!
Any idea how we can get around the keyboard limitation of it having to be 'default' and not 'numeric'?

@igofind
Copy link

igofind commented Jul 14, 2017

@pecopeco
Thanks ! It works!

@kengjungwa
Copy link

@pecopeco works but NOT on keyboardType={"numeric"}

@ahmetacikgoz
Copy link

ahmetacikgoz commented Jul 31, 2017

+1
Same issue!

@programmdesign
Copy link

@pecopeco: thanks for the workaround. We can't use multiline though. Any idea for a workaround w/o multilines?

@enamin
Copy link

enamin commented Aug 29, 2017

+1
Same Issue

@yuvalsegev
Copy link

+1

Anyone willing to help?

@moughxyz
Copy link

I solved this issue by installing a PanResponder:

  componentWillMount: function() {
    this._panResponder = PanResponder.create({
      // Ask to be the responder:
      onStartShouldSetPanResponder: (evt, gestureState) => true,
      onStartShouldSetPanResponderCapture: (evt, gestureState) => true,
      onMoveShouldSetPanResponder: (evt, gestureState) => true,
      onMoveShouldSetPanResponderCapture: (evt, gestureState) => true,

      onPanResponderGrant: (evt, gestureState) => {
        // The gesture has started. Show visual feedback so the user knows
        // what is happening!

        // gestureState.d{x,y} will be set to zero now
      },
      onPanResponderMove: (evt, gestureState) => {
        // The most recent move distance is gestureState.move{X,Y}

        // The accumulated gesture distance since becoming responder is
        // gestureState.d{x,y}
      },
      onPanResponderTerminationRequest: (evt, gestureState) => true,
      onPanResponderRelease: (evt, gestureState) => {
        // The user has released all touches while this view is the
        // responder. This typically means a gesture has succeeded
      },
      onPanResponderTerminate: (evt, gestureState) => {
        // Another component has become the responder, so this gesture
        // should be cancelled
      },
      onShouldBlockNativeResponder: (evt, gestureState) => {
        // Returns whether this component should block native components from becoming the JS
        // responder. Returns true by default. Is currently only supported on android.
        return true;
      },
    });
  },

Then on your main view:

 <View {...this._panResponder.panHandlers} />

@nishiltamboli
Copy link

@pecopeco Thanks mate that worked like a charm. Weird issue really.

@moughxyz
Copy link

moughxyz commented Oct 7, 2017

For the record, The TextInput component is rendered inside of a TouchableWithoutFeedback that focuses on press, so I'm not sure how long any of these workarounds will last:

https://github.com/facebook/react-native/blob/master/Libraries/Components/TextInput/TextInput.js#L799

You might also be able to subclass TextInput, override the render method, and remove the Touchable wrapper.

@derakhshanfar
Copy link

derakhshanfar commented Oct 31, 2017

same issue for me, my textInput is numeric and i don't want a multiLine textinput

@derakhshanfar
Copy link

@mobitar could you write example please?

@aizigao
Copy link

aizigao commented Nov 20, 2017

same problem, has some solution ?

@derakhshanfar
Copy link

any solution?!

@yqz0203
Copy link

yqz0203 commented Dec 26, 2017

@derakhshanfar did you have resolved this problem?

@louislatreille
Copy link

+1
I also have the same issue when manually setting the height of the text input under the default height. This causes it to be vertically scrollable, and eat the ScrollView scroll action. Having the height set like that, removing the textAlign prop or the workaround proposed by @pecopeco aren't even working.

@ammoradi
Copy link

not fixed yet!
still it is in 0.60.4

@elmonshareh
Copy link

elmonshareh commented Nov 12, 2019

I tried all the best way that solved my problem
multiline={true}
blurOnSubmit={true} (it prevents you to make a new line .)
maxLength={20}
I know that is a work around but that is the best way till now

@leviduan
Copy link

Thank you so much, you help me resolve my question.

@stale
Copy link

stale bot commented Feb 27, 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 Feb 27, 2020
@aliakbarazizi
Copy link
Contributor

aliakbarazizi commented Mar 3, 2020

Is there any fix for this issue?
multiline can't be used with password input

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

it's about three years and this issue still exist

@mydesweb
Copy link

I have the same issue, it's 2020 and there is no working solution.. so sad!

@akhila-antony
Copy link

multiline={true}

I had an issue in textinput. textAlign propery was given as center and when I'm clearing my input completely the cursor will be at the right end.
Added multiline={true} fixed my issue.

@fabOnReact
Copy link
Contributor

I can not reproduce on react-native master. Can you provide a reproducible example or provide explanation of expected behaviour and maybe the documentation you are referring to? My code is

import React, { Component } from "react";
import { ScrollView, TextInput, View, Text, StyleSheet } from "react-native";

export default class App extends Component {
  render() {
    return (
      <ScrollView>
        <TextInput
          onFocus={() => console.warn("onFocus")}
          style={{ 
            textAlign: 'right',
            backgroundColor: 'yellow',
          }} />
        <View style={{ height: 2000 }} />
      </ScrollView>
    );
  }
}

const styles = StyleSheet.create({
});

this is the output. You will see console.warn("onFocus") when I tap on TextInput. Same behaviour without textAlign. It is what I expect with TextInput, otherwise how will the user type in it? Double Tap?

align_right

@aliakbarazizi
Copy link
Contributor

I can not reproduce on react-native master. Can you provide a reproducible example or provide explanation of expected behaviour and maybe the documentation you are referring to? My code is

import React, { Component } from "react";
import { ScrollView, TextInput, View, Text, StyleSheet } from "react-native";

export default class App extends Component {
  render() {
    return (
      <ScrollView>
        <TextInput
          onFocus={() => console.warn("onFocus")}
          style={{ 
            textAlign: 'right',
            backgroundColor: 'yellow',
          }} />
        <View style={{ height: 2000 }} />
      </ScrollView>
    );
  }
}

const styles = StyleSheet.create({
});

this is the output. You will see console.warn("onFocus") when I tap on TextInput. Same behaviour without textAlign. It is what I expect with TextInput, otherwise how will the user type in it? Double Tap?

align_right

try this
https://snack.expo.io/@cooper47/c2a6bb
android version

try to scroll page while first touch is on textinput.
not tapping, just drag on textinput for scroll and see the textinput will be focused.

excepted behavior is page scroll without focus on textinput

@stale
Copy link

stale bot commented Aug 29, 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 Aug 29, 2020
@aliakbarazizi
Copy link
Contributor

Issue still exist

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

is there any solution

berghdavid added a commit to careerfairsystems/nexpo-app that referenced this issue Oct 25, 2021
Builds a basic QR-screen which has the simple functionality to scan
QR-codes of a student-ID and send a companyConnection - request.
Next step is to add a 1-5 rating framework and also implement a QR-code
for the students.

Additional fixes:
Solves problem in profileScreen where ScrollView wouldn't scroll when
dragging on a <TextInput> which has style textAlign: 'center'. Solved
by adding the attribute numberoflines={1} to the <TextInput>.
More on the issue: facebook/react-native#12167
@lucassouza16
Copy link

lucassouza16 commented Dec 9, 2022

This solution solves the problem, but it makes it impossible for the user to move the cursor through the text or select it, it is still more practical to use, I did this improvisation but the experience is still not good:

import React, { forwardRef, useState, useRef, useImperativeHandle } from "react";
import {
    Text,
    StyleSheet,
    TouchableOpacity,
    TextStyle,
    TextInput as TextInputComponent,
    TextInputProps as TextInputComponentProps
} from "react-native";

export type TextInputProps = TextInputComponentProps & {};

export type TextInputRef = TextInputComponent & {};

const TextInput = (
    {
        style,
        multiline,
        placeholder,
        value,
        placeholderTextColor,
        textAlign: textAlignProp,
        ...rest
    }: TextInputProps,
    ref: any
) => {

    const inputRef = useRef<TextInputComponent>(null);
    const [widthPlaceholder, setWidthPlaceholder] = useState(0);

    let {
        textAlign,
        fontFamily,
        fontSize,
        fontStyle,
        fontWeight,
        textTransform,
        lineHeight,
        textAlignVertical,
        color,
        ...containerStyle
    } = StyleSheet.flatten(style);

    let textStyle: TextStyle = {
        fontFamily,
        fontSize,
        fontStyle,
        fontWeight,
        textTransform,
        lineHeight,
        color
    };

    textAlign = textAlign || textAlignProp;

    if (!multiline) {
        switch (textAlign) {
            case 'center':
                containerStyle.alignItems = 'center';
                break;
            case 'right':
                containerStyle.alignItems = 'flex-end';
                break;
        }
    } else {
        textStyle = { ...textStyle, textAlign, width: '100%' };
    }

    switch (textAlignVertical) {
        case 'top':
            containerStyle.justifyContent = 'flex-start';
            break;
        case 'bottom':
            containerStyle.justifyContent = 'flex-end';
            break;
        case 'center':
        default:
            containerStyle.justifyContent = 'center';
            break;
    }

    useImperativeHandle(ref, () => inputRef.current);

    return (
        <TouchableOpacity
            style={
                [
                    styles.container,
                    containerStyle
                ]
            }
            activeOpacity={1}
            onPress={() => {
                inputRef.current?.blur();
                inputRef.current?.focus();
            }}
        >
            {
                !value && <Text
                    numberOfLines={1}
                    style={
                        [
                            styles.placeholder,
                            textStyle,
                            { color: placeholderTextColor || color }
                        ]
                    }
                    onLayout={
                        ({ nativeEvent }) =>
                            setWidthPlaceholder(nativeEvent.layout.width)
                    }
                >
                    {placeholder}
                </Text>
            }
            <TextInputComponent
                {...rest}
                ref={inputRef}
                value={value}
                multiline={multiline}
                placeholderTextColor="transparent"
                placeholder={multiline ? placeholder : undefined}
                style={
                    [
                        styles.input,
                        textStyle,
                        {
                            width: value ? undefined : widthPlaceholder,
                            color: value ? color : 'transparent'
                        }
                    ]
                }
            />
        </TouchableOpacity>
    );
};

const styles = StyleSheet.create({
    input: {
        minWidth: 2,
        maxWidth: '100%'
    },
    placeholder: {
        maxWidth: '100%',
        position: 'absolute'
    },
    container: {
        justifyContent: 'center'
    }
});

export default forwardRef<
    TextInputRef,
    TextInputProps
>(TextInput);

@github-actions
Copy link

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.

@github-actions github-actions bot added the Stale There has been a lack of activity on this issue and it may be closed soon. label Jun 13, 2023
@lucassouza16
Copy link

Este problema está obsoleto porque está aberto há 180 dias sem atividade. Remova o rótulo ou comentário obsoleto ou isso será fechado em 7 dias.

A

@github-actions github-actions bot removed the Stale There has been a lack of activity on this issue and it may be closed soon. label Jun 14, 2023
Copy link

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.

@github-actions github-actions bot added the Stale There has been a lack of activity on this issue and it may be closed soon. label Dec 11, 2023
Copy link

This issue was closed because it has been stalled for 7 days with no activity.

@JuozasIzi1
Copy link

please reopon this

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug Component: TextInput Related to the TextInput component. Platform: Android Android applications. Ran Commands One of our bots successfully processed a command. Stale There has been a lack of activity on this issue and it may be closed soon.
Projects
None yet
Development

Successfully merging a pull request may close this issue.