はじめに
v0.63から追加されたPressable
は、コンポーネントをタップしたときのスタイルや描画内容を制御できる非常に便利なAPIです。
例えば、v0.63以前だとTouchableOpacity
でしか制御できなかったタップ時のopacityを、Pressable
だとstyle
をちょっといじるだけで変更することができます。
この便利さ故、TouchableOpacity
とTouchableWithoutFeedback
のページにも、拡張性の高いボタンをつくるならPressable
を使え的なことが書かれています。
ただ、各ファイルでPressable
を使うことになったとき、以下のようにstyleを定義していくと、タップ時のopacityをただ変えたいだけなのにも関わらず、冗長な記述となってしまいます。
<Pressable
onPress={onPress}
style={({ pressed }) => [
{
opacity: pressed
? 0.5
: 1
},
styles.container
]}>
{children}
</Pressable>
各ファイルへのこのような記述の点在を避けるために、opacityを簡単に制御できるPressableStyle
を作成しました。
実装
かなり冗長なタップ中のopacityの記述をPressableStyle
でラップします。
type PressableStateCallbackType = Readonly<{
pressed: boolean;
}>;
const PressableStyle = {
opacity: ({ opacity = 0.5, style = [] }: { opacity?: number; style?: StyleProp<ViewStyle> }) => {
return ({ pressed }: PressableStateCallbackType) => [{ opacity: pressed ? opacity : 1 }, style];
},
};
以下がPressableStyle
を適用したコンポーネントの例です。
デフォルト値(0.5)以外のopacityを設定したい場合は、opacity: 0.2
のように指定します。
type Props = {
onPress: () => void;
containerStyle?: StyleProp<ViewStyle>;
children: React.ReactNode;
}
export const StyledButton: React.FC<Props> = React.memo(
({ onPress, containerStyle, children }) => {
return (
<Pressable
onPress={onPress}
style={PressableStyle.opacity({
opacity: 0.2,
style: [styles.container, containerStyle],
})}
>
{children}
</Pressable>
);
},
);
おわりに
TouchableOpacity
だとopacityは0.2で固定で、コンポーネントによってはタップ時の透過が強く感じるときがあります。
そんなときはPressable
を使って柔軟にスタイルを制御しましょう。
参考資料