Cross platform scrollable bottom sheet with virtualisation support and fully native animations, that integrates with all core scrollable components from React Native: FlatList, ScrollView and SectionList. Also, it's 100% compatible with Expo.
FlatList
and SectionList
components are 1st class citizens, as well as ScrollView
npm i react-native-scroll-bottom-sheet
yarn add react-native-scroll-bottom-sheet
If you don't use Expo, you also need to install react-native-gesture-handler and react-native-reanimated libraries along with this one.
It's recommended you install a version of gesture handler equal or higher than 1.6.0
, and for reanimated, equal or higher than 1.7.0
. Otherwise you may run into unexpected errors. This library is also compatible with reanimated 2.x, starting with react-native-reanimated: 2.0.0-alpha.4
.
The below is an example using the core FlatList
from React Native as the scrollable component.
import React from 'react';
import { Dimensions, StyleSheet, Text, View } from 'react-native';
import ScrollBottomSheet from 'react-native-scroll-bottom-sheet';
const windowHeight = Dimensions.get('window').height;
function Example() {
return (
<View style={styles.container}>
<ScrollBottomSheet<string> // If you are using TS, that'll infer the renderItem `item` type
componentType="FlatList"
snapPoints={[128, '50%', windowHeight - 200]}
initialSnapIndex={2}
renderHandle={() => (
<View style={styles.header}>
<View style={styles.panelHandle} />
</View>
)}
data={Array.from({ length: 200 }).map((_, i) => String(i))}
keyExtractor={i => i}
renderItem={({ item }) => (
<View style={styles.item}>
<Text>{`Item ${item}`}</Text>
</View>
)}
contentContainerStyle={styles.contentContainerStyle}
/>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
},
contentContainerStyle: {
padding: 16,
backgroundColor: '#F3F4F9',
},
header: {
alignItems: 'center',
backgroundColor: 'white',
paddingVertical: 20,
borderTopLeftRadius: 20,
borderTopRightRadius: 20
},
panelHandle: {
width: 40,
height: 2,
backgroundColor: 'rgba(0,0,0,0.3)',
borderRadius: 4
},
item: {
padding: 20,
justifyContent: 'center',
backgroundColor: 'white',
alignItems: 'center',
marginVertical: 10,
},
});
There are 2 types of props this component receives: explicit and inherited.
This is the list of exclusive props that are meant to be used to customise the bottom sheet behaviour.
Name | Required | Type | Description |
---|---|---|---|
componentType |
yes | string |
'FlatList', 'ScrollView', or 'SectionList' |
snapPoints |
yes | Array<string | number> |
Array of numbers and/or percentages that indicate the different resting positions of the bottom sheet (in dp or %), starting from the top. If a percentage is used, that would translate to the relative amount of the total window height. If you want that percentage to be calculated based on the parent available space instead, for example to account for safe areas or navigation bars, use it in combination with topInset prop |
initialSnapIndex |
yes | number |
Index that references the initial resting position of the drawer, starting from the top |
renderHandle |
yes | () => React.ReactNode |
Render prop for the handle, should return a React Element |
onSettle |
no | (index: number) => void |
Callback that is executed right after the bottom sheet settles in one of the snapping points. The new index is provided on the callback |
animationType |
no | string |
timing (default) or spring |
animationConfig |
no | TimingConfig or SpringConfig |
Timing or Spring configuration for the animation. If animationType is timing , it uses by default a timing configuration with a duration of 250ms and easing fn Easing.inOut(Easing.linear) . If animationType is spring , it uses this default spring configuration. You can partially override any parameter from the animation config as per your needs |
animatedPosition |
no | Animated.Value<number> |
Animated value that tracks the position of the drawer, being: 0 => closed, 1 => fully opened |
topInset |
no | number |
This value is useful to provide an offset (in dp) when applying percentages for snapping points |
innerRef |
no | RefObject |
Ref to the inner scrollable component (ScrollView, FlatList or SectionList), so that you can call its imperative methods. For instance, calling scrollTo on a ScrollView. In order to so, you have to use getNode as well, since it's wrapped into an animated component: ref.current.getNode().scrollTo({y: 0, animated: true}) |
containerStyle |
no | StyleProp<ViewStyle> |
Style to be applied to the container (Handle and Content) |
friction |
no | number |
Factor of resistance when the gesture is released. A value of 0 offers maximum * acceleration, whereas 1 acts as the opposite. Defaults to 0.95 |
enableOverScroll |
no | boolean |
Allow drawer to be dragged beyond lowest snap point |
Depending on the value of componentType
chosen, the bottom sheet component will inherit its underlying props, being one ofFlatListProps, ScrollViewProps or SectionListProps, so that you can tailor the scrollable content behaviour as per your needs.
snapTo(index)
Imperative method to snap to a specific index, i.e.
bottomSheetRef.current.snapTo(0)
bottomSheetRef
refers to the ref
passed to the ScrollBottomSheet
component.
You may add some touchable components inside the bottom sheet or several FlatList
widgets for horizontal mode. Unfortunately, not all interactable React Native components are compatible with this library. This is due to some limitations on react-native-gesture-handler
, which this library uses behind the scenes. For that, please follow this compatibility table:
Import | Touchable | Flatlist |
---|---|---|
react-native | iOS |
|
react-native-gesture-handler | Android | Android, iOS |
As you can see on the table, for any touchable component (TouchableOpacity
, TouchableHighlight
, ...) you need to have different imports depending on the platform. The below is a snippet you may find useful to abstract that into a component.
import React from "react";
import { Platform, TouchableOpacity } from "react-native";
import { TouchableOpacity as RNGHTouchableOpacity } from "react-native-gesture-handler";
const BottomSheetTouchable = (props) => {
if (Platform.OS === "android") {
return (
<RNGHTouchableOpacity {...props} />
);
}
return <TouchableOpacity {...props} />
};
export default BottomSheetTouchable;
For this mode to work properly, you have to import FlatList
from react-native-gesture-handler instead of react-native.
import { FlatList } from 'react-native-gesture-handler';
...
At the moment, the component does not support updating snap points via state, something you may want to achieve when changing device orientation for instance. A temporary workaround is to leverage React keys to force a re-mount of the component. This is some illustrative code to give you an idea how you could handle an orientation change with keys:
import { useDimensions } from '@react-native-community/hooks'
const useOrientation = () => {
const { width, height } = useDimensions().window;
if (height > width) {
return 'portrait'
}
return 'landscape'
}
const OrientationAwareBS = () => {
const orientation = useOrientation();
const snapPoints = {
portrait: [...],
landscape: [...]
}
return (
<ScrollBottomSheet
key={orientation}
componentType="FlatList"
snapPoints={snapPoints[orientation]}
initialSnapIndex={2}
...
/>
);
}
There is an Expo example application that you can play with to get a good grasp on the different customisation options. In case of Android, you can directly open the project here. For iOS, head to the example folder and run the project locally:
$ npm install
$ npm start
The library has been written in Typescript, so you'll get type checking and autocompletion if you use it as well.
MIT
react-native-bottom-sheet Android Bottom Sheet 的 React Native 实现。 Demo 如何安装(How to install) 首先安装 npm 包(Install package from npm first) npm install react-native-bottom-sheet --save link(current may not
本文向大家介绍react-native 启动React Native Packager,包括了react-native 启动React Native Packager的使用技巧和注意事项,需要的朋友参考一下 示例 在最新版本的React Native上,无需运行打包程序。它将自动运行。 默认情况下,这将在端口8081上启动服务器。要指定服务器所在的端口
百度移动统计SDK支持使用react native框架的H5页面统计,封装好的插件已经在github上开源,相关用法具体请参考:https://github.com/BaiduMobileAnalysis/baidumobstat-react-native。
The React Native environment has a lot of little quirks, so this documentation is aimed at helping smooth those over. Please feel free to create issues on GitHub for recommendations and additions to t
React Native 可以基于目前大热的开源JavaScript库React.js来开发iOS和Android原生App。而且React Native已经用于生产环境——Facebook Groups iOS 应用就是基于它开发的。 React Native的原理是在JavaScript中用React抽象操作系统原生的UI组件,代替DOM元素来渲染,比如以<View>取代<div>,以<Ima
本文向大家介绍react-native setState,包括了react-native setState的使用技巧和注意事项,需要的朋友参考一下 示例 要在应用程序中更改视图,可以使用setState-这将重新渲染您的组件及其任何子组件。setState在新状态和先前状态之间执行浅表合并,并触发组件的重新呈现。 setState 接受键值对象或返回键值对象的函数 键值对象 功能 使用函数对于基于