Hide qr code fab button when scrolling down using spring animation

This commit is contained in:
Arnaud Vergnet 2020-04-12 21:53:47 +02:00
parent 7128a68641
commit f88c98537a
2 changed files with 72 additions and 14 deletions

View file

@ -4,7 +4,7 @@ import * as React from 'react';
import {ERROR_TYPE, readData} from "../../utils/WebData"; import {ERROR_TYPE, readData} from "../../utils/WebData";
import i18n from "i18n-js"; import i18n from "i18n-js";
import {Snackbar} from 'react-native-paper'; import {Snackbar} from 'react-native-paper';
import {RefreshControl, SectionList, View} from "react-native"; import {Animated, RefreshControl, View} from "react-native";
import ErrorView from "../Custom/ErrorView"; import ErrorView from "../Custom/ErrorView";
import BasicLoadingScreen from "../Custom/BasicLoadingScreen"; import BasicLoadingScreen from "../Custom/BasicLoadingScreen";
@ -19,6 +19,7 @@ type Props = {
createDataset: Function, createDataset: Function,
updateData: number, updateData: number,
itemHeight: number | null, itemHeight: number | null,
onScroll: Function,
} }
type State = { type State = {
@ -178,7 +179,7 @@ export default class WebSectionList extends React.PureComponent<Props, State> {
return ( return (
<View> <View>
{/*$FlowFixMe*/} {/*$FlowFixMe*/}
<SectionList <Animated.SectionList
sections={dataset} sections={dataset}
extraData={this.props.updateData} extraData={this.props.updateData}
refreshControl={ refreshControl={
@ -203,6 +204,8 @@ export default class WebSectionList extends React.PureComponent<Props, State> {
} }
removeClippedSubviews={true} removeClippedSubviews={true}
getItemLayout={this.props.itemHeight !== null ? this.itemLayout : undefined} getItemLayout={this.props.itemHeight !== null ? this.itemLayout : undefined}
// Animations
onScroll={this.props.onScroll}
/> />
<Snackbar <Snackbar
visible={this.state.snackbarVisible} visible={this.state.snackbarVisible}

View file

@ -1,7 +1,7 @@
// @flow // @flow
import * as React from 'react'; import * as React from 'react';
import {FlatList, StyleSheet, View} from 'react-native'; import {Animated, FlatList, StyleSheet, View} from 'react-native';
import i18n from "i18n-js"; import i18n from "i18n-js";
import DashboardItem from "../components/Home/EventDashboardItem"; import DashboardItem from "../components/Home/EventDashboardItem";
import WebSectionList from "../components/Lists/WebSectionList"; import WebSectionList from "../components/Lists/WebSectionList";
@ -14,6 +14,7 @@ import ActionsDashBoardItem from "../components/Home/ActionsDashboardItem";
import ConnectionManager from "../managers/ConnectionManager"; import ConnectionManager from "../managers/ConnectionManager";
import {CommonActions} from '@react-navigation/native'; import {CommonActions} from '@react-navigation/native';
import MaterialHeaderButtons, {Item} from "../components/Custom/HeaderButton"; import MaterialHeaderButtons, {Item} from "../components/Custom/HeaderButton";
import {AnimatedValue} from "react-native-reanimated";
// import DATA from "../dashboard_data.json"; // import DATA from "../dashboard_data.json";
@ -26,6 +27,8 @@ const SECTIONS_ID = [
'news_feed' 'news_feed'
]; ];
const AnimatedFAB = Animated.createAnimatedComponent(FAB);
const REFRESH_TIME = 1000 * 20; // Refresh every 20 seconds const REFRESH_TIME = 1000 * 20; // Refresh every 20 seconds
type Props = { type Props = {
@ -34,19 +37,35 @@ type Props = {
theme: Object, theme: Object,
} }
type State = {
showFab: boolean,
fabPosition: AnimatedValue
}
/** /**
* Class defining the app's home screen * Class defining the app's home screen
*/ */
class HomeScreen extends React.Component<Props> { class HomeScreen extends React.Component<Props, State> {
colors: Object; colors: Object;
isLoggedIn: boolean | null; isLoggedIn: boolean | null;
isAnimationDownPlaying: boolean;
isAnimationUpPlaying: boolean;
downAnimation;
upAnimation;
state = {
showFab: true,
fabPosition: new Animated.Value(0),
};
constructor(props) { constructor(props) {
super(props); super(props);
this.colors = props.theme.colors; this.colors = props.theme.colors;
this.isAnimationDownPlaying = false;
this.isAnimationUpPlaying = false;
this.isLoggedIn = null; this.isLoggedIn = null;
} }
@ -441,6 +460,38 @@ class HomeScreen extends React.Component<Props> {
openScanner = () => this.props.navigation.navigate("scanner"); openScanner = () => this.props.navigation.navigate("scanner");
onScroll = ({nativeEvent}: Object) => {
if (nativeEvent.velocity.y > 0.2) { // Go down
if (!this.isAnimationDownPlaying) {
this.isAnimationDownPlaying = true;
if (this.isAnimationUpPlaying)
this.upAnimation.stop();
this.downAnimation = Animated.spring(this.state.fabPosition, {
toValue: 100,
duration: 50,
useNativeDriver: true,
});
this.downAnimation.start(() => {
this.isAnimationDownPlaying = false
});
}
} else if (nativeEvent.velocity.y < -0.2) { // Go up
if (!this.isAnimationUpPlaying) {
this.isAnimationUpPlaying = true;
if (this.isAnimationDownPlaying)
this.downAnimation.stop();
this.upAnimation = Animated.spring(this.state.fabPosition, {
toValue: 0,
duration: 50,
useNativeDriver: true,
});
this.upAnimation.start(() => {
this.isAnimationUpPlaying = false
});
}
}
};
render() { render() {
const nav = this.props.navigation; const nav = this.props.navigation;
return ( return (
@ -453,9 +504,13 @@ class HomeScreen extends React.Component<Props> {
fetchUrl={DATA_URL} fetchUrl={DATA_URL}
renderItem={this.getRenderItem} renderItem={this.getRenderItem}
itemHeight={FEED_ITEM_HEIGHT} itemHeight={FEED_ITEM_HEIGHT}
onScroll={this.onScroll}
/> />
<FAB <AnimatedFAB
style={styles.fab} style={{
...styles.fab,
transform: [{translateY: this.state.fabPosition}]
}}
icon="qrcode-scan" icon="qrcode-scan"
onPress={this.openScanner} onPress={this.openScanner}
/> />