mirror of
https://github.com/zhigang1992/react-navigation.git
synced 2026-02-10 22:47:02 +08:00
wip
This commit is contained in:
@@ -1,31 +0,0 @@
|
||||
/* @flow */
|
||||
/* eslint-disable import/no-commonjs */
|
||||
|
||||
module.exports = {
|
||||
/**
|
||||
* Navigators
|
||||
*/
|
||||
get createBottomTabNavigator() {
|
||||
return require('./navigators/createBottomTabNavigator').default;
|
||||
},
|
||||
get createMaterialTopTabNavigator() {
|
||||
return require('./navigators/createMaterialTopTabNavigator').default;
|
||||
},
|
||||
|
||||
/**
|
||||
* Views
|
||||
*/
|
||||
get BottomTabBar() {
|
||||
return require('./views/BottomTabBar').default;
|
||||
},
|
||||
get MaterialTopTabBar() {
|
||||
return require('./views/MaterialTopTabBar').default;
|
||||
},
|
||||
|
||||
/**
|
||||
* Utils
|
||||
*/
|
||||
get createTabNavigator() {
|
||||
return require('./utils/createTabNavigator').default;
|
||||
},
|
||||
};
|
||||
20
packages/bottom-tabs/src/index.tsx
Normal file
20
packages/bottom-tabs/src/index.tsx
Normal file
@@ -0,0 +1,20 @@
|
||||
/**
|
||||
* Navigators
|
||||
*/
|
||||
export {
|
||||
default as createBottomTabNavigator,
|
||||
} from './navigators/createBottomTabNavigator';
|
||||
export {
|
||||
default as createMaterialTopTabNavigator,
|
||||
} from './navigators/createMaterialTopTabNavigator';
|
||||
|
||||
/**
|
||||
* Views
|
||||
*/
|
||||
export { default as BottomTabBar } from './views/BottomTabBar';
|
||||
export { default as MaterialTopTabBar } from './views/MaterialTopTabBar';
|
||||
|
||||
/**
|
||||
* Utils
|
||||
*/
|
||||
export { default as createTabNavigator } from './utils/createTabNavigator';
|
||||
@@ -1,5 +1,3 @@
|
||||
/* @flow */
|
||||
|
||||
import * as React from 'react';
|
||||
import { View, StyleSheet } from 'react-native';
|
||||
|
||||
@@ -7,31 +5,36 @@ import { View, StyleSheet } from 'react-native';
|
||||
import { ScreenContainer } from 'react-native-screens';
|
||||
|
||||
import createTabNavigator, {
|
||||
type InjectedProps,
|
||||
NavigationViewProps,
|
||||
} from '../utils/createTabNavigator';
|
||||
import BottomTabBar, { type TabBarOptions } from '../views/BottomTabBar';
|
||||
import BottomTabBar, { TabBarOptions } from '../views/BottomTabBar';
|
||||
import ResourceSavingScene from '../views/ResourceSavingScene';
|
||||
import { NavigationProp, Route, SceneDescriptor } from '../types';
|
||||
|
||||
type Props = InjectedProps & {
|
||||
getAccessibilityRole: (props: { route: any }) => string,
|
||||
getAccessibilityStates: (props: { route: any }) => string[],
|
||||
lazy?: boolean,
|
||||
tabBarComponent?: React.ComponentType<*>,
|
||||
tabBarOptions?: TabBarOptions,
|
||||
type Props = NavigationViewProps & {
|
||||
getAccessibilityRole: (props: { route: any }) => string;
|
||||
getAccessibilityStates: (props: { route: any }) => string[];
|
||||
lazy?: boolean;
|
||||
tabBarComponent?: React.ComponentType<any>;
|
||||
tabBarOptions?: TabBarOptions;
|
||||
navigation: NavigationProp;
|
||||
descriptors: { [key: string]: SceneDescriptor };
|
||||
screenProps?: unknown;
|
||||
};
|
||||
|
||||
type State = {
|
||||
loaded: number[],
|
||||
loaded: number[];
|
||||
};
|
||||
|
||||
class TabNavigationView extends React.PureComponent<Props, State> {
|
||||
static defaultProps = {
|
||||
lazy: true,
|
||||
getAccessibilityRole: () => 'button',
|
||||
getAccessibilityStates: ({ focused }) => (focused ? ['selected'] : []),
|
||||
getAccessibilityStates: ({ focused }: { focused: boolean }) =>
|
||||
focused ? ['selected'] : [],
|
||||
};
|
||||
|
||||
static getDerivedStateFromProps(nextProps, prevState) {
|
||||
static getDerivedStateFromProps(nextProps: Props, prevState: State) {
|
||||
const { index } = nextProps.navigation.state;
|
||||
|
||||
return {
|
||||
@@ -46,7 +49,7 @@ class TabNavigationView extends React.PureComponent<Props, State> {
|
||||
loaded: [this.props.navigation.state.index],
|
||||
};
|
||||
|
||||
_getButtonComponent = ({ route }) => {
|
||||
_getButtonComponent = ({ route }: { route: Route }) => {
|
||||
const { descriptors } = this.props;
|
||||
const descriptor = descriptors[route.key];
|
||||
const options = descriptor.options;
|
||||
@@ -55,7 +58,7 @@ class TabNavigationView extends React.PureComponent<Props, State> {
|
||||
return options.tabBarButtonComponent;
|
||||
}
|
||||
|
||||
return null;
|
||||
return undefined;
|
||||
};
|
||||
|
||||
_renderTabBar = () => {
|
||||
@@ -1,138 +0,0 @@
|
||||
/* @flow */
|
||||
|
||||
import * as React from 'react';
|
||||
import { TabView } from 'react-native-tab-view';
|
||||
import type { ViewStyleProp } from 'react-native/Libraries/StyleSheet/StyleSheet';
|
||||
import createTabNavigator, {
|
||||
type InjectedProps,
|
||||
} from '../utils/createTabNavigator';
|
||||
import MaterialTopTabBar, {
|
||||
type TabBarOptions,
|
||||
} from '../views/MaterialTopTabBar';
|
||||
|
||||
type Route = {
|
||||
key: string,
|
||||
routeName: string,
|
||||
};
|
||||
|
||||
type Props = {|
|
||||
...InjectedProps,
|
||||
keyboardDismissMode?: 'none' | 'on-drag',
|
||||
swipeEnabled?: boolean,
|
||||
swipeDistanceThreshold?: number,
|
||||
swipeVelocityThreshold?: number,
|
||||
onSwipeStart?: () => mixed,
|
||||
onSwipeEnd?: () => mixed,
|
||||
initialLayout?: { width?: number, height?: number },
|
||||
lazy?: boolean,
|
||||
lazyPlaceholderComponent?: React.ComponentType<{ route: Route }>,
|
||||
tabBarComponent?: React.ComponentType<*>,
|
||||
tabBarOptions?: TabBarOptions,
|
||||
tabBarPosition?: 'top' | 'bottom',
|
||||
sceneContainerStyle?: ViewStyleProp,
|
||||
style?: ViewStyleProp,
|
||||
|};
|
||||
|
||||
class MaterialTabView extends React.PureComponent<Props> {
|
||||
_renderLazyPlaceholder = props => {
|
||||
const { lazyPlaceholderComponent: LazyPlaceholder } = this.props;
|
||||
|
||||
if (LazyPlaceholder != null) {
|
||||
return <LazyPlaceholder {...props} />;
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
_renderTabBar = props => {
|
||||
const { state } = this.props.navigation;
|
||||
const route = state.routes[state.index];
|
||||
const { descriptors } = this.props;
|
||||
const descriptor = descriptors[route.key];
|
||||
const options = descriptor.options;
|
||||
|
||||
const tabBarVisible =
|
||||
options.tabBarVisible == null ? true : options.tabBarVisible;
|
||||
|
||||
const {
|
||||
navigation,
|
||||
getLabelText,
|
||||
getAccessibilityLabel,
|
||||
getTestID,
|
||||
renderIcon,
|
||||
onTabPress,
|
||||
onTabLongPress,
|
||||
tabBarComponent: TabBarComponent = MaterialTopTabBar,
|
||||
tabBarPosition,
|
||||
tabBarOptions,
|
||||
screenProps,
|
||||
} = this.props;
|
||||
|
||||
if (TabBarComponent === null || !tabBarVisible) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<TabBarComponent
|
||||
{...tabBarOptions}
|
||||
{...props}
|
||||
tabBarPosition={tabBarPosition}
|
||||
screenProps={screenProps}
|
||||
navigation={navigation}
|
||||
getLabelText={getLabelText}
|
||||
getAccessibilityLabel={getAccessibilityLabel}
|
||||
getTestID={getTestID}
|
||||
renderIcon={renderIcon}
|
||||
onTabPress={onTabPress}
|
||||
onTabLongPress={onTabLongPress}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
render() {
|
||||
const {
|
||||
/* eslint-disable no-unused-vars */
|
||||
getLabelText,
|
||||
getAccessibilityLabel,
|
||||
getTestID,
|
||||
renderIcon,
|
||||
onTabPress,
|
||||
onTabLongPress,
|
||||
screenProps,
|
||||
lazyPlaceholderComponent,
|
||||
tabBarComponent,
|
||||
tabBarOptions,
|
||||
/* eslint-enable no-unused-vars */
|
||||
navigation,
|
||||
descriptors,
|
||||
...rest
|
||||
} = this.props;
|
||||
|
||||
const { state } = navigation;
|
||||
const route = state.routes[state.index];
|
||||
|
||||
const descriptor = descriptors[route.key];
|
||||
const options = descriptor.options;
|
||||
|
||||
let swipeEnabled =
|
||||
options.swipeEnabled == null
|
||||
? this.props.swipeEnabled
|
||||
: options.swipeEnabled;
|
||||
|
||||
if (typeof swipeEnabled === 'function') {
|
||||
swipeEnabled = swipeEnabled(state);
|
||||
}
|
||||
|
||||
return (
|
||||
<TabView
|
||||
{...rest}
|
||||
navigationState={navigation.state}
|
||||
swipeEnabled={swipeEnabled}
|
||||
renderTabBar={this._renderTabBar}
|
||||
renderLazyPlaceholder={this._renderLazyPlaceholder}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default createTabNavigator(MaterialTabView);
|
||||
@@ -38,6 +38,7 @@ export type NavigationProp<RouteName = string, Params = object> = {
|
||||
|
||||
export type NavigationTabOptions = {
|
||||
title?: string;
|
||||
tabBarVisible?: boolean;
|
||||
tabBarLabel?: React.ReactNode;
|
||||
tabBarIcon?:
|
||||
| React.ReactNode
|
||||
@@ -56,6 +57,7 @@ export type NavigationTabOptions = {
|
||||
defaultHandler: () => void;
|
||||
}) => void;
|
||||
tabBarAccessibilityLabel?: string;
|
||||
tabBarButtonComponent?: React.ComponentType<any>;
|
||||
};
|
||||
|
||||
export type SceneDescriptor = {
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
/* @flow */
|
||||
|
||||
import React from 'react';
|
||||
import {
|
||||
Animated,
|
||||
@@ -8,11 +6,18 @@ import {
|
||||
View,
|
||||
Keyboard,
|
||||
Platform,
|
||||
StyleProp,
|
||||
TextStyle,
|
||||
ViewStyle,
|
||||
LayoutChangeEvent,
|
||||
AccessibilityRole,
|
||||
AccessibilityState,
|
||||
} from 'react-native';
|
||||
import { SafeAreaView } from '@react-navigation/native';
|
||||
import SafeAreaView from 'react-native-safe-area-view';
|
||||
|
||||
import CrossFadeIcon from './CrossFadeIcon';
|
||||
import withDimensions from '../utils/withDimensions';
|
||||
import { Route, NavigationProp } from '../types';
|
||||
|
||||
type Orientation = 'horizontal' | 'vertical';
|
||||
type Position = 'beside-icon' | 'below-icon';
|
||||
@@ -21,50 +26,70 @@ type LabelPosition =
|
||||
| ((options: { deviceOrientation: Orientation }) => Position);
|
||||
|
||||
export type TabBarOptions = {
|
||||
keyboardHidesTabBar: boolean,
|
||||
activeTintColor?: string,
|
||||
inactiveTintColor?: string,
|
||||
activeBackgroundColor?: string,
|
||||
inactiveBackgroundColor?: string,
|
||||
allowFontScaling: boolean,
|
||||
showLabel: boolean,
|
||||
showIcon: boolean,
|
||||
labelStyle: any,
|
||||
tabStyle: any,
|
||||
labelPosition?: LabelPosition,
|
||||
adaptive?: boolean,
|
||||
style: any,
|
||||
keyboardHidesTabBar: boolean;
|
||||
activeTintColor?: string;
|
||||
inactiveTintColor?: string;
|
||||
activeBackgroundColor?: string;
|
||||
inactiveBackgroundColor?: string;
|
||||
allowFontScaling: boolean;
|
||||
showLabel: boolean;
|
||||
showIcon: boolean;
|
||||
labelStyle: StyleProp<TextStyle>;
|
||||
tabStyle: StyleProp<ViewStyle>;
|
||||
labelPosition?: LabelPosition;
|
||||
adaptive?: boolean;
|
||||
style: StyleProp<ViewStyle>;
|
||||
};
|
||||
|
||||
type Props = TabBarOptions & {
|
||||
navigation: any,
|
||||
onTabPress: any,
|
||||
onTabLongPress: any,
|
||||
getAccessibilityLabel: (props: { route: any }) => string,
|
||||
getAccessibilityRole: (props: { route: any }) => string,
|
||||
getAccessibilityStates: (props: { route: any }) => string[],
|
||||
getButtonComponent: ({ route: any }) => any,
|
||||
getLabelText: ({ route: any }) => any,
|
||||
getTestID: (props: { route: any }) => string,
|
||||
renderIcon: any,
|
||||
dimensions: { width: number, height: number },
|
||||
isLandscape: boolean,
|
||||
safeAreaInset: { top: string, right: string, bottom: string, left: string },
|
||||
navigation: NavigationProp;
|
||||
onTabPress: (props: { route: Route }) => void;
|
||||
onTabLongPress: (props: { route: Route }) => void;
|
||||
getAccessibilityLabel: (props: { route: Route }) => string | undefined;
|
||||
getAccessibilityRole: (props: {
|
||||
route: Route;
|
||||
}) => AccessibilityRole | undefined;
|
||||
getAccessibilityStates: (props: { route: Route }) => AccessibilityState[];
|
||||
getButtonComponent: (props: {
|
||||
route: Route;
|
||||
}) => React.ComponentType<any> | undefined;
|
||||
getLabelText: (props: {
|
||||
route: Route;
|
||||
}) =>
|
||||
| ((scene: {
|
||||
focused: boolean;
|
||||
tintColor?: string;
|
||||
orientation: 'horizontal' | 'vertical';
|
||||
}) => React.ReactNode)
|
||||
| string
|
||||
| undefined;
|
||||
getTestID: (props: { route: Route }) => string;
|
||||
renderIcon: (props: {
|
||||
route: Route;
|
||||
focused: boolean;
|
||||
tintColor?: string;
|
||||
horizontal?: boolean;
|
||||
}) => React.ReactNode;
|
||||
dimensions: { width: number; height: number };
|
||||
isLandscape: boolean;
|
||||
safeAreaInset: React.ComponentProps<typeof SafeAreaView>['forceInset'];
|
||||
};
|
||||
|
||||
type State = {
|
||||
layout: { height: number, width: number },
|
||||
keyboard: boolean,
|
||||
visible: Animated.Value,
|
||||
layout: { height: number; width: number };
|
||||
keyboard: boolean;
|
||||
visible: Animated.Value;
|
||||
};
|
||||
|
||||
const majorVersion = parseInt(Platform.Version, 10);
|
||||
const majorVersion = parseInt(Platform.Version as string, 10);
|
||||
const isIos = Platform.OS === 'ios';
|
||||
const isIOS11 = majorVersion >= 11 && isIos;
|
||||
|
||||
const DEFAULT_MAX_TAB_ITEM_WIDTH = 125;
|
||||
|
||||
class TouchableWithoutFeedbackWrapper extends React.Component<*> {
|
||||
class TouchableWithoutFeedbackWrapper extends React.Component<
|
||||
React.ComponentProps<typeof TouchableWithoutFeedback>
|
||||
> {
|
||||
render() {
|
||||
const {
|
||||
onPress,
|
||||
@@ -103,7 +128,9 @@ class TabBarBottom extends React.Component<Props, State> {
|
||||
showIcon: true,
|
||||
allowFontScaling: true,
|
||||
adaptive: isIOS11,
|
||||
safeAreaInset: { bottom: 'always', top: 'never' },
|
||||
safeAreaInset: { bottom: 'always', top: 'never' } as React.ComponentProps<
|
||||
typeof SafeAreaView
|
||||
>['forceInset'],
|
||||
};
|
||||
|
||||
state = {
|
||||
@@ -150,7 +177,7 @@ class TabBarBottom extends React.Component<Props, State> {
|
||||
this.setState({ keyboard: false });
|
||||
});
|
||||
|
||||
_handleLayout = e => {
|
||||
_handleLayout = (e: LayoutChangeEvent) => {
|
||||
const { layout } = this.state;
|
||||
const { height, width } = e.nativeEvent.layout;
|
||||
|
||||
@@ -166,7 +193,7 @@ class TabBarBottom extends React.Component<Props, State> {
|
||||
});
|
||||
};
|
||||
|
||||
_renderLabel = ({ route, focused }) => {
|
||||
_renderLabel = ({ route, focused }: { route: Route; focused: boolean }) => {
|
||||
const {
|
||||
activeTintColor,
|
||||
inactiveTintColor,
|
||||
@@ -203,7 +230,6 @@ class TabBarBottom extends React.Component<Props, State> {
|
||||
|
||||
if (typeof label === 'function') {
|
||||
return label({
|
||||
route,
|
||||
focused,
|
||||
tintColor,
|
||||
orientation: horizontal ? 'horizontal' : 'vertical',
|
||||
@@ -213,9 +239,8 @@ class TabBarBottom extends React.Component<Props, State> {
|
||||
return label;
|
||||
};
|
||||
|
||||
_renderIcon = ({ route, focused }) => {
|
||||
_renderIcon = ({ route, focused }: { route: Route; focused: boolean }) => {
|
||||
const {
|
||||
navigation,
|
||||
activeTintColor,
|
||||
inactiveTintColor,
|
||||
renderIcon,
|
||||
@@ -235,7 +260,6 @@ class TabBarBottom extends React.Component<Props, State> {
|
||||
<CrossFadeIcon
|
||||
route={route}
|
||||
horizontal={horizontal}
|
||||
navigation={navigation}
|
||||
activeOpacity={activeOpacity}
|
||||
inactiveOpacity={inactiveOpacity}
|
||||
activeTintColor={activeTintColor}
|
||||
@@ -279,6 +303,7 @@ class TabBarBottom extends React.Component<Props, State> {
|
||||
return false;
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
if (Platform.isPad) {
|
||||
let maxTabItemWidth = DEFAULT_MAX_TAB_ITEM_WIDTH;
|
||||
|
||||
@@ -315,6 +340,7 @@ class TabBarBottom extends React.Component<Props, State> {
|
||||
|
||||
const tabBarStyle = [
|
||||
styles.tabBar,
|
||||
// @ts-ignore
|
||||
this._shouldUseHorizontalLabels() && !Platform.isPad
|
||||
? styles.tabBarCompact
|
||||
: styles.tabBarRegular,
|
||||
@@ -444,6 +470,7 @@ const styles = StyleSheet.create({
|
||||
flex: 1,
|
||||
},
|
||||
iconWithExplicitHeight: {
|
||||
// @ts-ignore
|
||||
height: Platform.isPad ? DEFAULT_HEIGHT : COMPACT_HEIGHT,
|
||||
},
|
||||
label: {
|
||||
@@ -1,70 +0,0 @@
|
||||
/* @flow */
|
||||
|
||||
import React from 'react';
|
||||
import { View, StyleSheet } from 'react-native';
|
||||
import Animated from 'react-native-reanimated';
|
||||
|
||||
type Props = {
|
||||
route: any,
|
||||
horizontal?: boolean,
|
||||
activeOpacity: any,
|
||||
inactiveOpacity: any,
|
||||
activeTintColor: any,
|
||||
inactiveTintColor: any,
|
||||
renderIcon: any,
|
||||
style: any,
|
||||
};
|
||||
|
||||
export default class TabBarIcon extends React.Component<Props> {
|
||||
render() {
|
||||
const {
|
||||
route,
|
||||
activeOpacity,
|
||||
inactiveOpacity,
|
||||
activeTintColor,
|
||||
inactiveTintColor,
|
||||
renderIcon,
|
||||
horizontal,
|
||||
style,
|
||||
} = this.props;
|
||||
|
||||
// We render the icon twice at the same position on top of each other:
|
||||
// active and inactive one, so we can fade between them.
|
||||
return (
|
||||
<View style={style}>
|
||||
<Animated.View style={[styles.icon, { opacity: activeOpacity }]}>
|
||||
{renderIcon({
|
||||
route,
|
||||
focused: true,
|
||||
horizontal,
|
||||
tintColor: activeTintColor,
|
||||
})}
|
||||
</Animated.View>
|
||||
<Animated.View style={[styles.icon, { opacity: inactiveOpacity }]}>
|
||||
{renderIcon({
|
||||
route,
|
||||
focused: false,
|
||||
horizontal,
|
||||
tintColor: inactiveTintColor,
|
||||
})}
|
||||
</Animated.View>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
icon: {
|
||||
// We render the icon twice at the same position on top of each other:
|
||||
// active and inactive one, so we can fade between them:
|
||||
// Cover the whole iconContainer:
|
||||
position: 'absolute',
|
||||
alignSelf: 'center',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
height: '100%',
|
||||
width: '100%',
|
||||
// Workaround for react-native >= 0.54 layout bug
|
||||
minWidth: 25,
|
||||
},
|
||||
});
|
||||
@@ -1,169 +0,0 @@
|
||||
/* @flow */
|
||||
|
||||
import * as React from 'react';
|
||||
import { View, StyleSheet } from 'react-native';
|
||||
import { TabBar } from 'react-native-tab-view';
|
||||
import Animated from 'react-native-reanimated';
|
||||
import type {
|
||||
ViewStyleProp,
|
||||
TextStyleProp,
|
||||
} from 'react-native/Libraries/StyleSheet/StyleSheet';
|
||||
|
||||
type Route = {
|
||||
key: string,
|
||||
routeName: string,
|
||||
};
|
||||
|
||||
type Layout = {|
|
||||
width: number,
|
||||
height: number,
|
||||
|};
|
||||
|
||||
export type TabBarOptions = {|
|
||||
activeTintColor?: string,
|
||||
allowFontScaling?: boolean,
|
||||
bounces?: boolean,
|
||||
inactiveTintColor?: string,
|
||||
pressColor?: string,
|
||||
pressOpacity?: number,
|
||||
scrollEnabled?: boolean,
|
||||
showIcon?: boolean,
|
||||
showLabel?: boolean,
|
||||
upperCaseLabel?: boolean,
|
||||
tabStyle?: ViewStyleProp,
|
||||
indicatorStyle?: ViewStyleProp,
|
||||
iconStyle?: any,
|
||||
labelStyle?: TextStyleProp,
|
||||
contentContainerStyle?: ViewStyleProp,
|
||||
style?: ViewStyleProp,
|
||||
|};
|
||||
|
||||
type Props = {|
|
||||
...TabBarOptions,
|
||||
layout: Layout,
|
||||
position: Animated.Node<number>,
|
||||
jumpTo: (key: string) => void,
|
||||
getLabelText: (scene: { route: Route }) => ?string,
|
||||
getAccessible?: (scene: { route: Route }) => ?boolean,
|
||||
getAccessibilityLabel: (scene: { route: Route }) => ?string,
|
||||
getTestID: (scene: { route: Route }) => ?string,
|
||||
renderIcon: (scene: {
|
||||
route: Route,
|
||||
focused: boolean,
|
||||
tintColor: string,
|
||||
horizontal?: boolean,
|
||||
}) => React.Node,
|
||||
renderBadge?: (scene: { route: Route }) => React.Node,
|
||||
onTabPress?: (scene: { route: Route }) => mixed,
|
||||
onTabLongPress?: (scene: { route: Route }) => mixed,
|
||||
tabBarPosition: 'top' | 'bottom',
|
||||
navigationState: any,
|
||||
screenProps: any,
|
||||
navigation: any,
|
||||
|};
|
||||
|
||||
export default class TabBarTop extends React.PureComponent<Props> {
|
||||
static defaultProps = {
|
||||
activeTintColor: 'rgba(255, 255, 255, 1)',
|
||||
inactiveTintColor: 'rgba(255, 255, 255, 0.7)',
|
||||
showIcon: false,
|
||||
showLabel: true,
|
||||
upperCaseLabel: true,
|
||||
allowFontScaling: true,
|
||||
};
|
||||
|
||||
_renderLabel = ({ route, focused, color }) => {
|
||||
const {
|
||||
showLabel,
|
||||
upperCaseLabel,
|
||||
labelStyle,
|
||||
allowFontScaling,
|
||||
} = this.props;
|
||||
|
||||
if (showLabel === false) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const label = this.props.getLabelText({ route });
|
||||
|
||||
if (typeof label === 'string') {
|
||||
return (
|
||||
<Animated.Text
|
||||
style={[styles.label, { color }, labelStyle]}
|
||||
allowFontScaling={allowFontScaling}
|
||||
>
|
||||
{upperCaseLabel ? label.toUpperCase() : label}
|
||||
</Animated.Text>
|
||||
);
|
||||
}
|
||||
|
||||
if (typeof label === 'function') {
|
||||
return label({ focused, tintColor: color });
|
||||
}
|
||||
|
||||
return label;
|
||||
};
|
||||
|
||||
_renderIcon = ({ route, focused, color }) => {
|
||||
const { renderIcon, showIcon, iconStyle } = this.props;
|
||||
|
||||
if (showIcon === false) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<View style={[styles.icon, iconStyle]}>
|
||||
{renderIcon({
|
||||
route,
|
||||
focused,
|
||||
tintColor: color,
|
||||
})}
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
render() {
|
||||
const {
|
||||
navigation,
|
||||
activeTintColor,
|
||||
inactiveTintColor,
|
||||
/* eslint-disable no-unused-vars */
|
||||
renderIcon,
|
||||
getLabelText,
|
||||
allowFontScaling,
|
||||
showLabel,
|
||||
showIcon,
|
||||
upperCaseLabel,
|
||||
tabBarPosition,
|
||||
navigationState,
|
||||
screenProps,
|
||||
iconStyle,
|
||||
/* eslint-enable no-unused-vars */
|
||||
...rest
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<TabBar
|
||||
{...rest}
|
||||
activeColor={activeTintColor}
|
||||
inactiveColor={inactiveTintColor}
|
||||
navigationState={navigation.state}
|
||||
renderIcon={this._renderIcon}
|
||||
renderLabel={this._renderLabel}
|
||||
/>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
icon: {
|
||||
height: 24,
|
||||
width: 24,
|
||||
},
|
||||
label: {
|
||||
textAlign: 'center',
|
||||
fontSize: 13,
|
||||
margin: 4,
|
||||
backgroundColor: 'transparent',
|
||||
},
|
||||
});
|
||||
@@ -1,5 +1,3 @@
|
||||
/* @flow */
|
||||
|
||||
import * as React from 'react';
|
||||
import { Platform, StyleSheet, View } from 'react-native';
|
||||
|
||||
@@ -7,9 +5,9 @@ import { Platform, StyleSheet, View } from 'react-native';
|
||||
import { Screen, screensEnabled } from 'react-native-screens';
|
||||
|
||||
type Props = {
|
||||
isVisible: boolean,
|
||||
children: React.Node,
|
||||
style?: any,
|
||||
isVisible: boolean;
|
||||
children: React.ReactNode;
|
||||
style?: any;
|
||||
};
|
||||
|
||||
const FAR_FAR_AWAY = 3000; // this should be big enough to move the whole view out of its container
|
||||
@@ -18,6 +16,7 @@ export default class ResourceSavingScene extends React.Component<Props> {
|
||||
render() {
|
||||
if (screensEnabled && screensEnabled()) {
|
||||
const { isVisible, ...rest } = this.props;
|
||||
// @ts-ignore
|
||||
return <Screen active={isVisible ? 1 : 0} {...rest} />;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user