我将
react-native
与 nativewind
库一起使用,并且 Pressable
中的条件样式在包含在带有 View
类名的 nativewind
中时不起作用。 className
中删除 View
使 Pressable
样式工作(背景颜色切换)。 <View className="flex-row basis-8/12 gap-x-2">
<Pressable
style={({ pressed }) => [
{
backgroundColor: pressed ? 'black' : 'white',
},
]}>
<Text>Select</Text>
</Pressable>
</View>
我已经实现了一种使用状态管理来处理按下状态并应用条件样式的解决方法。我们将使用 cn 函数 (utils/cn.ts):
import { ClassValue, clsx } from "clsx";
import { twMerge } from "tailwind-merge";
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs));
}
现在您可以更新组件 (ActionButton.tsx) 以使用 useState 挂钩来管理按下状态并使用 cn 有条件地应用样式:
import { useState } from "react";
import { Pressable, Text } from "react-native";
import { cn } from "@/utils/cn";
export default function MyComponent() {
const [isPressed, setPressed] = useState(false);
return (
<View className="flex-row basis-8/12 gap-x-2">
<Pressable
onPressIn={() => setPressed(true)}
onPressOut={() => setPressed(false)}
className={cn(
"items-center justify-center rounded-md p-3",
isPressed ? "bg-black" : "bg-white"
)}
>
<Text>Select</Text>
</Pressable>
</View>
);
}
但这迫使您为布局上的每个可按按钮使用状态。这是一个简单的组件(CustomPressable.tsx),可以帮助您避免这种情况:
import React, { useState } from "react";
import { Pressable, StyleProp, ViewStyle } from "react-native";
interface CustomPressableProps {
className: (isPressed: boolean) => string;
children: React.ReactNode | ((isPressed: boolean) => React.ReactNode);
onPress?: () => void;
onPressIn?: () => void;
onPressOut?: () => void;
style?: StyleProp<ViewStyle>;
}
export function CustomPressable({
className,
style,
children,
onPress,
onPressIn,
onPressOut,
}: CustomPressableProps) {
const [isPressed, setPressed] = useState(false);
return (
<Pressable
onPress={onPress}
onPressIn={() => {
onPressIn && onPressIn();
setPressed(true);
}}
onPressOut={() => {
onPressOut && onPressOut();
setPressed(false);
}}
className={className(isPressed)}
style={style}
>
{typeof children === "function" ? children(isPressed) : children}
</Pressable>
);
}
这是一个使用示例(ActionButton.tsx):
import React from "react";
import { Svg } from "react-native-svg";
import colors from "tailwindcss/colors";
import { CustomPressable } from "@/components/CustomPressable";
import { cn } from "@/utils/cn";
export function ActionButton({
iconComponent,
buttonSize,
iconScale = 1,
}: {
iconComponent: React.ReactElement;
buttonSize: number;
iconScale?: number;
}) {
const scaledSize = buttonSize * iconScale;
return (
<CustomPressable
style={{
width: buttonSize,
height: buttonSize,
}}
className={(isPressed) =>
cn(
"items-center justify-center rounded-xl",
isPressed ? "bg-accent" : "bg-gray-200",
)
}
>
{(isPressed) => (
<Svg
width={scaledSize}
height={scaledSize}
viewBox="0 0 24 24"
color={isPressed ? "white" : colors.violet["800"]}
>
{iconComponent}
</Svg>
)}
</CustomPressable>
);
}
如果有人制作了一个与 Pressable 具有相同属性的组件 - 请与我分享 ^^