Search code examples
reactjsreact-nativeanimationreact-native-animatable

react-native make status bar 'barStyle' animatable


I'm trying to make status bar's barStyle animated so that when I scroll I could change the barStyle type from 'dark-content' to 'light-content'.

First, I made my statusBar animated:

const AnimatedStatusBar = Animated.createAnimatedComponent(StatusBar);

Second, set Animated Value:

scroll = new Animated.Value(0);

  tabY = this.nScroll.interpolate({
    inputRange: [0, SCROLL_HEIGHT, SCROLL_HEIGHT],
    outputRange: [0, 0, 1]
  });
  headerBg = this.scroll.interpolate({
    inputRange: [0, SCROLL_HEIGHT, SCROLL_HEIGHT],
    outputRange: ["black", 'white'],
    extrapolate: "clamp"
  });

Finally, change the barStyle if this.HeaderBg has changed:

<AnimatedStatusBar barStyle={this.headerBg === 'transparent'? 'dark-content' : 'light-content'} translucent={true} /> 

I feel like my code should work but it is not working as I expected.

Any idea how I could change the type of the statusBar's barStyle when animated has changed?

By the way I am not using hooks. I want to know how to do it with class components.


Solution

  • We can only animate the status bar by using a variable.(by toggling)

    enter image description here

    let's take dark as the variable.

    state = {
      dark: true,
    };
    

    initially, it's true. so the status bar style should be dark.

    <StatusBar
        barStyle={dark ? 'dark-content' : 'light-content'}
        translucent
        backgroundColor="transparent"
    />
    

    The toggle is done inside on scroll method. here I am using 100 as an offset.

    onScroll = ({nativeEvent}) => {
      let y = nativeEvent.contentOffset.y;
      this.scroll.setValue(y); // set scroll animation value here
      const {dark} = this.state;
      let scrollValue = y;
      if (scrollValue > 100 && dark) {
        this.setState({dark: false});
      }
      if (scrollValue < 100 && !dark) {
        this.setState({dark: true});
      }
    };
    

    Example Code

    import React, {Component} from 'react';
    import {
      View,
      StatusBar,
      StyleSheet,
      ScrollView,
      Dimensions,
      Animated,
    } from 'react-native';
    const {height} = Dimensions.get('window');
    
    export default class Home extends Component {
      scroll = new Animated.Value(0);
      state = {
        dark: true,
      };
      onScroll = ({nativeEvent}) => {
        let y = nativeEvent.contentOffset.y;
        this.scroll.setValue(y); // set scroll animation value here
        const {dark} = this.state;
        let scrollValue = y;
        if (scrollValue > 100 && dark) {
          this.setState({dark: false});
        }
        if (scrollValue < 100 && !dark) {
          this.setState({dark: true});
        }
      };
      render() {
        const {dark} = this.state;
        return (
          <View style={styles.container}>
            <StatusBar
              barStyle={dark ? 'dark-content' : 'light-content'}
              translucent
              backgroundColor="transparent"
            />
            <ScrollView
              style={styles.ScrollView}
              contentContainerStyle={styles.scrollContainer}
              onScroll={this.onScroll}>
              <View style={styles.item} />
            </ScrollView>
          </View>
        );
      }
    }
    
    const styles = StyleSheet.create({
      container: {
        flex: 1,
      },
      ScrollView: {
        flex: 1,
      },
      scrollContainer: {
        height: height * 2,
        backgroundColor: '#000',
      },
      item: {
        height: 100,
        backgroundColor: '#fff',
      },
    });