diff --git a/README.md b/README.md index e1b3889..e0c11c7 100644 --- a/README.md +++ b/README.md @@ -203,6 +203,8 @@ const HiddenItemWrappedTwice = ()=> This is a React context provider needed for `overflowMenuPressHandlerDropdownMenu` to work. If you're not using `overflowMenuPressHandlerDropdownMenu` then you don't need it. By default, you need to wrap your root component with it. +On Android, `OverflowMenuProvider` accepts an optional `spaceAboveMenu` prop, which can be used to set the distance between the top of the screen and the top of the overflow menu. + #### `HeaderButton` You will typically not use `HeaderButton` directly. `HeaderButton` is where all the `onPress`, `title` and Icon-related props meet to render actual button. diff --git a/index.d.ts b/index.d.ts index aed792f..b17c4a7 100644 --- a/index.d.ts +++ b/index.d.ts @@ -95,6 +95,7 @@ declare class Divider extends Component<{ declare class OverflowMenuProvider extends Component<{ children: ReactChild; + spaceAboveMenu?: number; }> {} export interface OnOverflowMenuPressParams { diff --git a/src/overflowMenu/OverflowMenuContext.js b/src/overflowMenu/OverflowMenuContext.js index 234e55c..83beeee 100644 --- a/src/overflowMenu/OverflowMenuContext.js +++ b/src/overflowMenu/OverflowMenuContext.js @@ -1,8 +1,8 @@ // @flow import * as React from 'react'; import { Dimensions, Platform } from 'react-native'; +import { getDefaultSpaceAboveMenu } from './statusBarUtils'; import { Menu } from './vendor/Menu'; -import { getSpaceAboveMenu } from './statusBarUtils'; export type ToggleMenuParam = ?{| elements: React.ChildrenArray, @@ -24,9 +24,10 @@ export const OverflowMenuContext = React.createContext<(ToggleMenuParam) => void type Props = {| children: React.Element, + spaceAboveMenu?: number, |}; -export const OverflowMenuProvider = ({ children }: Props) => { +export const OverflowMenuProvider = ({ children, spaceAboveMenu }: Props) => { const [visible, setVisible] = React.useState(false); const [position, setPosition] = React.useState({ x: Dimensions.get('window').width - 10, y: 40 }); const [elements, setElements] = React.useState(null); @@ -35,19 +36,22 @@ export const OverflowMenuProvider = ({ children }: Props) => { setVisible(false); }, []); - const toggleMenu = React.useCallback((params: ToggleMenuParam) => { - setVisible((prevVisible) => !prevVisible); - setElements(params?.elements || []); - if (params) { - const { x, y } = params; - const heightApprox = getSpaceAboveMenu(); - const extraDelta = Platform.select({ - android: heightApprox, - default: OVERFLOW_TOP, - }); - setPosition({ x, y: y + extraDelta }); - } - }, []); + const toggleMenu = React.useCallback( + (params: ToggleMenuParam) => { + setVisible((prevVisible) => !prevVisible); + setElements(params?.elements || []); + if (params) { + const { x, y } = params; + const heightApprox = spaceAboveMenu ?? getDefaultSpaceAboveMenu(); + const extraDelta = Platform.select({ + android: heightApprox, + default: OVERFLOW_TOP, + }); + setPosition({ x, y: y + extraDelta }); + } + }, + [spaceAboveMenu] + ); return ( diff --git a/src/overflowMenu/statusBarUtils.expo.js b/src/overflowMenu/statusBarUtils.expo.js index 768eedb..3a69f93 100644 --- a/src/overflowMenu/statusBarUtils.expo.js +++ b/src/overflowMenu/statusBarUtils.expo.js @@ -1,6 +1,6 @@ import { StatusBar } from 'react-native'; -export const getSpaceAboveMenu = () => { +export const getDefaultSpaceAboveMenu = () => { // approximation, expo draws views right from below the display edge // which is a different behavior from vanilla RN return StatusBar.currentHeight + 3; diff --git a/src/overflowMenu/statusBarUtils.js b/src/overflowMenu/statusBarUtils.js index c83dd66..bbc2701 100644 --- a/src/overflowMenu/statusBarUtils.js +++ b/src/overflowMenu/statusBarUtils.js @@ -1,3 +1,3 @@ -export const getSpaceAboveMenu = () => { +export const getDefaultSpaceAboveMenu = () => { return 0; };