123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385 |
- /**
- * 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
- * @format
- */
- 'use strict';
- const Platform = require('../../Utilities/Platform');
- const React = require('react');
- const StatusBar = require('../StatusBar/StatusBar');
- const StyleSheet = require('../../StyleSheet/StyleSheet');
- const View = require('../View/View');
- const dismissKeyboard = require('../../Utilities/dismissKeyboard');
- const nullthrows = require('nullthrows');
- import AndroidDrawerLayoutNativeComponent, {
- Commands,
- } from './AndroidDrawerLayoutNativeComponent';
- const DRAWER_STATES = ['Idle', 'Dragging', 'Settling'];
- import type {ViewStyleProp} from '../../StyleSheet/StyleSheet';
- import type {ColorValue} from '../../StyleSheet/StyleSheetTypes';
- import type {DirectEventHandler} from '../../Types/CodegenTypes';
- import type {
- MeasureOnSuccessCallback,
- MeasureInWindowOnSuccessCallback,
- MeasureLayoutOnSuccessCallback,
- } from '../../Renderer/shims/ReactNativeTypes';
- type DrawerStates = 'Idle' | 'Dragging' | 'Settling';
- type DrawerSlideEvent = $ReadOnly<{|
- offset: number,
- |}>;
- type Props = $ReadOnly<{|
- /**
- * Determines whether the keyboard gets dismissed in response to a drag.
- * - 'none' (the default), drags do not dismiss the keyboard.
- * - 'on-drag', the keyboard is dismissed when a drag begins.
- */
- keyboardDismissMode?: ?('none' | 'on-drag'),
- /**
- * Specifies the background color of the drawer. The default value is white.
- * If you want to set the opacity of the drawer, use rgba. Example:
- *
- * ```
- * return (
- * <DrawerLayoutAndroid drawerBackgroundColor="rgba(0,0,0,0.5)">
- * </DrawerLayoutAndroid>
- * );
- * ```
- */
- drawerBackgroundColor: ColorValue,
- /**
- * Specifies the side of the screen from which the drawer will slide in.
- */
- drawerPosition: ?('left' | 'right'),
- /**
- * Specifies the width of the drawer, more precisely the width of the view that be pulled in
- * from the edge of the window.
- */
- drawerWidth?: ?number,
- /**
- * Specifies the lock mode of the drawer. The drawer can be locked in 3 states:
- * - unlocked (default), meaning that the drawer will respond (open/close) to touch gestures.
- * - locked-closed, meaning that the drawer will stay closed and not respond to gestures.
- * - locked-open, meaning that the drawer will stay opened and not respond to gestures.
- * The drawer may still be opened and closed programmatically (`openDrawer`/`closeDrawer`).
- */
- drawerLockMode?: ?('unlocked' | 'locked-closed' | 'locked-open'),
- /**
- * Function called whenever there is an interaction with the navigation view.
- */
- onDrawerSlide?: ?DirectEventHandler<DrawerSlideEvent>,
- /**
- * Function called when the drawer state has changed. The drawer can be in 3 states:
- * - Idle, meaning there is no interaction with the navigation view happening at the time
- * - Dragging, meaning there is currently an interaction with the navigation view
- * - Settling, meaning that there was an interaction with the navigation view, and the
- * navigation view is now finishing its closing or opening animation
- */
- onDrawerStateChanged?: ?(state: DrawerStates) => mixed,
- /**
- * Function called whenever the navigation view has been opened.
- */
- onDrawerOpen?: ?() => mixed,
- /**
- * Function called whenever the navigation view has been closed.
- */
- onDrawerClose?: ?() => mixed,
- /**
- * The navigation view that will be rendered to the side of the screen and can be pulled in.
- */
- renderNavigationView: () => React.Element<any>,
- /**
- * Make the drawer take the entire screen and draw the background of the
- * status bar to allow it to open over the status bar. It will only have an
- * effect on API 21+.
- */
- statusBarBackgroundColor?: ?ColorValue,
- children?: React.Node,
- style?: ?ViewStyleProp,
- |}>;
- type State = {|
- statusBarBackgroundColor: ColorValue,
- |};
- /**
- * React component that wraps the platform `DrawerLayout` (Android only). The
- * Drawer (typically used for navigation) is rendered with `renderNavigationView`
- * and direct children are the main view (where your content goes). The navigation
- * view is initially not visible on the screen, but can be pulled in from the
- * side of the window specified by the `drawerPosition` prop and its width can
- * be set by the `drawerWidth` prop.
- *
- * Example:
- *
- * ```
- * render: function() {
- * var navigationView = (
- * <View style={{flex: 1, backgroundColor: '#fff'}}>
- * <Text style={{margin: 10, fontSize: 15, textAlign: 'left'}}>I'm in the Drawer!</Text>
- * </View>
- * );
- * return (
- * <DrawerLayoutAndroid
- * drawerWidth={300}
- * drawerPosition="left"
- * renderNavigationView={() => navigationView}>
- * <View style={{flex: 1, alignItems: 'center'}}>
- * <Text style={{margin: 10, fontSize: 15, textAlign: 'right'}}>Hello</Text>
- * <Text style={{margin: 10, fontSize: 15, textAlign: 'right'}}>World!</Text>
- * </View>
- * </DrawerLayoutAndroid>
- * );
- * },
- * ```
- */
- class DrawerLayoutAndroid extends React.Component<Props, State> {
- static get positions(): mixed {
- console.warn(
- 'Setting DrawerLayoutAndroid drawerPosition using `DrawerLayoutAndroid.positions` is deprecated. Instead pass the string value "left" or "right"',
- );
- return {Left: 'left', Right: 'right'};
- }
- static defaultProps: {|
- drawerBackgroundColor: 'white',
- |} = {
- drawerBackgroundColor: 'white',
- };
- _nativeRef = React.createRef<
- React.ElementRef<typeof AndroidDrawerLayoutNativeComponent>,
- >();
- state: State = {statusBarBackgroundColor: null};
- render(): React.Node {
- const {
- onDrawerStateChanged,
- renderNavigationView,
- onDrawerOpen,
- onDrawerClose,
- ...props
- } = this.props;
- const drawStatusBar =
- Platform.Version >= 21 && this.props.statusBarBackgroundColor != null;
- const drawerViewWrapper = (
- <View
- style={[
- styles.drawerSubview,
- {
- width: this.props.drawerWidth,
- backgroundColor: this.props.drawerBackgroundColor,
- },
- ]}
- collapsable={false}>
- {renderNavigationView()}
- {drawStatusBar && <View style={styles.drawerStatusBar} />}
- </View>
- );
- const childrenWrapper = (
- <View style={styles.mainSubview} collapsable={false}>
- {drawStatusBar && (
- <StatusBar
- translucent
- backgroundColor={this.props.statusBarBackgroundColor}
- />
- )}
- {drawStatusBar && (
- <View
- style={[
- styles.statusBar,
- {backgroundColor: this.props.statusBarBackgroundColor},
- ]}
- />
- )}
- {this.props.children}
- </View>
- );
- return (
- <AndroidDrawerLayoutNativeComponent
- {...props}
- ref={this._nativeRef}
- drawerWidth={this.props.drawerWidth}
- drawerPosition={this.props.drawerPosition}
- drawerLockMode={this.props.drawerLockMode}
- style={[styles.base, this.props.style]}
- onDrawerSlide={this._onDrawerSlide}
- onDrawerOpen={this._onDrawerOpen}
- onDrawerClose={this._onDrawerClose}
- onDrawerStateChanged={this._onDrawerStateChanged}>
- {childrenWrapper}
- {drawerViewWrapper}
- </AndroidDrawerLayoutNativeComponent>
- );
- }
- _onDrawerSlide = event => {
- if (this.props.onDrawerSlide) {
- this.props.onDrawerSlide(event);
- }
- if (this.props.keyboardDismissMode === 'on-drag') {
- dismissKeyboard();
- }
- };
- _onDrawerOpen = () => {
- if (this.props.onDrawerOpen) {
- this.props.onDrawerOpen();
- }
- };
- _onDrawerClose = () => {
- if (this.props.onDrawerClose) {
- this.props.onDrawerClose();
- }
- };
- _onDrawerStateChanged = event => {
- if (this.props.onDrawerStateChanged) {
- this.props.onDrawerStateChanged(
- DRAWER_STATES[event.nativeEvent.drawerState],
- );
- }
- };
- /**
- * Opens the drawer.
- */
- openDrawer() {
- Commands.openDrawer(nullthrows(this._nativeRef.current));
- }
- /**
- * Closes the drawer.
- */
- closeDrawer() {
- Commands.closeDrawer(nullthrows(this._nativeRef.current));
- }
- /**
- * Closing and opening example
- * Note: To access the drawer you have to give it a ref
- *
- * Class component:
- *
- * render () {
- * this.openDrawer = () => {
- * this.refs.DRAWER.openDrawer()
- * }
- * this.closeDrawer = () => {
- * this.refs.DRAWER.closeDrawer()
- * }
- * return (
- * <DrawerLayoutAndroid ref={'DRAWER'}>
- * {children}
- * </DrawerLayoutAndroid>
- * )
- * }
- *
- * Function component:
- *
- * const drawerRef = useRef()
- * const openDrawer = () => {
- * drawerRef.current.openDrawer()
- * }
- * const closeDrawer = () => {
- * drawerRef.current.closeDrawer()
- * }
- * return (
- * <DrawerLayoutAndroid ref={drawerRef}>
- * {children}
- * </DrawerLayoutAndroid>
- * )
- */
- /**
- * Native methods
- */
- blur() {
- nullthrows(this._nativeRef.current).blur();
- }
- focus() {
- nullthrows(this._nativeRef.current).focus();
- }
- measure(callback: MeasureOnSuccessCallback) {
- nullthrows(this._nativeRef.current).measure(callback);
- }
- measureInWindow(callback: MeasureInWindowOnSuccessCallback) {
- nullthrows(this._nativeRef.current).measureInWindow(callback);
- }
- measureLayout(
- relativeToNativeNode: number,
- onSuccess: MeasureLayoutOnSuccessCallback,
- onFail?: () => void,
- ) {
- nullthrows(this._nativeRef.current).measureLayout(
- relativeToNativeNode,
- onSuccess,
- onFail,
- );
- }
- setNativeProps(nativeProps: Object) {
- nullthrows(this._nativeRef.current).setNativeProps(nativeProps);
- }
- }
- const styles = StyleSheet.create({
- base: {
- flex: 1,
- elevation: 16,
- },
- mainSubview: {
- position: 'absolute',
- top: 0,
- left: 0,
- right: 0,
- bottom: 0,
- },
- drawerSubview: {
- position: 'absolute',
- top: 0,
- bottom: 0,
- },
- statusBar: {
- height: StatusBar.currentHeight,
- },
- drawerStatusBar: {
- position: 'absolute',
- top: 0,
- left: 0,
- right: 0,
- height: StatusBar.currentHeight,
- backgroundColor: 'rgba(0, 0, 0, 0.251)',
- },
- });
- module.exports = DrawerLayoutAndroid;
|