fix: consistent elevation behavior across platforms (#785)

This commit is contained in:
Julian Hundeloh
2019-07-01 14:42:45 +02:00
committed by Dawid
parent deefc02150
commit c3881bbdf7
8 changed files with 164 additions and 31 deletions

View File

@@ -65,7 +65,7 @@ class Surface extends React.Component<Props> {
{...rest}
style={[
{ backgroundColor: theme.colors.surface },
elevation && shadow(elevation),
shadow(elevation),
style,
]}
/>

View File

@@ -195,6 +195,13 @@ exports[`renders visible banner, with action buttons and with image 1`] = `
"elevation": 0,
"margin": 4,
"minWidth": "auto",
"shadowColor": "#000000",
"shadowOffset": Object {
"height": 0,
"width": 0,
},
"shadowOpacity": 0.24,
"shadowRadius": 0,
}
}
>
@@ -357,6 +364,13 @@ exports[`renders visible banner, with action buttons and without image 1`] = `
"elevation": 0,
"margin": 4,
"minWidth": "auto",
"shadowColor": "#000000",
"shadowOffset": Object {
"height": 0,
"width": 0,
},
"shadowOpacity": 0.24,
"shadowRadius": 0,
}
}
>
@@ -440,6 +454,13 @@ exports[`renders visible banner, with action buttons and without image 1`] = `
"elevation": 0,
"margin": 4,
"minWidth": "auto",
"shadowColor": "#000000",
"shadowOffset": Object {
"height": 0,
"width": 0,
},
"shadowOpacity": 0.24,
"shadowRadius": 0,
}
}
>

View File

@@ -11,6 +11,13 @@ exports[`renders button with color 1`] = `
"borderWidth": 0,
"elevation": 0,
"minWidth": 64,
"shadowColor": "#000000",
"shadowOffset": Object {
"height": 0,
"width": 0,
},
"shadowOpacity": 0.24,
"shadowRadius": 0,
}
}
>
@@ -94,6 +101,13 @@ exports[`renders button with icon 1`] = `
"borderWidth": 0,
"elevation": 0,
"minWidth": 64,
"shadowColor": "#000000",
"shadowOffset": Object {
"height": 0,
"width": 0,
},
"shadowOpacity": 0.24,
"shadowRadius": 0,
}
}
>
@@ -311,6 +325,13 @@ exports[`renders disabled button 1`] = `
"borderWidth": 0,
"elevation": 0,
"minWidth": 64,
"shadowColor": "#000000",
"shadowOffset": Object {
"height": 0,
"width": 0,
},
"shadowOpacity": 0.24,
"shadowRadius": 0,
}
}
>
@@ -399,6 +420,13 @@ exports[`renders loading button 1`] = `
"borderWidth": 0,
"elevation": 0,
"minWidth": 64,
"shadowColor": "#000000",
"shadowOffset": Object {
"height": 0,
"width": 0,
},
"shadowOpacity": 0.24,
"shadowRadius": 0,
}
}
>
@@ -495,6 +523,13 @@ exports[`renders outlined button with mode 1`] = `
"borderWidth": 0.5,
"elevation": 0,
"minWidth": 64,
"shadowColor": "#000000",
"shadowOffset": Object {
"height": 0,
"width": 0,
},
"shadowOpacity": 0.24,
"shadowRadius": 0,
}
}
>
@@ -578,6 +613,13 @@ exports[`renders text button by default 1`] = `
"borderWidth": 0,
"elevation": 0,
"minWidth": 64,
"shadowColor": "#000000",
"shadowOffset": Object {
"height": 0,
"width": 0,
},
"shadowOpacity": 0.24,
"shadowRadius": 0,
}
}
>
@@ -661,6 +703,13 @@ exports[`renders text button with mode 1`] = `
"borderWidth": 0,
"elevation": 0,
"minWidth": 64,
"shadowColor": "#000000",
"shadowOffset": Object {
"height": 0,
"width": 0,
},
"shadowOpacity": 0.24,
"shadowRadius": 0,
}
}
>

View File

