Procházet zdrojové kódy

[RN] Refactor SideBar layout and animation

Layout:

Use an absolute-fill view as the background with the sidebar on top of. This
greatly simplifies styling, as there is no need to calculate how large the
backdrop needs to be.

Animation:

Switch to a translateX transform animation. This serves 2 purposes: first,
there seems to be a bug somewhere in React Native 0.51-0.55 where the content
that is being animated starts to be clipped. Very weird! But more importantly,
translateX transmorm animations are supported by the native animation driver!

https://facebook.github.io/react-native/blog/2017/02/14/using-native-driver-for-animated.html
8f5ebe5952/Libraries/Animated/src/NativeAnimatedHelper.js (L138-L176)

This makes the animation more performant and buttery smooth.

Some small cleanups are also included here.
j8
Saúl Ibarra Corretgé před 7 roky
rodič
revize
c700261852

+ 39
- 73
react/features/base/react/components/native/SideBar.js Zobrazit soubor

@@ -1,9 +1,8 @@
1 1
 // @flow
2 2
 
3
-import React, { Component } from 'react';
3
+import React, { Component, type Node } from 'react';
4 4
 import {
5 5
     Animated,
6
-    Dimensions,
7 6
     TouchableWithoutFeedback,
8 7
     View
9 8
 } from 'react-native';
@@ -15,15 +14,10 @@ import styles, { SIDEBAR_WIDTH } from './styles';
15 14
  */
