How would one add a zoom effect when doing pull to refresh #1471
Replies: 4 comments 8 replies
-
Hey! @Daavidaviid if it was Swift/OC it would be very easy to implement, just need to use but RN does not have enough relevant APIs for this, maybe I didn't think of a good way to deal with them. and I want to use anyways, I will follow the |
Beta Was this translation helpful? Give feedback.
-
Here you can see it working both on iOS and Android : Android Screen.Recording.2022-09-05.at.16.33.41.moviOS Screen.Recording.2022-09-05.at.16.33.59.movBasically, I just add the banner image below the scrollview. export type CollapsibleHeaderProps<T extends Route> = {
initHeaderHeight?: number;
- renderScrollHeader: () => React.ReactElement | null;
+ renderScrollHeader: (translateYValue: SharedValue<number>) => React.ReactElement | null;
+ renderAbsoluteBackgroundContent?: (translateYValue: SharedValue<number>) => React.ReactElement | null;
initTabbarHeight?: number;
minHeaderHeight?: number;
overflowHeight?: number; And here is the full patch below. Tell me what you think about this solution. I noticed some performances issue with diff --git a/node_modules/@showtime-xyz/universal.collapsible-tab-view/dist/gesture-container.ios.js b/node_modules/@showtime-xyz/universal.collapsible-tab-view/dist/gesture-container.ios.js
index 28fa8bc..51ceed9 100644
--- a/node_modules/@showtime-xyz/universal.collapsible-tab-view/dist/gesture-container.ios.js
+++ b/node_modules/@showtime-xyz/universal.collapsible-tab-view/dist/gesture-container.ios.js
@@ -9,7 +9,7 @@ import RefreshControlContainer from "./refresh-control";
import { animateToRefresh, mScrollTo } from "./utils";
const { width } = Dimensions.get("window");
// Todo: temporarily add `.ios.tsx` file to try the bounces effect, will be merged into `gesture-container.tsx` after stabilization
-export const GestureContainer = React.forwardRef(function GestureContainer({ refreshHeight = 80, pullExtendedCoefficient = 0.1, overflowPull = 50, overflowHeight = 0, scrollEnabled = true, minHeaderHeight = 0, isRefreshing: isRefreshingProp = false, initialPage, onStartRefresh, initTabbarHeight = 49, initHeaderHeight = 0, renderScrollHeader, renderTabView, renderRefreshControl: renderRefreshControlProp, animationHeaderPosition, animationHeaderHeight, panHeaderMaxOffset, onPullEnough, refreshControlColor, refreshControlTop = 0, emptyBodyComponent, navigationState, renderSceneHeader, }, forwardedRef) {
+export const GestureContainer = React.forwardRef(function GestureContainer({ refreshHeight = 80, pullExtendedCoefficient = 0.1, overflowPull = 50, overflowHeight = 0, scrollEnabled = true, minHeaderHeight = 0, isRefreshing: isRefreshingProp = false, initialPage, onStartRefresh, initTabbarHeight = 49, initHeaderHeight = 0, renderScrollHeader, renderAbsoluteBackgroundContent, renderTabView, renderRefreshControl: renderRefreshControlProp, animationHeaderPosition, animationHeaderHeight, panHeaderMaxOffset, onPullEnough, refreshControlColor, refreshControlTop = 0, emptyBodyComponent, navigationState, renderSceneHeader, }, forwardedRef) {
//#region animation value
const shareAnimatedValue = useSharedValue(0);
const curIndexValue = useSharedValue(initialPage);
@@ -441,7 +441,7 @@ export const GestureContainer = React.forwardRef(function GestureContainer({ ref
return (<Animated.View style={[styles.tabbarStyle, tabbarAnimateStyle]}>
<GestureDetector gesture={gestureHandlerHeader}>
<Animated.View style={styles.container}>
- {renderScrollHeader && (<View onLayout={headerOnLayout}>{renderScrollHeader()}</View>)}
+ {renderScrollHeader && (<View onLayout={headerOnLayout}>{renderScrollHeader(translateYValue)}</View>)}
{navigationState?.routes.length === 0 && emptyBodyComponent ? (<View style={{ marginTop: tabbarHeight }}>
{emptyBodyComponent}
</View>) : (<Animated.View style={{ transform: [{ translateY: -overflowHeight }] }} onLayout={tabbarOnLayout}>
@@ -472,6 +472,7 @@ export const GestureContainer = React.forwardRef(function GestureContainer({ ref
curIndexValue.value = index;
},
}), [curIndexValue]);
+
return (<HeaderTabContext.Provider value={{
shareAnimatedValue,
headerTrans,
@@ -492,6 +493,11 @@ export const GestureContainer = React.forwardRef(function GestureContainer({ ref
}}>
<GestureDetector gesture={gestureHandler}>
<Animated.View style={[styles.container, opacityStyle]}>
+ {!!renderAbsoluteBackgroundContent && (
+ <View style={styles.absoluteBackground}>
+ {renderAbsoluteBackgroundContent(translateYValue)}
+ </View>
+ )}
<Animated.View style={[styles.container, animateStyle]} onLayout={containerOnLayout}>
{renderTabView({
renderTabBarContainer: _renderTabBarContainer,
@@ -514,5 +520,10 @@ const styles = StyleSheet.create({
right: 0,
zIndex: 10,
},
+ absoluteBackground: {
+ position: "absolute",
+ top: 0,
+ width: '100%',
+ }
});
//# sourceMappingURL=gesture-container.ios.js.map
\ No newline at end of file
diff --git a/node_modules/@showtime-xyz/universal.collapsible-tab-view/dist/gesture-container.js b/node_modules/@showtime-xyz/universal.collapsible-tab-view/dist/gesture-container.js
index cb357c5..17d4c31 100644
--- a/node_modules/@showtime-xyz/universal.collapsible-tab-view/dist/gesture-container.js
+++ b/node_modules/@showtime-xyz/universal.collapsible-tab-view/dist/gesture-container.js
@@ -8,7 +8,7 @@ import { useSceneInfo } from "./hooks/use-scene-info";
import RefreshControlContainer from "./refresh-control";
import { animateToRefresh, mScrollTo } from "./utils";
const { width } = Dimensions.get("window");
-export const GestureContainer = React.forwardRef(function GestureContainer({ refreshHeight = 80, pullExtendedCoefficient = 0.1, overflowPull = 50, overflowHeight = 0, scrollEnabled = true, minHeaderHeight = 0, isRefreshing: isRefreshingProp = false, initialPage, onStartRefresh, initTabbarHeight = 49, initHeaderHeight = 0, renderScrollHeader, renderTabView, renderRefreshControl: renderRefreshControlProp, animationHeaderPosition, animationHeaderHeight, panHeaderMaxOffset, onPullEnough, refreshControlColor, refreshControlTop = 0, emptyBodyComponent, navigationState, renderSceneHeader, }, forwardedRef) {
+export const GestureContainer = React.forwardRef(function GestureContainer({ refreshHeight = 80, pullExtendedCoefficient = 0.1, overflowPull = 50, overflowHeight = 0, scrollEnabled = true, minHeaderHeight = 0, isRefreshing: isRefreshingProp = false, initialPage, onStartRefresh, initTabbarHeight = 49, initHeaderHeight = 0, renderScrollHeader, renderAbsoluteBackgroundContent, renderTabView, renderRefreshControl: renderRefreshControlProp, animationHeaderPosition, animationHeaderHeight, panHeaderMaxOffset, onPullEnough, refreshControlColor, refreshControlTop = 0, emptyBodyComponent, navigationState, renderSceneHeader, }, forwardedRef) {
//#region animation value
const shareAnimatedValue = useSharedValue(0);
const curIndexValue = useSharedValue(initialPage);
@@ -429,7 +429,7 @@ export const GestureContainer = React.forwardRef(function GestureContainer({ ref
return (<Animated.View style={[styles.tabbarStyle, tabbarAnimateStyle]}>
<GestureDetector gesture={gestureHandlerHeader}>
<Animated.View style={styles.container}>
- {renderScrollHeader && (<View onLayout={headerOnLayout}>{renderScrollHeader()}</View>)}
+ {renderScrollHeader && (<View onLayout={headerOnLayout}>{renderScrollHeader(translateYValue)}</View>)}
{navigationState?.routes.length === 0 && emptyBodyComponent ? (<View style={{ marginTop: tabbarHeight }}>
{emptyBodyComponent}
</View>) : (<Animated.View style={{ transform: [{ translateY: -overflowHeight }] }} onLayout={tabbarOnLayout}>
@@ -480,6 +480,11 @@ export const GestureContainer = React.forwardRef(function GestureContainer({ ref
}}>
<GestureDetector gesture={gestureHandler}>
<Animated.View style={[styles.container, opacityStyle]}>
+ {!!renderAbsoluteBackgroundContent && (
+ <View style={styles.absoluteBackground}>
+ {renderAbsoluteBackgroundContent(translateYValue)}
+ </View>
+ )}
<Animated.View style={[styles.container, animateStyle]} onLayout={containerOnLayout}>
{renderTabView({
renderTabBarContainer: _renderTabBarContainer,
@@ -502,5 +507,10 @@ const styles = StyleSheet.create({
right: 0,
zIndex: 10,
},
+ absoluteBackground: {
+ position: "absolute",
+ top: 0,
+ width: "100%",
+ }
});
//# sourceMappingURL=gesture-container.js.map
\ No newline at end of file
diff --git a/node_modules/@showtime-xyz/universal.collapsible-tab-view/gesture-container.ios.tsx b/node_modules/@showtime-xyz/universal.collapsible-tab-view/gesture-container.ios.tsx
index 2ff7de5..ac5802c 100644
--- a/node_modules/@showtime-xyz/universal.collapsible-tab-view/gesture-container.ios.tsx
+++ b/node_modules/@showtime-xyz/universal.collapsible-tab-view/gesture-container.ios.tsx
@@ -58,6 +58,7 @@ export const GestureContainer = React.forwardRef<
initTabbarHeight = 49,
initHeaderHeight = 0,
renderScrollHeader,
+ renderAbsoluteBackgroundContent,
renderTabView,
renderRefreshControl: renderRefreshControlProp,
animationHeaderPosition,
@@ -615,7 +616,7 @@ export const GestureContainer = React.forwardRef<
<GestureDetector gesture={gestureHandlerHeader}>
<Animated.View style={styles.container}>
{renderScrollHeader && (
- <View onLayout={headerOnLayout}>{renderScrollHeader()}</View>
+ <View onLayout={headerOnLayout}>{renderScrollHeader(translateYValue)}</View>
)}
{navigationState?.routes.length === 0 && emptyBodyComponent ? (
<View style={{ marginTop: tabbarHeight }}>
@@ -698,6 +699,11 @@ export const GestureContainer = React.forwardRef<
}}
>
<GestureDetector gesture={gestureHandler}>
+ {!!renderAbsoluteBackgroundContent && (
+ <View style={styles.absoluteBackground}>
+ {renderAbsoluteBackgroundContent(translateYValue)}
+ </View>
+ )}
<Animated.View style={[styles.container, opacityStyle]}>
<Animated.View
style={[styles.container, animateStyle]}
@@ -726,4 +732,9 @@ const styles = StyleSheet.create({
right: 0,
zIndex: 10,
},
+ absoluteBackground: {
+ position: "absolute",
+ top: 0,
+ width: "100%",
+ }
});
diff --git a/node_modules/@showtime-xyz/universal.collapsible-tab-view/gesture-container.tsx b/node_modules/@showtime-xyz/universal.collapsible-tab-view/gesture-container.tsx
index 3ed6d25..2c362c4 100644
--- a/node_modules/@showtime-xyz/universal.collapsible-tab-view/gesture-container.tsx
+++ b/node_modules/@showtime-xyz/universal.collapsible-tab-view/gesture-container.tsx
@@ -599,7 +599,7 @@ export const GestureContainer = React.forwardRef<
<GestureDetector gesture={gestureHandlerHeader}>
<Animated.View style={styles.container}>
{renderScrollHeader && (
- <View onLayout={headerOnLayout}>{renderScrollHeader()}</View>
+ <View onLayout={headerOnLayout}>{renderScrollHeader(translateYValue)}</View>
)}
{navigationState?.routes.length === 0 && emptyBodyComponent ? (
<View style={{ marginTop: tabbarHeight }}>
diff --git a/node_modules/@showtime-xyz/universal.collapsible-tab-view/types.tsx b/node_modules/@showtime-xyz/universal.collapsible-tab-view/types.tsx
index 4f7d28c..655fc6f 100644
--- a/node_modules/@showtime-xyz/universal.collapsible-tab-view/types.tsx
+++ b/node_modules/@showtime-xyz/universal.collapsible-tab-view/types.tsx
@@ -4,6 +4,7 @@ import type { ScrollViewProps } from "react-native";
import type { NativeGesture } from "react-native-gesture-handler";
import type Animated from "react-native-reanimated";
+import { SharedValue } from "react-native-reanimated";
import type {
TabViewProps,
Route as TabViewRoute,
@@ -25,7 +26,8 @@ export enum RefreshTypeEnum {
export type CollapsibleHeaderProps<T extends Route> = {
initHeaderHeight?: number;
- renderScrollHeader: () => React.ReactElement | null;
+ renderScrollHeader: (translateYValue: SharedValue<number>) => React.ReactElement | null;
+ renderAbsoluteBackgroundContent?: (translateYValue: SharedValue<number>) => React.ReactElement | null;
initTabbarHeight?: number;
minHeaderHeight?: number;
overflowHeight?: number;
|
Beta Was this translation helpful? Give feedback.
-
Hey ! I can't reproduce on expo because of the issue with the latest version of expo go |
Beta Was this translation helpful? Give feedback.
-
Hey @alantoa,
I'd like to use this library. But to maintain an existing behaviour I would need to make a zoom effect on the banner image when doing pull to refresh.
I've been trying to tweak the lib, for example in
gesture-container.ios
I do this :instead of this :
Using this technique I can interpolate
translateYValue
to scale my banner in the header, but it get cropped :Screen.Recording.2022-09-05.at.12.54.00.mov
But still no luck yet. Do you think it's easy to add this possibility ?
Beta Was this translation helpful? Give feedback.
All reactions