@@ -10,6 +10,13 @@ exports[`renders chip with close button 1`] = `
"borderStyle": "solid",
"borderWidth": 0.5,
"elevation": 0,
"shadowColor": "#000000",
"shadowOffset": Object {
"height": 0,
"width": 0,
},
"shadowOpacity": 0.24,
"shadowRadius": 0,
}
}
>
@@ -184,6 +191,13 @@ exports[`renders chip with icon 1`] = `
"borderStyle": "solid",
"borderWidth": 0.5,
"elevation": 0,
"shadowColor": "#000000",
"shadowOffset": Object {
"height": 0,
"width": 0,
},
"shadowOpacity": 0.24,
"shadowRadius": 0,
}
}
>
@@ -307,6 +321,13 @@ exports[`renders chip with onPress 1`] = `
"borderStyle": "solid",
"borderWidth": 0.5,
"elevation": 0,
"shadowColor": "#000000",
"shadowOffset": Object {
"height": 0,
"width": 0,
},
"shadowOpacity": 0.24,
"shadowRadius": 0,
}
}
>
@@ -385,6 +406,13 @@ exports[`renders outlined disabled chip 1`] = `
"borderStyle": "solid",
"borderWidth": 0.5,
"elevation": 0,
"shadowColor": "#000000",
"shadowOffset": Object {
"height": 0,
"width": 0,
},
"shadowOpacity": 0.24,
"shadowRadius": 0,
}
}
>
@@ -467,6 +495,13 @@ exports[`renders selected chip 1`] = `
"borderStyle": "solid",
"borderWidth": 0.5,
"elevation": 0,
"shadowColor": "#000000",
"shadowOffset": Object {
"height": 0,
"width": 0,
},
"shadowOpacity": 0.24,
"shadowRadius": 0,
}
}
>

View File

@@ -89,6 +89,13 @@ exports[`renders list item with custom description 1`] = `
"borderStyle": "solid",
"borderWidth": 0.5,
"elevation": 0,
"shadowColor": "#000000",
"shadowOffset": Object {
"height": 0,
"width": 0,
},
"shadowOpacity": 0.24,
"shadowRadius": 0,
}
}
>

View File

@@ -14,6 +14,13 @@ exports[`renders not visible menu 1`] = `
"borderWidth": 0.5,
"elevation": 0,
"minWidth": 64,
"shadowColor": "#000000",
"shadowOffset": Object {
"height": 0,
"width": 0,
},
"shadowOpacity": 0.24,
"shadowRadius": 0,
}
}
>
@@ -101,6 +108,13 @@ exports[`renders visible menu 1`] = `
"borderWidth": 0.5,
"elevation": 0,
"minWidth": 64,
"shadowColor": "#000000",
"shadowOffset": Object {
"height": 0,
"width": 0,
},
"shadowOpacity": 0.24,
"shadowRadius": 0,
}
}
>

View File

@@ -150,6 +150,13 @@ exports[`renders snackbar with action button 1`] = `
"marginHorizontal": 8,
"marginVertical": 6,
"minWidth": "auto",
"shadowColor": "#000000",
"shadowOffset": Object {
"height": 0,
"width": 0,
},
"shadowOpacity": 0.24,
"shadowRadius": 0,
}
}
>

View File

@@ -1,44 +1,44 @@
/* @flow */
import * as Colors from './colors';
import { Animated } from 'react-native';
import * as Colors from '../styles/colors';
export default function shadow(elevation: number | Animated.Value) {
let height, radius;
type Shadow = {
shadowColor: string,
shadowOffset: {
width: Animated.Value,
height: Animated.Interpolation,
},
shadowOpacity: Animated.Value,
shadowRadius: Animated.Interpolation,
};
if (elevation instanceof Animated.Value) {
height = elevation.interpolate({
inputRange: [0, 1, 2, 3, 8, 24],
outputRange: [0, 0.5, 0.75, 2, 7, 23],
});
export default function shadow(elevation: ?number | Animated.Value): Shadow {
const animatedElevation: Animated.Value =
elevation instanceof Animated.Value
? elevation
: new Animated.Value(elevation || 0);
const inputRange = [0, 1, 2, 3, 8, 24];
radius = elevation.interpolate({
inputRange: [0, 1, 2, 3, 8, 24],
outputRange: [0, 0.75, 1.5, 3, 8, 24],
});
} else {
switch (elevation) {
case 1:
height = 0.5;
radius = 0.75;
break;
case 2:
height = 0.75;
radius = 1.5;
break;
default:
height = elevation - 1;
radius = elevation;
}
}
// Important: we need to return Animated values to ensure they are properly used in the Animated.View
const shadowOpacity = new Animated.Value(0.24);
const width = new Animated.Value(0);
const height = animatedElevation.interpolate({
inputRange,
outputRange: [0, 0.5, 0.75, 2, 7, 23],
});
const shadowRadius = animatedElevation.interpolate({
inputRange,
outputRange: [0, 0.75, 1.5, 3, 8, 24],
});
return {
shadowColor: Colors.black,
shadowOffset: {
width: 0,
width,
height,
},
shadowOpacity: 0.24,
shadowRadius: radius,
shadowOpacity,
shadowRadius,
};
}