diff --git a/example/src/Examples/CardExample.tsx b/example/src/Examples/CardExample.tsx
index 292cb3c3c8..92a1b5780b 100644
--- a/example/src/Examples/CardExample.tsx
+++ b/example/src/Examples/CardExample.tsx
@@ -10,6 +10,7 @@ import {
Text,
Switch,
} from 'react-native-paper';
+import { PreferencesContext } from '..';
import ScreenWrapper from '../ScreenWrapper';
const CardExample = () => {
@@ -19,6 +20,8 @@ const CardExample = () => {
const [isOutlined, setIsOutlined] = React.useState(false);
const mode = isOutlined ? 'outlined' : 'elevated';
+ const preferences = React.useContext(PreferencesContext);
+
return (
@@ -120,6 +123,23 @@ const CardExample = () => {
+ {
+ preferences.toggleTheme();
+ }}
+ mode={mode}
+ >
+ }
+ />
+
+
+ This is pressable card. If you press me, I will switch the theme.
+
+
+
);
diff --git a/example/src/index.tsx b/example/src/index.tsx
index 559e04211e..96dcf1ab6f 100644
--- a/example/src/index.tsx
+++ b/example/src/index.tsx
@@ -70,7 +70,7 @@ const CustomDefaultTheme = {
},
};
-const PreferencesContext = React.createContext(null);
+export const PreferencesContext = React.createContext(null);
const DrawerContent = () => {
return (
diff --git a/src/components/Card/Card.tsx b/src/components/Card/Card.tsx
index 6a76c90782..d504524116 100644
--- a/src/components/Card/Card.tsx
+++ b/src/components/Card/Card.tsx
@@ -28,6 +28,8 @@ type ElevatedCardProps = {
elevation?: number;
};
+type HandlePressType = 'in' | 'out';
+
type Props = React.ComponentProps & {
/**
* Resting elevation of the card which controls the drop shadow.
@@ -111,30 +113,69 @@ const Card = ({
accessible,
...rest
}: (OutlinedCardProps | ElevatedCardProps) & Props) => {
+ // Default animated value
const { current: elevation } = React.useRef(
new Animated.Value(cardElevation)
);
+ // Dark adaptive animated value, used in case of toggling the theme,
+ // it prevents animating the background with native drivers inside Surface
+ const { current: elevationDarkAdaptive } = React.useRef(
+ new Animated.Value(cardElevation)
+ );
const { animation, dark, mode, roundness } = theme;
+ const prevDarkRef = React.useRef(dark);
+ React.useEffect(() => {
+ prevDarkRef.current = dark;
+ });
+
+ const prevDark = prevDarkRef.current;
+ const isAdaptiveMode = mode === 'adaptive';
+ const animationDuration = 150 * animation.scale;
+
+ React.useEffect(() => {
+ /**
+ * Resets animations values if updating to dark adaptive mode,
+ * otherwise, any card that is in the middle of animation while
+ * toggling the theme will stay at that animated value until
+ * the next press-in
+ */
+ if (dark && isAdaptiveMode && !prevDark) {
+ elevation.setValue(cardElevation);
+ elevationDarkAdaptive.setValue(cardElevation);
+ }
+ }, [
+ prevDark,
+ dark,
+ isAdaptiveMode,
+ cardElevation,
+ elevation,
+ elevationDarkAdaptive,
+ ]);
+
+ const runElevationAnimation = (pressType: HandlePressType) => {
+ const isPressTypeIn = pressType === 'in';
+ if (dark && isAdaptiveMode) {
+ Animated.timing(elevationDarkAdaptive, {
+ toValue: isPressTypeIn ? 8 : cardElevation,
+ duration: animationDuration,
+ useNativeDriver: false,
+ }).start();
+ } else {
+ Animated.timing(elevation, {
+ toValue: isPressTypeIn ? 8 : cardElevation,
+ duration: animationDuration,
+ useNativeDriver: true,
+ }).start();
+ }
+ };
+
const handlePressIn = () => {
- const {
- dark,
- mode,
- animation: { scale },
- } = theme;
- Animated.timing(elevation, {
- toValue: 8,
- duration: 150 * scale,
- useNativeDriver: !dark || mode === 'exact',
- }).start();
+ runElevationAnimation('in');
};
const handlePressOut = () => {
- Animated.timing(elevation, {
- toValue: cardElevation,
- duration: 150 * animation.scale,
- useNativeDriver: !dark || mode === 'exact',
- }).start();
+ runElevationAnimation('out');
};
const total = React.Children.count(children);
@@ -143,15 +184,17 @@ const Card = ({
? (child.type as any).displayName
: null
);
- const borderColor = color(theme.dark ? white : black)
+ const borderColor = color(dark ? white : black)
.alpha(0.12)
.rgb()
.string();
+ const computedElevation =
+ dark && isAdaptiveMode ? elevationDarkAdaptive : elevation;
return (