mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
0823f299e5
Summary: This PR aims to enable support for foreground ripple in Pressable. This makes it possible to show ripple on top of custom child components like Image as shown in the below example. ## Changelog <!-- Help reviewers and the release process by writing your own changelog entry. For an example, see: https://github.com/facebook/react-native/wiki/Changelog --> [Android] [Added] - Support for foreground ripple in Pressable Pull Request resolved: https://github.com/facebook/react-native/pull/31632 Test Plan: - Pass property useForeground: true in android_ripple config to verify the changes. https://user-images.githubusercontent.com/23293248/120111371-4cecbf00-c18f-11eb-8acb-d10718d5483c.mov Reviewed By: kacieb Differential Revision: D28926493 Pulled By: yungsters fbshipit-source-id: 12a6ba71a7dc6ed60fbaeb651f015cace38e03b1
106 lines
3.0 KiB
JavaScript
106 lines
3.0 KiB
JavaScript
/**
|
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
*
|
|
* This source code is licensed under the MIT license found in the
|
|
* LICENSE file in the root directory of this source tree.
|
|
*
|
|
* @flow strict-local
|
|
* @format
|
|
*/
|
|
|
|
import invariant from 'invariant';
|
|
import {Commands} from '../View/ViewNativeComponent';
|
|
import type {ColorValue} from '../../StyleSheet/StyleSheet';
|
|
import type {PressEvent} from '../../Types/CoreEventTypes';
|
|
import {Platform, View, processColor} from 'react-native';
|
|
import * as React from 'react';
|
|
import {useMemo} from 'react';
|
|
|
|
type NativeBackgroundProp = $ReadOnly<{|
|
|
type: 'RippleAndroid',
|
|
color: ?number,
|
|
borderless: boolean,
|
|
rippleRadius: ?number,
|
|
|}>;
|
|
|
|
export type RippleConfig = {|
|
|
color?: ColorValue,
|
|
borderless?: boolean,
|
|
radius?: number,
|
|
foreground?: boolean,
|
|
|};
|
|
|
|
/**
|
|
* Provides the event handlers and props for configuring the ripple effect on
|
|
* supported versions of Android.
|
|
*/
|
|
export default function useAndroidRippleForView(
|
|
rippleConfig: ?RippleConfig,
|
|
viewRef: {|current: null | React.ElementRef<typeof View>|},
|
|
): ?$ReadOnly<{|
|
|
onPressIn: (event: PressEvent) => void,
|
|
onPressMove: (event: PressEvent) => void,
|
|
onPressOut: (event: PressEvent) => void,
|
|
viewProps:
|
|
| $ReadOnly<{|nativeBackgroundAndroid: NativeBackgroundProp|}>
|
|
| $ReadOnly<{|nativeForegroundAndroid: NativeBackgroundProp|}>,
|
|
|}> {
|
|
const {color, borderless, radius, foreground} = rippleConfig ?? {};
|
|
|
|
return useMemo(() => {
|
|
if (
|
|
Platform.OS === 'android' &&
|
|
Platform.Version >= 21 &&
|
|
(color != null || borderless != null || radius != null)
|
|
) {
|
|
const processedColor = processColor(color);
|
|
invariant(
|
|
processedColor == null || typeof processedColor === 'number',
|
|
'Unexpected color given for Ripple color',
|
|
);
|
|
|
|
const nativeRippleValue = {
|
|
type: 'RippleAndroid',
|
|
color: processedColor,
|
|
borderless: borderless === true,
|
|
rippleRadius: radius,
|
|
};
|
|
|
|
return {
|
|
viewProps:
|
|
foreground === true
|
|
? {nativeForegroundAndroid: nativeRippleValue}
|
|
: {nativeBackgroundAndroid: nativeRippleValue},
|
|
onPressIn(event: PressEvent): void {
|
|
const view = viewRef.current;
|
|
if (view != null) {
|
|
Commands.setPressed(view, true);
|
|
Commands.hotspotUpdate(
|
|
view,
|
|
event.nativeEvent.locationX ?? 0,
|
|
event.nativeEvent.locationY ?? 0,
|
|
);
|
|
}
|
|
},
|
|
onPressMove(event: PressEvent): void {
|
|
const view = viewRef.current;
|
|
if (view != null) {
|
|
Commands.hotspotUpdate(
|
|
view,
|
|
event.nativeEvent.locationX ?? 0,
|
|
event.nativeEvent.locationY ?? 0,
|
|
);
|
|
}
|
|
},
|
|
onPressOut(event: PressEvent): void {
|
|
const view = viewRef.current;
|
|
if (view != null) {
|
|
Commands.setPressed(view, false);
|
|
}
|
|
},
|
|
};
|
|
}
|
|
return null;
|
|
}, [borderless, color, foreground, radius, viewRef]);
|
|
}
|