react-native icon indicating copy to clipboard operation
react-native copied to clipboard

KeyboardAvoidingView Layout Shift On Next Input Focus

Open deviled opened this issue 3 years ago • 3 comments

Description

KeyboardAvoidingView is causing a layout shift when focusing the next input on the screen. I have noticed it happens when the view content is vertically aligned in the center.

blurOnSubmit={false} is not helping to solve this problem. Also, I have reproduced it with TextInput from react-native.

import { useRef } from 'react';
import { View, KeyboardAvoidingView, StyleSheet } from 'react-native';

import { TextInput } from 'react-native-paper';

export default function App() {
  const passwordRef = useRef(null);
  return (
    <KeyboardAvoidingView style={styles.container} behavior="padding">
      <View style={styles.wrapper}>
        <TextInput
          style={styles.input}
          placeholder="Email"
          returnKeyType="next"
          onSubmitEditing={() => {
              passwordRef?.current?.focus();
          }}
          blurOnSubmit={false}
        />
        <TextInput 
          ref={passwordRef}
          style={styles.input}
          placeholder="Password"
          returnKeyType="done"
          textContentType="password"
        />
      </View>
    </KeyboardAvoidingView>
  );
}

const styles = StyleSheet.create({
  wrapper: {
    width: 340,
    height: 140,
  },
  input: {
    flex: 1,
    width: '100%',
  },  
  container: {
    flex: 1,
    padding: 20,
    width: '100%',
    maxWidth: 340,
    alignSelf: 'center',
    alignItems: 'center',
    justifyContent: 'center',
  }
});

Version

0.70.6

Output of npx react-native info

System: OS: macOS 13.1 CPU: (12) x64 Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz Memory: 634.14 MB / 16.00 GB Shell: 5.8.1 - /bin/zsh Binaries: Node: 16.14.2 - /usr/local/bin/node Yarn: 1.22.11 - /usr/local/bin/yarn npm: 8.5.0 - /usr/local/bin/npm Watchman: 2023.01.02.00 - /usr/local/bin/watchman Managers: CocoaPods: 1.11.3 - /Users/deviled/.rvm/gems/ruby-2.7.5/bin/pod SDKs: iOS SDK: Platforms: DriverKit 22.2, iOS 16.2, macOS 13.1, tvOS 16.1, watchOS 9.1 Android SDK: Not Found IDEs: Android Studio: Not Found Xcode: 14.2/14C18 - /usr/bin/xcodebuild Languages: Java: Not Found npmPackages: @react-native-community/cli: Not Found react: 18.1.0 => 18.1.0 react-native: 0.70.6 => 0.70.6 react-native-macos: Not Found npmGlobalPackages: react-native: Not Found

Steps to reproduce

  1. Focus first input Email.
  2. Click 'next' button on iOS keyboard to focus next input Password.

Snack, code example, screenshot, or link to a repository

https://snack.expo.dev/@deviled/fascinated-milkshake

https://user-images.githubusercontent.com/22294450/211523130-630b948a-c24c-44cb-a437-7af137369848.MP4

deviled avatar Jan 10 '23 10:01 deviled

Yes I am having the same issue

jaydwevidi avatar Jan 11 '23 05:01 jaydwevidi

I've noticed that the keyboardDidShow event happens two times before the keyboard is shown and the event.endCoordinates.height is different each time.

image

deviled avatar Jan 11 '23 17:01 deviled

I've found a temporary solution here that works for majority of cases. https://gist.github.com/deviled/4e403a892e4ee57db8f923b46ed3b4f6

The idea is to filter out the events that have event.startCoordinates.height larger than event.endCoordinates.height.

_onKeyboardChange = (event: KeyboardEvent) => {
    if (
        event.startCoordinates &&
        event.startCoordinates.height > event.endCoordinates.height
    ) {
        return null;
    }
    this._keyboardEvent = event;
    this._updateBottomIfNecessary();
};

deviled avatar Jan 11 '23 21:01 deviled

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[bot] avatar Jul 11 '23 05:07 github-actions[bot]

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

github-actions[bot] avatar Jul 18 '23 05:07 github-actions[bot]