mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
6e903b07fa
Summary: Currently, ScrollViews provide the prop `keyboardDismissMode` which lets you choose `"interactive"`. However when the keyboard is shown, it will be rendered above the ScrollView, potentially blocking content. With the `automaticallyAdjustKeyboardInsets` prop the ScrollView will automatically adjust it's `contentInset`, `scrollIndicatorInsets` and `contentOffset` (scroll Y) props to push the content up so nothing gets blocked. * The animation curve and duration of the Keyboard is exactly matched. * The absolute position of the ScrollView is respected, so if the Keyboard only overlaps 10 pixels of the ScrollView, it will only get inset by 10 pixels. * By respecting the absolute position on screen, this automatically makes it fully compatible with phones with notches (custom safe areas) * By using the keyboard frame, this also works for different sized keyboards and even `<InputAccessoryView>`s * This also supports `maintainVisibleContentPosition` and `autoscrollToTopThreshold`. * I also fixed an issue with the `maintainVisibleContentPosition` (`autoscrollToTopThreshold`) prop(s), so they behave more reliably when `contentInset`s are applied. (This makes automatically scrolling to new items fully compatible with `automaticallyAdjustKeyboardInsets`) ## Changelog * [iOS] [Added] - ScrollView: `automaticallyAdjustKeyboardInsets` prop: Automatically animate `contentInset`, `scrollIndicatorInsets` and `contentOffset` (scroll Y) to avoid the Keyboard. (respecting absolute position on screen and safe-areas) * [iOS] [Fixed] - ScrollView: Respect `contentInset` when animating new items with `autoscrollToTopThreshold`, make `automaticallyAdjustKeyboardInsets` work with `autoscrollToTopThreshold` (includes vertical, vertical-inverted, horizontal and horizontal-inverted ScrollViews) Pull Request resolved: https://github.com/facebook/react-native/pull/31402 Test Plan: <table> <tr> <th>Before</th> <th>After</th> </tr> <tr> <td> https://user-images.githubusercontent.com/15199031/115708680-9700aa80-a370-11eb-8016-e75d81a92cd7.MP4 </td> <td> https://user-images.githubusercontent.com/15199031/115708699-9b2cc800-a370-11eb-976f-c4010cd96d55.MP4 </td> </table> ### "Why not just use `<KeyboardAvoidingView>`?" <table> <tr> <th>Before (with <code><KeyboardAvoidingView></code>)</th> <th>After (with <code>automaticallyAdjustKeyboardInsets</code>)</th> </tr> <tr> <td> https://user-images.githubusercontent.com/15199031/115708749-abdd3e00-a370-11eb-8e09-a27ffaef12b8.MP4 </td> <td> https://user-images.githubusercontent.com/15199031/115708777-b3044c00-a370-11eb-9b7a-e040ccb3ef8c.MP4 </td> </table> > Also notice how the `<KeyboardAvoidingView>` does not match the animation curve of the Keyboard ### Usage ```jsx export const ChatPage = ({ flatListProps, textInputProps }: Props): React.ReactElement => ( <> <FlatList {...flatListProps} keyboardDismissMode="interactive" automaticallyAdjustContentInsets={false} contentInsetAdjustmentBehavior="never" maintainVisibleContentPosition={{ minIndexForVisible: 0, autoscrollToTopThreshold: 100 }} automaticallyAdjustKeyboardInsets={true} /> <InputAccessoryView backgroundColor={colors.white}> <ChatInput {...textInputProps} /> </InputAccessoryView> </> ); ``` ## Related Issues * Fixes https://github.com/facebook/react-native/issues/31394 * Fixes https://github.com/facebook/react-native/issues/13073 Reviewed By: yungsters Differential Revision: D30015799 Pulled By: sota000 fbshipit-source-id: 9ccfb4b6d477da192a96db4cfa07c31a2d2cefcb
85 lines
2.3 KiB
JavaScript
85 lines
2.3 KiB
JavaScript
/**
|
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
*
|
|
* This source code is licensed under the MIT license found in the
|
|
* LICENSE file in the root directory of this source tree.
|
|
*
|
|
* @flow strict-local
|
|
* @format
|
|
*/
|
|
|
|
'use strict';
|
|
|
|
import type {PartialViewConfig} from '../../Renderer/shims/ReactNativeTypes';
|
|
|
|
const ScrollViewViewConfig = {
|
|
uiViewClassName: 'RCTScrollView',
|
|
bubblingEventTypes: {},
|
|
directEventTypes: {
|
|
topScrollToTop: {
|
|
registrationName: 'onScrollToTop',
|
|
},
|
|
},
|
|
validAttributes: {
|
|
alwaysBounceHorizontal: true,
|
|
alwaysBounceVertical: true,
|
|
automaticallyAdjustContentInsets: true,
|
|
automaticallyAdjustKeyboardInsets: true,
|
|
automaticallyAdjustsScrollIndicatorInsets: true,
|
|
bounces: true,
|
|
bouncesZoom: true,
|
|
canCancelContentTouches: true,
|
|
centerContent: true,
|
|
contentInset: {
|
|
diff: require('../../Utilities/differ/pointsDiffer'),
|
|
},
|
|
contentOffset: {
|
|
diff: require('../../Utilities/differ/pointsDiffer'),
|
|
},
|
|
contentInsetAdjustmentBehavior: true,
|
|
decelerationRate: true,
|
|
directionalLockEnabled: true,
|
|
disableIntervalMomentum: true,
|
|
endFillColor: {
|
|
process: require('../../StyleSheet/processColor'),
|
|
},
|
|
fadingEdgeLength: true,
|
|
indicatorStyle: true,
|
|
inverted: true,
|
|
keyboardDismissMode: true,
|
|
maintainVisibleContentPosition: true,
|
|
maximumZoomScale: true,
|
|
minimumZoomScale: true,
|
|
nestedScrollEnabled: true,
|
|
onMomentumScrollBegin: true,
|
|
onMomentumScrollEnd: true,
|
|
onScroll: true,
|
|
onScrollBeginDrag: true,
|
|
onScrollEndDrag: true,
|
|
onScrollToTop: true,
|
|
overScrollMode: true,
|
|
pagingEnabled: true,
|
|
persistentScrollbar: true,
|
|
pinchGestureEnabled: true,
|
|
scrollEnabled: true,
|
|
scrollEventThrottle: true,
|
|
scrollIndicatorInsets: {
|
|
diff: require('../../Utilities/differ/pointsDiffer'),
|
|
},
|
|
scrollPerfTag: true,
|
|
scrollToOverflowEnabled: true,
|
|
scrollsToTop: true,
|
|
sendMomentumEvents: true,
|
|
showsHorizontalScrollIndicator: true,
|
|
showsVerticalScrollIndicator: true,
|
|
snapToAlignment: true,
|
|
snapToEnd: true,
|
|
snapToInterval: true,
|
|
snapToOffsets: true,
|
|
snapToStart: true,
|
|
zoomScale: true,
|
|
},
|
|
};
|
|
|
|
module.exports = (ScrollViewViewConfig: PartialViewConfig);
|