Fix WindowsInsets for apps targeting SDK 35+
Summary
This change fixes the following issue for apps targeting SDK 35+ https://github.com/facebook/react-native/issues/49759
Technical details:
Before targeting SDK 35, using
android:windowSoftInputMode=”adjustResize”was all you needed to maintain focus on — for example — anEditTextin aRecyclerViewwhen opening an IME. With“adjustResize”, the framework treated the IME as the system window, and the window’s root views were padded so content avoids the system window.After targeting SDK 35, you must also account for the IME using
ViewCompat.setOnApplyWindowInsetsListenerandWindowInsetsCompat.Type.ime()because the framework will not pad the window’s root views.
source: https://medium.com/androiddevelopers/insets-handling-tips-for-android-15s-edge-to-edge-enforcement-872774e8839b
Test Plan
Reproducible project can be found here: https://github.com/dprevost-LMI/rn81/tree/issue-497590-KeyboardAvoidingView-hide-input-under-SDK35
Adjust SafeAreaView style by removing height and changing paddingBottom to 32.
Without the fix TextInput is hidden whenever a soft keyboard is shown on SDK 35+, after the fix TextInput is correctly placed on top of the keyboard.
| Keyboard hidden | Current behavior | Fix applied |
|---|---|---|
Reproducible screen (taken from
https://github.com/dprevost-LMI/rn81/tree/issue-497590-KeyboardAvoidingView-hide-input-under-SDK35 with adjustments to SafeAreaView bottom padding and height)
import { NewAppScreen } from '@react-native/new-app-screen';
import { KeyboardAvoidingView, StatusBar, StyleSheet, TextInput, useColorScheme, View } from 'react-native';
import {
SafeAreaProvider,
SafeAreaView,
useSafeAreaInsets,
} from 'react-native-safe-area-context';
function App() {
const isDarkMode = useColorScheme() === 'dark';
return (
<SafeAreaProvider>
<StatusBar barStyle={isDarkMode ? 'light-content' : 'dark-content'} />
<AppContent />
<SafeAreaView style={{ backgroundColor: isDarkMode ? '#000' : '#fff', paddingBottom:32 }} edges={['bottom']}>
<KeyboardAvoidingView behavior={'height'} >
<TextInput style={styles.textInput}/>
</KeyboardAvoidingView>
</SafeAreaView>
</SafeAreaProvider>
);
}
function AppContent() {
const safeAreaInsets = useSafeAreaInsets();
return (
<View style={styles.container}>
<NewAppScreen
templateFileName="App.tsx"
safeAreaInsets={safeAreaInsets}
/>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
},
textInput: {
flex: 1,
marginHorizontal: 8 * 1.3,
textAlignVertical: 'center',
borderRadius: 21,
backgroundColor: 'white',
paddingHorizontal: 8 * 2,
paddingVertical: 8,
paddingTop: 8,
minHeight: 8 * 5,
},
});
export default App;
FYI: I've submitted a similar PR long ago, which was rejected. See discussions below: #623
Okay, I can see what the maintainers' concerns are. I've added a comment to the original KeyboardAvoidingView issue summarizing the possible options to proceed with. I'll let the core RN team to handle it. Until then I assume we can keep this one open.