Browse Source

Hide qr code fab button when scrolling down using spring animation

Arnaud Vergnet 4 years ago
parent
commit
f88c98537a
2 changed files with 72 additions and 14 deletions
  1. 5
    2
      src/components/Lists/WebSectionList.js
  2. 67
    12
      src/screens/HomeScreen.js

+ 5
- 2
src/components/Lists/WebSectionList.js View File

@@ -4,7 +4,7 @@ import * as React from 'react';
4 4
 import {ERROR_TYPE, readData} from "../../utils/WebData";
5 5
 import i18n from "i18n-js";
6 6
 import {Snackbar} from 'react-native-paper';
7
-import {RefreshControl, SectionList, View} from "react-native";
7
+import {Animated, RefreshControl, View} from "react-native";
8 8
 import ErrorView from "../Custom/ErrorView";
9 9
 import BasicLoadingScreen from "../Custom/BasicLoadingScreen";
10 10
 
@@ -19,6 +19,7 @@ type Props = {
19 19
     createDataset: Function,
20 20
     updateData: number,
21 21
     itemHeight: number | null,
22
+    onScroll: Function,
22 23
 }
23 24
 
24 25
 type State = {
@@ -178,7 +179,7 @@ export default class WebSectionList extends React.PureComponent<Props, State> {
178 179
         return (
179 180
             <View>
180 181
                 {/*$FlowFixMe*/}
181
-                <SectionList
182
+                <Animated.SectionList
182 183
                     sections={dataset}
183 184
                     extraData={this.props.updateData}
184 185
                     refreshControl={
@@ -203,6 +204,8 @@ export default class WebSectionList extends React.PureComponent<Props, State> {
203 204
                     }
204 205
                     removeClippedSubviews={true}
205 206
                     getItemLayout={this.props.itemHeight !== null ? this.itemLayout : undefined}
207
+                    // Animations
208
+                    onScroll={this.props.onScroll}
206 209
                 />
207 210
                 <Snackbar
208 211
                     visible={this.state.snackbarVisible}

+ 67
- 12
src/screens/HomeScreen.js View File

@@ -1,7 +1,7 @@
1 1
 // @flow
2 2
 
3 3
 import * as React from 'react';
4
-import {FlatList, StyleSheet, View} from 'react-native';
4
+import {Animated, FlatList, StyleSheet, View} from 'react-native';
5 5
 import i18n from "i18n-js";
6 6
 import DashboardItem from "../components/Home/EventDashboardItem";
7 7
 import WebSectionList from "../components/Lists/WebSectionList";
@@ -14,6 +14,7 @@ import ActionsDashBoardItem from "../components/Home/ActionsDashboardItem";
14 14
 import ConnectionManager from "../managers/ConnectionManager";
15 15
 import {CommonActions} from '@react-navigation/native';
16 16
 import MaterialHeaderButtons, {Item} from "../components/Custom/HeaderButton";
17
+import {AnimatedValue} from "react-native-reanimated";
17 18
 // import DATA from "../dashboard_data.json";
18 19
 
19 20
 
@@ -26,6 +27,8 @@ const SECTIONS_ID = [
26 27
     'news_feed'
27 28
 ];
28 29
 
30
+const AnimatedFAB = Animated.createAnimatedComponent(FAB);
31
+
29 32
 const REFRESH_TIME = 1000 * 20; // Refresh every 20 seconds
30 33
 
31 34
 type Props = {
@@ -34,19 +37,35 @@ type Props = {
34 37
     theme: Object,
35 38
 }
36 39
 
40
+type State = {
41
+    showFab: boolean,
42
+    fabPosition: AnimatedValue
43
+}
44
+
37 45
 /**
38 46
  * Class defining the app's home screen
39 47
  */
40
-class HomeScreen extends React.Component<Props> {
48
+class HomeScreen extends React.Component<Props, State> {
41 49
 
42 50
     colors: Object;
43 51
 
44 52
     isLoggedIn: boolean | null;
53
+    isAnimationDownPlaying: boolean;
54
+    isAnimationUpPlaying: boolean;
55
+
56
+    downAnimation;
57
+    upAnimation;
58
+
59
+    state = {
60
+        showFab: true,
61
+        fabPosition: new Animated.Value(0),
62
+    };
45 63
 
46 64
     constructor(props) {
47 65
         super(props);
48 66
         this.colors = props.theme.colors;
49
-
67
+        this.isAnimationDownPlaying = false;
68
+        this.isAnimationUpPlaying = false;
50 69
         this.isLoggedIn = null;
51 70
     }
52 71
 
@@ -379,7 +398,7 @@ class HomeScreen extends React.Component<Props> {
379 398
     }
380 399
 
381 400
     dashboardRowRenderItem = ({item}: Object) => {
382
-        return(
401
+        return (
383 402
             <SquareDashboardItem
384 403
                 color={item.color}
385 404
                 icon={item.icon}
@@ -398,14 +417,14 @@ class HomeScreen extends React.Component<Props> {
398 417
      */
399 418
     getDashboardRow(content: Array<Object>) {
400 419
         return <FlatList
401
-                data={content}
402
-                renderItem={this.dashboardRowRenderItem}
403
-                horizontal={true}
404
-                contentContainerStyle={{
420
+            data={content}
421
+            renderItem={this.dashboardRowRenderItem}
422
+            horizontal={true}
423
+            contentContainerStyle={{
405 424
                 marginLeft: 'auto',
406 425
                 marginRight: 'auto',
407
-                }}
408
-            />;
426
+            }}
427
+        />;
409 428
     }
410 429
 
411 430
     /**
@@ -441,6 +460,38 @@ class HomeScreen extends React.Component<Props> {
441 460
 
442 461
     openScanner = () => this.props.navigation.navigate("scanner");
443 462
 
463
+    onScroll = ({nativeEvent}: Object) => {
464
+        if (nativeEvent.velocity.y > 0.2) { // Go down
465
+            if (!this.isAnimationDownPlaying) {
466
+                this.isAnimationDownPlaying = true;
467
+                if (this.isAnimationUpPlaying)
468
+                    this.upAnimation.stop();
469
+                this.downAnimation = Animated.spring(this.state.fabPosition, {
470
+                    toValue: 100,
471
+                    duration: 50,
472
+                    useNativeDriver: true,
473
+                });
474
+                this.downAnimation.start(() => {
475
+                    this.isAnimationDownPlaying = false
476
+                });
477
+            }
478
+        } else if (nativeEvent.velocity.y < -0.2) { // Go up
479
+            if (!this.isAnimationUpPlaying) {
480
+                this.isAnimationUpPlaying = true;
481
+                if (this.isAnimationDownPlaying)
482
+                    this.downAnimation.stop();
483
+                this.upAnimation = Animated.spring(this.state.fabPosition, {
484
+                    toValue: 0,
485
+                    duration: 50,
486
+                    useNativeDriver: true,
487
+                });
488
+                this.upAnimation.start(() => {
489
+                    this.isAnimationUpPlaying = false
490
+                });
491
+            }
492
+        }
493
+    };
494
+
444 495
     render() {
445 496
         const nav = this.props.navigation;
446 497
         return (
@@ -453,9 +504,13 @@ class HomeScreen extends React.Component<Props> {
453 504
                     fetchUrl={DATA_URL}
454 505
                     renderItem={this.getRenderItem}
455 506
                     itemHeight={FEED_ITEM_HEIGHT}
507
+                    onScroll={this.onScroll}
456 508
                 />
457
-                <FAB
458
-                    style={styles.fab}
509
+                <AnimatedFAB
510
+                    style={{
511
+                        ...styles.fab,
512
+                        transform: [{translateY: this.state.fabPosition}]
513
+                    }}
459 514
                     icon="qrcode-scan"
460 515
                     onPress={this.openScanner}
461 516
                 />

Loading…
Cancel
Save