Skip to content

Commit

Permalink
Change opacity transition from discrete to continuous
Browse files Browse the repository at this point in the history
  • Loading branch information
dmnplb committed Apr 10, 2024
1 parent fbb766c commit f27e3ae
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 22 deletions.
10 changes: 5 additions & 5 deletions example/src/pages/GradientScroll.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,19 +23,19 @@ export const GradientScroll = () => {
<GradientScrollView
debugMode
actionsProps={{
type: "ThreeButtons",
type: "TwoButtons",
primary: {
label: "Primary action",
onPress: () => Alert.alert("Primary action pressed! (⁠⁠ꈍ⁠ᴗ⁠ꈍ⁠)")
},
secondary: {
label: "Secondary",
onPress: () => Alert.alert("Secondary action pressed! (⁠⁠ꈍ⁠ᴗ⁠ꈍ⁠)")
},
tertiary: {
label: "Tertiary",
onPress: () => Alert.alert("Tertiary action pressed! (⁠⁠ꈍ⁠ᴗ⁠ꈍ⁠)")
}
// tertiary: {
// label: "Tertiary",
// onPress: () => Alert.alert("Tertiary action pressed! (⁠⁠ꈍ⁠ᴗ⁠ꈍ⁠)")
// }
}}
>
<H2>Start</H2>
Expand Down
36 changes: 19 additions & 17 deletions src/components/layout/GradientScrollView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,11 @@ import { easeGradient } from "react-native-easing-gradient";
import LinearGradient from "react-native-linear-gradient";
import Animated, {
Easing,
Extrapolate,
interpolate,
useAnimatedScrollHandler,
useAnimatedStyle,
useSharedValue,
withTiming
useSharedValue
} from "react-native-reanimated";
import { useSafeAreaInsets } from "react-native-safe-area-context";
import {
Expand Down Expand Up @@ -57,8 +58,11 @@ type GradientScrollView = WithTestID<
}>
>;

/* Percentage of scrolled content that triggers
the gradient opaciy transition */
const gradientOpacityScrollTrigger = 0.85;
/* Extended gradient area above the actions */
export const gradientSafeAreaHeight: IOSpacingScale = 96;
const gradientSafeAreaHeight: IOSpacingScale = 96;
/* End content margin before the actions */
const contentEndMargin: IOSpacingScale = 32;
/* Margin between ButtonSolid and ButtonOutline */
Expand Down Expand Up @@ -102,7 +106,7 @@ export const GradientScrollView = ({
const theme = useIOTheme();

/* Shared Values for `reanimated` */
const gradientOpacity = useSharedValue(1);
const scrollPositionPercentage = useSharedValue(0); /* Scroll position */

/* Total height of actions */
const [actionBlockHeight, setActionBlockHeight] =
Expand Down Expand Up @@ -171,32 +175,30 @@ export const GradientScrollView = ({

const handleScroll = useAnimatedScrollHandler(
({ contentOffset, layoutMeasurement, contentSize }) => {
/* We use Math.floor because decimals used on Android
devices never change the `isEndReached` boolean value.
We have more consistent behavior across platforms
if we round these calculations ¯\_(ツ)_/¯ */
const isEndReached =
Math.floor(layoutMeasurement.height + contentOffset.y) >=
Math.floor(contentSize.height);
const scrollPosition = contentOffset.y;
const maxScrollHeight = contentSize.height - layoutMeasurement.height;
const scrollPercentage = scrollPosition / maxScrollHeight;

// eslint-disable-next-line functional/immutable-data
gradientOpacity.value = isEndReached ? 0 : 1;
scrollPositionPercentage.value = scrollPercentage;
}
);

const opacityTransition = useAnimatedStyle(() => ({
opacity: withTiming(gradientOpacity.value, {
duration: 200,
easing: Easing.ease
})
opacity: interpolate(
scrollPositionPercentage.value,
[0, gradientOpacityScrollTrigger, 1],
[1, 1, 0],
Extrapolate.CLAMP
)
}));

return (
<>
<Animated.ScrollView
testID={testID}
onScroll={handleScroll}
scrollEventThrottle={16}
scrollEventThrottle={8}
contentContainerStyle={{
paddingHorizontal: IOVisualCostants.appMarginDefault,
paddingBottom: safeBottomAreaHeight
Expand Down

0 comments on commit f27e3ae

Please sign in to comment.