callstack / react-native-paper

Material Design for React Native (Android & iOS)
https://reactnativepaper.com
MIT License
12.91k stars 2.09k forks source link

TextInput autofocus is not opening keyboard on Android #4456

Open JestemTrzcinska opened 3 months ago

JestemTrzcinska commented 3 months ago

Current behaviour

Trying to improve user experience by auto focusing to input and showing keyboard. On iOS everything works fine, but on Android two thinks are happening.

TextInput gets auto focused on Android but: 1) keyboard is not showing automatically, only after direct pressing text input 2) I have bottom sheet that is behind modal with text input and after pressing on TextInput to get the keyboard open the BottomSheet rises for no reason.

Expected behaviour

When opening modal (TextInput initial) the TextInput is focused and keyboard is open (as on iOS)

How to reproduce?

First case code example: code example on snack.expo.dev

Preview

Second case preview:

2 case (2) 2 case (1)

What have you tried so far?

update react-native-paper

Your Environment

software version
ios 17.0
android 34
react-native ^0.73.6
react-native-paper ^5.12.3
node 18.18.0
npm or yarn 9.8.1
expo sdk x.x.x
kamilkedzierski commented 3 months ago

@JestemTrzcinska let me take a look into this issue! 👀

kamilkedzierski commented 3 months ago

So, I've been looking into this issue with TextInput using autofocus inside a Modal from react-native on Android. Turns out, it's a known problem. The Modal component creates a new root view, and sometimes the keyboard doesn't show up because the modal's new view hierarchy isn't fully rendered by the time the TextInput tries to focus.

I've found a workaround that's helped others with the same issue. You can check it out here: autofocus workaround.

On another note, I've tested the TextInput autofocus with BottomSheetModal from @gorhom/bottom-sheet, and it worked perfectly without any need for workarounds. If it's possible to use @gorhom/bottom-sheet in your project, it might be worth a try! Unfortunately, I couldn't add @gorhom/bottom-sheet to an Expo Snack, but here's a snippet you can use.

Video of BottomSheetModal from @gorhom/bottom-sheet https://github.com/user-attachments/assets/ca663390-baff-4ec8-9466-5dad587b29e5

import * as React from 'react';
import { useState } from 'react';
import { Button, StyleSheet, View } from 'react-native';

import {
  BottomSheetModal,
  BottomSheetModalProvider,
  BottomSheetView,
} from '@gorhom/bottom-sheet';
import { TextInput } from 'react-native-paper';

export const Example = () => {
  const [searchFilter, setSearchFilter] = useState('');

  const bottomSheetModalRef = React.useRef<BottomSheetModal>(null);

  const handlePresentModalPress = React.useCallback(() => {
    bottomSheetModalRef.current?.present();
  }, []);
  const handleSheetChanges = React.useCallback((index: number) => {
    console.log('handleSheetChanges', index);
  }, []);

  return (
    <View style={styles.container}>
      <Button title={'show modal'} onPress={handlePresentModalPress} />
      <BottomSheetModalProvider>
        <BottomSheetModal
          ref={bottomSheetModalRef}
          onChange={handleSheetChanges}
          snapPoints={['25%', '50%', '75%']} 
        >
          <BottomSheetView style={styles.contentContainer}>
            <TextInput
              textColor={'black'}
              value={searchFilter}
              onChangeText={setSearchFilter}
              style={styles.textInput}
              dense
              mode="outlined"
              outlineStyle={styles.outlineStyle}
              autoFocus
            />
          </BottomSheetView>
        </BottomSheetModal>
      </BottomSheetModalProvider>
    </View>
  );
};

const styles = StyleSheet.create({
  textInput: {
    fontSize: 17,
    width: '100%',
    marginTop: 10,
  },
  container: {
    flex: 1,
    padding: 24,
    justifyContent: 'center',
    backgroundColor: '#f6f6f6',
  },
  contentContainer: {
    flex: 1,
    alignItems: 'center',
    width: '100%',
    padding: 10,
  },
  outlineStyle: {
    borderRadius: 10,
    borderWidth: 1,
    justifyContent: 'center',
  },
});
kamilkedzierski commented 3 months ago

@JestemTrzcinska Hey! Just checking in—can we close this issue, or do you have any questions? 😊

JestemTrzcinska commented 2 months ago

@kamilkedzierski thanks for the workaround! any chance for the autofocus to work with modal in the future? you can close the issue ;)

anggaprytn commented 1 month ago

try this: setTimeout(() => textInputRef.current?.focus(), 100);

It worked for me.