From 7f5ade5999f4ced64f64245c67f05f1c4d635b64 Mon Sep 17 00:00:00 2001 From: Arnaud Vergnet Date: Sat, 18 Apr 2020 16:55:08 +0200 Subject: [PATCH] Improved tab hiding by following header animation --- App.js | 2 +- src/components/Lists/WebSectionList.js | 14 +++---- src/components/Screens/WebViewScreen.js | 9 ----- src/components/Tabbar/CustomTabBar.js | 53 ++++++++++++++++--------- src/navigation/MainTabNavigator.js | 9 ----- 5 files changed, 40 insertions(+), 47 deletions(-) diff --git a/App.js b/App.js index d709bc4..69872ab 100644 --- a/App.js +++ b/App.js @@ -62,7 +62,7 @@ export default class App extends React.Component { this.defaultData = {}; this.urlHandler = new URLHandler(this.onInitialURLParsed, this.onDetectURL); this.urlHandler.listen(); - setSafeBounceHeight(Platform.OS === 'ios' ? 100 : 0); + setSafeBounceHeight(Platform.OS === 'ios' ? 100 : 20); } onInitialURLParsed = ({route, data}: Object) => { diff --git a/src/components/Lists/WebSectionList.js b/src/components/Lists/WebSectionList.js index bea52a4..82f3e10 100644 --- a/src/components/Lists/WebSectionList.js +++ b/src/components/Lists/WebSectionList.js @@ -9,7 +9,6 @@ import ErrorView from "../Custom/ErrorView"; import BasicLoadingScreen from "../Custom/BasicLoadingScreen"; import {withCollapsible} from "../../utils/withCollapsible"; import * as Animatable from 'react-native-animatable'; -import AutoHideHandler from "../../utils/AutoHideHandler"; import CustomTabBar from "../Tabbar/CustomTabBar"; type Props = { @@ -52,9 +51,9 @@ class WebSectionList extends React.PureComponent { itemHeight: null, }; + scrollRef: Object; refreshInterval: IntervalID; lastRefresh: Date; - hideHandler: AutoHideHandler; state = { refreshing: false, @@ -75,8 +74,6 @@ class WebSectionList extends React.PureComponent { this.onFetchSuccess = this.onFetchSuccess.bind(this); this.onFetchError = this.onFetchError.bind(this); this.getEmptySectionHeader = this.getEmptySectionHeader.bind(this); - this.hideHandler = new AutoHideHandler(false); - this.hideHandler.addListener(this.onHideChange); } /** @@ -88,6 +85,7 @@ class WebSectionList extends React.PureComponent { const onScreenBlur = this.onScreenBlur.bind(this); this.props.navigation.addListener('focus', onScreenFocus); this.props.navigation.addListener('blur', onScreenBlur); + this.scrollRef = React.createRef(); this.onRefresh(); } @@ -99,6 +97,8 @@ class WebSectionList extends React.PureComponent { this.onRefresh(); if (this.props.autoRefreshTime > 0) this.refreshInterval = setInterval(this.onRefresh, this.props.autoRefreshTime) + // if (this.scrollRef.current) // Reset scroll to top + // this.scrollRef.current.getNode().scrollToLocation({animated:false, itemIndex:0, sectionIndex:0}); } /** @@ -205,15 +205,10 @@ class WebSectionList extends React.PureComponent { } onScroll = (event: Object) => { - this.hideHandler.onScroll(event); if (this.props.onScroll) this.props.onScroll(event); } - onHideChange = (shouldHide: boolean) => { - this.props.navigation.setParams({hideTabBar: shouldHide}); - } - render() { let dataset = []; if (this.state.fetchedData !== undefined) @@ -224,6 +219,7 @@ class WebSectionList extends React.PureComponent { {/*$FlowFixMe*/} { }; webviewRef: Object; - hideHandler: AutoHideHandler; canGoBack: boolean; @@ -42,8 +40,6 @@ class WebViewScreen extends React.PureComponent { super(); this.webviewRef = React.createRef(); this.canGoBack = false; - this.hideHandler = new AutoHideHandler(false); - this.hideHandler.addListener(this.onHideChange); } /** @@ -136,15 +132,10 @@ class WebViewScreen extends React.PureComponent { } onScroll = (event: Object) => { - this.hideHandler.onScroll(event); if (this.props.onScroll) this.props.onScroll(event); } - onHideChange = (shouldHide: boolean) => { - this.props.navigation.setParams({hideTabBar: shouldHide}); - } - render() { const {containerPaddingTop, onScrollWithListener} = this.props.collapsibleStack; return ( diff --git a/src/components/Tabbar/CustomTabBar.js b/src/components/Tabbar/CustomTabBar.js index 2b66647..fa3a486 100644 --- a/src/components/Tabbar/CustomTabBar.js +++ b/src/components/Tabbar/CustomTabBar.js @@ -2,33 +2,45 @@ import * as React from 'react'; import {withTheme} from 'react-native-paper'; import TabIcon from "./TabIcon"; import TabHomeIcon from "./TabHomeIcon"; -import * as Animatable from 'react-native-animatable'; +import {AnimatedValue} from "react-native-reanimated"; +import {Animated} from 'react-native'; type Props = { state: Object, descriptors: Object, navigation: Object, theme: Object, + collapsibleStack: Object, +} + +type State = { + translateY: AnimatedValue, } /** * Abstraction layer for Agenda component, using custom configuration */ -class CustomTabBar extends React.Component { +class CustomTabBar extends React.Component { static TAB_BAR_HEIGHT = 48; + barSynced: boolean; // Is the bar synced with the header for animations? + + state = { + translateY: new Animated.Value(0), + } + // shouldComponentUpdate(nextProps: Props): boolean { // return (nextProps.theme.dark !== this.props.theme.dark) // || (nextProps.state.index !== this.props.state.index); // } - isHidden: boolean; tabRef: Object; constructor() { super(); this.tabRef = React.createRef(); + this.barSynced = false; } onItemPress(route: Object, currentIndex: number, destIndex: number) { @@ -38,6 +50,7 @@ class CustomTabBar extends React.Component { canPreventDefault: true, }); if (currentIndex !== destIndex && !event.defaultPrevented) { + this.state.translateY = new Animated.Value(0); this.props.navigation.navigate(route.name, { screen: 'index', params: {animationDir: currentIndex < destIndex ? "right" : "left"} @@ -45,16 +58,21 @@ class CustomTabBar extends React.Component { } } + onRouteChange = () => { + this.barSynced = false; + } + render() { const state = this.props.state; const descriptors = this.props.descriptors; const navigation = this.props.navigation; + this.props.navigation.addListener('state', this.onRouteChange); return ( - { bottom: 0, left: 0, backgroundColor: this.props.theme.colors.surface, + transform: [{translateY: this.state.translateY}] }} > {state.routes.map((route, index) => { @@ -85,18 +104,14 @@ class CustomTabBar extends React.Component { }); }; if (isFocused) { - const tabVisible = options.tabBarVisible(); - console.log(tabVisible); - if (this.tabRef.current) { - if (this.isHidden && tabVisible) { - this.isHidden = false; - this.tabRef.current.slideInUp(300); - } else if (!this.isHidden && !tabVisible){ - this.isHidden = true; - this.tabRef.current.slideOutDown(300); - } + const stackState = route.state; + const stackRoute = route.state ? stackState.routes[stackState.index] : undefined; + const params = stackRoute ? stackRoute.params : undefined; + const collapsible = params ? params.collapsible : undefined; + if (collapsible && !this.barSynced) { + this.barSynced = true; + this.setState({translateY: Animated.multiply(-1.5, collapsible.translateY)}); } - } const color = isFocused ? options.activeColor : options.inactiveColor; @@ -120,7 +135,7 @@ class CustomTabBar extends React.Component { key={route.key} /> })} - + ); } } diff --git a/src/navigation/MainTabNavigator.js b/src/navigation/MainTabNavigator.js index 6b0ce77..154c21f 100644 --- a/src/navigation/MainTabNavigator.js +++ b/src/navigation/MainTabNavigator.js @@ -343,15 +343,6 @@ class TabNavigator extends React.Component { else return null; }, - tabBarVisible: () => { - const state = route.state; - // Get the current route in the stack - const screen = state ? state.routes[state.index] : undefined; - const params = screen ? screen.params : undefined; - const hideTabBar = params ? params.hideTabBar : undefined; - return hideTabBar !== undefined ? !hideTabBar : true; - }, - animationEnabled: true, tabBarLabel: route.name !== 'home' ? undefined : '', activeColor: this.props.theme.colors.primary, inactiveColor: this.props.theme.colors.tabIcon,