16 15
 type Props = {
17 16
 
18
-    /**
19
-     * The local participant's avatar
20
-     */
21
-    _avatar: string,
22
-
23 17
     /**
24 18
      * The children of the Component
25 19
      */
26
-    children: React$Node,
20
+    children: Node,
27 21
 
28 22
     /**
29 23
      * Callback to notify the containing Component that the sidebar is
@@ -47,11 +41,6 @@ type State = {
47 41
      */
48 42
     showOverlay: boolean,
49 43
 
50
-    /**
51
-     * Indicates whether the side bar is visible or not.
52
-     */
53
-    showSideBar: boolean,
54
-
55 44
     /**
56 45
      * The native animation object.
57 46
      */
@@ -62,8 +51,6 @@ type State = {
62 51
  * A generic animated side bar to be used for left side menus
63 52
  */
64 53
 export default class SideBar extends Component<Props, State> {
65
-    _mounted: boolean;
66
-
67 54
     /**
68 55
      * Initializes a new {@code SideBar} instance.
69 56
      *
@@ -74,15 +61,10 @@ export default class SideBar extends Component<Props, State> {
74 61
 
75 62
         this.state = {
76 63
             showOverlay: false,
77
-            showSideBar: false,
78
-            sliderAnimation: new Animated.Value(-SIDEBAR_WIDTH)
64
+            sliderAnimation: new Animated.Value(0)
79 65
         };
80 66
 
81
-        this._getContainerStyle = this._getContainerStyle.bind(this);
82 67
         this._onHideMenu = this._onHideMenu.bind(this);
83
-        this._setShow = this._setShow.bind(this);
84
-
85
-        this._setShow(props.show);
86 68
     }
87 69
 
88 70
     /**
@@ -91,7 +73,7 @@ export default class SideBar extends Component<Props, State> {
91 73
      * @inheritdoc
92 74
      */
93 75
     componentDidMount() {
94
-        this._mounted = true;
76
+        this._setShow(this.props.show);
95 77
     }
96 78
 
97 79
     /**
@@ -112,42 +94,37 @@ export default class SideBar extends Component<Props, State> {
112 94
      */
113 95
     render() {
114 96
         return (
115
-            <Animated.View
116
-                style = { this._getContainerStyle() } >
117
-                <View style = { styles.sideMenuContent }>
118
-                    {
119
-                        this.props.children
120
-                    }
121
-                </View>
122
-                <TouchableWithoutFeedback
123
-                    onPress = { this._onHideMenu }
124
-                    style = { styles.sideMenuShadowTouchable } >
125
-                    <View style = { styles.sideMenuShadow } />
126
-                </TouchableWithoutFeedback>
127
-            </Animated.View>
97
+            <View
98
+                pointerEvents = 'box-none'
99
+                style = { styles.sideMenuContainer } >
100
+                {
101
+                    this.state.showOverlay
102
+                        && <TouchableWithoutFeedback
103
+                            onPress = { this._onHideMenu } >
104
+                            <View style = { styles.sideMenuShadow } />
105
+                        </TouchableWithoutFeedback>
106
+                }
107
+                <Animated.View style = { this._getContentStyle() }>
108
+                    { this.props.children }
109
+                </Animated.View>
110
+            </View>
128 111
         );
129 112
     }
130 113
 
131
-    _getContainerStyle: () => Array<Object>
114
+    _getContentStyle: () => Array<Object>;
132 115
 
133 116
     /**
134
-     * Assembles a style array for the container.
117
+     * Assembles a style array for the sidebar content.
135 118
      *
136 119
      * @private
137 120
      * @returns {Array<Object>}
138 121
      */
139
-    _getContainerStyle() {
122
+    _getContentStyle() {
140 123
         const { sliderAnimation } = this.state;
141
-        const { height, width } = Dimensions.get('window');
142
-
143
-        return [
144
-            styles.sideMenuContainer,
145
-            {
146
-                left: sliderAnimation,
147
-                width: this.state.showOverlay
148
-                    ? Math.max(height, width) + SIDEBAR_WIDTH : SIDEBAR_WIDTH
149
-            }
150
-        ];
124
+        const transformStyle
125
+            = { transform: [ { translateX: sliderAnimation } ] };
126
+
127
+        return [ styles.sideMenuContent, transformStyle ];
151 128
     }
152 129
 
153 130
     _onHideMenu: () => void;
@@ -163,9 +140,7 @@ export default class SideBar extends Component<Props, State> {
163 140
 
164 141
         const { onHide } = this.props;
165 142
 
166
-        if (typeof onHide === 'function') {
167
-            onHide();
168
-        }
143
+        onHide && onHide();
169 144
     }
170 145
 
171 146
     _setShow: (boolean) => void;
@@ -178,30 +153,21 @@ export default class SideBar extends Component<Props, State> {
178 153
      * @returns {void}
179 154
      */
180 155
     _setShow(show) {
181
-        if (this.state.showSideBar !== show) {
182
-            if (show) {
183
-                this.setState({
184
-                    showOverlay: true
185
-                });
186
-            }
187
-
188
-            Animated
189
-                .timing(
190
-                    this.state.sliderAnimation,
191
-                    { toValue: show ? 0 : -SIDEBAR_WIDTH })
192
-                .start(animationState => {
193
-                    if (animationState.finished && !show) {
194
-                        this.setState({
195
-                            showOverlay: false
196
-                        });
197
-                    }
198
-                });
156
+        if (show) {
157
+            this.setState({ showOverlay: true });
199 158
         }
200 159
 
201
-        if (this._mounted) {
202
-            this.setState({
203
-                showSideBar: show
160
+        Animated
161
+            .timing(
162
+                this.state.sliderAnimation,
163
+                {
164
+                    toValue: show ? SIDEBAR_WIDTH : 0,
165
+                    useNativeDriver: true
166
+                })
167
+            .start(animationState => {
168
+                if (animationState.finished && !show) {
169
+                    this.setState({ showOverlay: false });
170
+                }
204 171
             });
205
-        }
206 172
     }
207 173
 }

+ 8
- 17
react/features/base/react/components/native/styles.js Zobrazit soubor

@@ -278,36 +278,27 @@ const SIDEBAR_STYLES = {
278 278
      * The topmost container of the side bar.
279 279
      */
280 280
     sideMenuContainer: {
281
-        bottom: 0,
282
-        flexDirection: 'row',
283
-        left: -SIDEBAR_WIDTH,
284
-        position: 'absolute',
285
-        top: 0,
286
-        width: SIDEBAR_WIDTH
281
+        ...StyleSheet.absoluteFillObject
287 282
     },
288 283
 
289 284
     /**
290 285
      * The container of the actual content of the side menu.
291 286
      */
292 287
     sideMenuContent: {
288
+        bottom: 0,
289
+        left: -SIDEBAR_WIDTH,
290
+        position: 'absolute',
291
+        top: 0,
293 292
         width: SIDEBAR_WIDTH
294 293
     },
295 294
 
296 295
     /**
297
-     * The opaque area that covers the rest of the scren, when
296
+     * The opaque area that covers the rest of the screen, when
298 297
      * the side bar is open.
299 298
      */
300 299
     sideMenuShadow: {
301
-        backgroundColor: 'rgba(0, 0, 0, 0.5)',
302
-        flex: 1
303
-    },
304
-
305
-    /**
306
-     * The touchable area of the rest of the screen that closes the side bar
307
-     * when tapped.
308
-     */
309
-    sideMenuShadowTouchable: {
310
-        flex: 1
300
+        ...StyleSheet.absoluteFillObject,
301
+        backgroundColor: 'rgba(0, 0, 0, 0.5)'
311 302
     }
312 303
 };
313 304
 

Načítá se…
Zrušit
Uložit