mirror of
https://github.com/zhigang1992/react-navigation.git
synced 2026-01-12 22:51:18 +08:00
refactor: migrate to Pressable
This commit is contained in:
@@ -24,10 +24,10 @@ const getTabBarIcon = (name: string) => ({
|
||||
}) => <MaterialCommunityIcons name={name} color={color} size={size} />;
|
||||
|
||||
type BottomTabParams = {
|
||||
Article: NavigatorScreenParams<SimpleStackParams>;
|
||||
Albums: undefined;
|
||||
Contacts: undefined;
|
||||
Chat: undefined;
|
||||
TabStack: NavigatorScreenParams<SimpleStackParams>;
|
||||
TabAlbums: undefined;
|
||||
TabContacts: undefined;
|
||||
TabChat: undefined;
|
||||
};
|
||||
|
||||
const BottomTabs = createBottomTabNavigator<BottomTabParams>();
|
||||
@@ -58,7 +58,7 @@ export default function BottomTabsScreen({
|
||||
}}
|
||||
>
|
||||
<BottomTabs.Screen
|
||||
name="Article"
|
||||
name="TabStack"
|
||||
component={SimpleStackScreen}
|
||||
options={{
|
||||
title: 'Article',
|
||||
@@ -66,7 +66,7 @@ export default function BottomTabsScreen({
|
||||
}}
|
||||
/>
|
||||
<BottomTabs.Screen
|
||||
name="Chat"
|
||||
name="TabChat"
|
||||
component={Chat}
|
||||
options={{
|
||||
tabBarLabel: 'Chat',
|
||||
@@ -75,7 +75,7 @@ export default function BottomTabsScreen({
|
||||
}}
|
||||
/>
|
||||
<BottomTabs.Screen
|
||||
name="Contacts"
|
||||
name="TabContacts"
|
||||
component={Contacts}
|
||||
options={{
|
||||
title: 'Contacts',
|
||||
@@ -83,7 +83,7 @@ export default function BottomTabsScreen({
|
||||
}}
|
||||
/>
|
||||
<BottomTabs.Screen
|
||||
name="Albums"
|
||||
name="TabAlbums"
|
||||
component={Albums}
|
||||
options={{
|
||||
title: 'Albums',
|
||||
|
||||
@@ -8,10 +8,10 @@ import Chat from '../Shared/Chat';
|
||||
import SimpleStackScreen, { SimpleStackParams } from './SimpleStack';
|
||||
|
||||
type MaterialBottomTabParams = {
|
||||
Article: NavigatorScreenParams<SimpleStackParams>;
|
||||
Albums: undefined;
|
||||
Contacts: undefined;
|
||||
Chat: undefined;
|
||||
TabStack: NavigatorScreenParams<SimpleStackParams>;
|
||||
TabAlbums: undefined;
|
||||
TabContacts: undefined;
|
||||
TabChat: undefined;
|
||||
};
|
||||
|
||||
const MaterialBottomTabs = createMaterialBottomTabNavigator<MaterialBottomTabParams>();
|
||||
@@ -20,7 +20,7 @@ export default function MaterialBottomTabsScreen() {
|
||||
return (
|
||||
<MaterialBottomTabs.Navigator barStyle={styles.tabBar}>
|
||||
<MaterialBottomTabs.Screen
|
||||
name="Article"
|
||||
name="TabStack"
|
||||
options={{
|
||||
tabBarLabel: 'Article',
|
||||
tabBarIcon: 'file-document',
|
||||
@@ -35,7 +35,7 @@ export default function MaterialBottomTabsScreen() {
|
||||
)}
|
||||
</MaterialBottomTabs.Screen>
|
||||
<MaterialBottomTabs.Screen
|
||||
name="Chat"
|
||||
name="TabChat"
|
||||
component={Chat}
|
||||
options={{
|
||||
tabBarLabel: 'Chat',
|
||||
@@ -45,7 +45,7 @@ export default function MaterialBottomTabsScreen() {
|
||||
}}
|
||||
/>
|
||||
<MaterialBottomTabs.Screen
|
||||
name="Contacts"
|
||||
name="TabContacts"
|
||||
component={Contacts}
|
||||
options={{
|
||||
tabBarLabel: 'Contacts',
|
||||
@@ -54,7 +54,7 @@ export default function MaterialBottomTabsScreen() {
|
||||
}}
|
||||
/>
|
||||
<MaterialBottomTabs.Screen
|
||||
name="Albums"
|
||||
name="TabAlbums"
|
||||
component={Albums}
|
||||
options={{
|
||||
tabBarLabel: 'Albums',
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import React from 'react';
|
||||
import {
|
||||
View,
|
||||
Text,
|
||||
TouchableWithoutFeedback,
|
||||
Pressable,
|
||||
StyleSheet,
|
||||
Platform,
|
||||
StyleProp,
|
||||
@@ -159,13 +158,14 @@ export default function BottomTabBarItem({
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<TouchableWithoutFeedback
|
||||
<Pressable
|
||||
{...rest}
|
||||
accessibilityRole={accessibilityRole}
|
||||
onPress={onPress}
|
||||
style={style}
|
||||
>
|
||||
<View style={style}>{children}</View>
|
||||
</TouchableWithoutFeedback>
|
||||
{children}
|
||||
</Pressable>
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
@@ -10,7 +10,7 @@ import {
|
||||
StyleProp,
|
||||
View,
|
||||
InteractionManager,
|
||||
TouchableWithoutFeedback,
|
||||
Pressable,
|
||||
} from 'react-native';
|
||||
import Animated from 'react-native-reanimated';
|
||||
import {
|
||||
@@ -661,13 +661,13 @@ export default class DrawerView extends React.Component<Props> {
|
||||
drawerType === 'permanent' ? null : Platform.OS === 'web' ||
|
||||
Platform.OS === 'windows' ||
|
||||
Platform.OS === 'macos' ? (
|
||||
<TouchableWithoutFeedback
|
||||
<Pressable
|
||||
onPress={
|
||||
gestureEnabled ? () => this.toggleDrawer(false) : undefined
|
||||
}
|
||||
>
|
||||
<Overlay progress={progress} style={overlayStyle as any} />
|
||||
</TouchableWithoutFeedback>
|
||||
</Pressable>
|
||||
) : (
|
||||
<TapGestureHandler
|
||||
enabled={gestureEnabled}
|
||||
|
||||
@@ -79,15 +79,17 @@ type Props = {
|
||||
style?: StyleProp<ViewStyle>;
|
||||
};
|
||||
|
||||
const Touchable = ({
|
||||
const LinkPressable = ({
|
||||
children,
|
||||
style,
|
||||
onPress,
|
||||
onLongPress,
|
||||
to,
|
||||
accessibilityRole,
|
||||
delayPressIn,
|
||||
...rest
|
||||
}: React.ComponentProps<typeof PlatformPressable> & {
|
||||
}: Omit<React.ComponentProps<typeof PlatformPressable>, 'style'> & {
|
||||
style: StyleProp<ViewStyle>;
|
||||
} & {
|
||||
to?: string;
|
||||
children: React.ReactNode;
|
||||
onPress?: () => void;
|
||||
@@ -109,6 +111,7 @@ const Touchable = ({
|
||||
onPress?.(e);
|
||||
}
|
||||
}}
|
||||
onLongPress={onLongPress ?? undefined}
|
||||
>
|
||||
{children}
|
||||
</Link>
|
||||
@@ -118,7 +121,6 @@ const Touchable = ({
|
||||
<PlatformPressable
|
||||
{...rest}
|
||||
accessibilityRole={accessibilityRole}
|
||||
delayPressIn={delayPressIn}
|
||||
onPress={onPress}
|
||||
>
|
||||
<View style={style}>{children}</View>
|
||||
@@ -164,8 +166,7 @@ export default function DrawerItem(props: Props) {
|
||||
{...rest}
|
||||
style={[styles.container, { borderRadius, backgroundColor }, style]}
|
||||
>
|
||||
<Touchable
|
||||
delayPressIn={0}
|
||||
<LinkPressable
|
||||
onPress={onPress}
|
||||
style={[styles.wrapper, { borderRadius }]}
|
||||
accessibilityRole="button"
|
||||
@@ -200,7 +201,7 @@ export default function DrawerItem(props: Props) {
|
||||
)}
|
||||
</View>
|
||||
</React.Fragment>
|
||||
</Touchable>
|
||||
</LinkPressable>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -23,14 +23,13 @@ export default function DrawerToggleButton({ tintColor, ...rest }: Props) {
|
||||
{...rest}
|
||||
accessible
|
||||
accessibilityRole="button"
|
||||
delayPressIn={0}
|
||||
android_ripple={{ borderless: true }}
|
||||
onPress={() => navigation.dispatch(DrawerActions.toggleDrawer())}
|
||||
style={styles.touchable}
|
||||
hitSlop={Platform.select({
|
||||
ios: undefined,
|
||||
default: { top: 16, right: 16, bottom: 16, left: 16 },
|
||||
})}
|
||||
borderless
|
||||
>
|
||||
<Image
|
||||
style={[styles.icon, tintColor ? { tintColor } : null]}
|
||||
|
||||
@@ -155,15 +155,14 @@ export default function HeaderBackButton({
|
||||
accessibilityRole="button"
|
||||
accessibilityLabel={accessibilityLabel}
|
||||
testID={testID}
|
||||
delayPressIn={0}
|
||||
onPress={disabled ? undefined : handlePress}
|
||||
pressColor={pressColorAndroid}
|
||||
android_ripple={{ borderless: true }}
|
||||
style={[styles.container, disabled && styles.disabled, style]}
|
||||
hitSlop={Platform.select({
|
||||
ios: undefined,
|
||||
default: { top: 16, right: 16, bottom: 16, left: 16 },
|
||||
})}
|
||||
borderless
|
||||
>
|
||||
<React.Fragment>
|
||||
{renderBackImage()}
|
||||
|
||||
@@ -1,21 +1,15 @@
|
||||
import * as React from 'react';
|
||||
import {
|
||||
Platform,
|
||||
TouchableNativeFeedback,
|
||||
TouchableOpacity,
|
||||
View,
|
||||
TouchableWithoutFeedbackProps,
|
||||
} from 'react-native';
|
||||
import { Platform, Pressable, PressableProps } from 'react-native';
|
||||
|
||||
export type Props = TouchableWithoutFeedbackProps & {
|
||||
export type Props = PressableProps & {
|
||||
pressColor?: string;
|
||||
pressOpacity?: number;
|
||||
disabled?: boolean | null;
|
||||
borderless?: boolean;
|
||||
children: React.ReactNode;
|
||||
};
|
||||
|
||||
const ANDROID_VERSION_LOLLIPOP = 21;
|
||||
const ANDROID_SUPPORTS_RIPPLE =
|
||||
Platform.OS === 'android' && Platform.Version >= ANDROID_VERSION_LOLLIPOP;
|
||||
|
||||
/**
|
||||
* PlatformPressable provides an abstraction on top of TouchableNativeFeedback and
|
||||
@@ -25,39 +19,24 @@ const ANDROID_VERSION_LOLLIPOP = 21;
|
||||
* On other platforms, you can pass the props of TouchableOpacity.
|
||||
*/
|
||||
export default function PlatformPressable({
|
||||
borderless = false,
|
||||
android_ripple,
|
||||
pressColor = 'rgba(0, 0, 0, .32)',
|
||||
pressOpacity,
|
||||
style,
|
||||
children,
|
||||
...rest
|
||||
}: Props) {
|
||||
/*
|
||||
* TouchableNativeFeedback.Ripple causes a crash on old Android versions,
|
||||
* therefore only enable it on Android Lollipop and above.
|
||||
*
|
||||
* All touchables on Android should have the ripple effect according to
|
||||
* platform design guidelines.
|
||||
* We need to pass the background prop to specify a borderless ripple effect.
|
||||
*/
|
||||
if (
|
||||
Platform.OS === 'android' &&
|
||||
Platform.Version >= ANDROID_VERSION_LOLLIPOP
|
||||
) {
|
||||
return (
|
||||
<TouchableNativeFeedback
|
||||
{...rest}
|
||||
useForeground={TouchableNativeFeedback.canUseNativeForeground()}
|
||||
background={TouchableNativeFeedback.Ripple(pressColor, borderless)}
|
||||
>
|
||||
<View style={style}>{React.Children.only(children)}</View>
|
||||
</TouchableNativeFeedback>
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<TouchableOpacity style={style} activeOpacity={pressOpacity} {...rest}>
|
||||
{children}
|
||||
</TouchableOpacity>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<Pressable
|
||||
android_ripple={
|
||||
ANDROID_SUPPORTS_RIPPLE
|
||||
? { color: pressColor, ...android_ripple }
|
||||
: undefined
|
||||
}
|
||||
style={({ pressed }) => [
|
||||
{ opacity: pressed && !ANDROID_SUPPORTS_RIPPLE ? pressOpacity : 1 },
|
||||
typeof style === 'function' ? style({ pressed }) : style,
|
||||
]}
|
||||
{...rest}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user