2

我正在尝试使状态栏barStyle动画化,这样当我滚动时,我可以将barStyle类型从“dark-content”更改为“light-content”。

首先,我制作了我的 statusBar 动画:

const AnimatedStatusBar = Animated.createAnimatedComponent(StatusBar);

二、设置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"
  });

最后,如果 barStylethis.HeaderBg已更改,则更改:

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

我觉得我的代码应该可以工作,但没有按预期工作。

知道barStyle当动画更改时如何更改状态栏的类型吗?

顺便说一句,我没有使用钩子。我想知道如何使用类组件来做到这一点。

4

3 回答 3

3

我们只能通过使用变量来为状态栏设置动画。(通过切换)

在此处输入图像描述

让我们将黑暗作为变量。

state = {
  dark: true,
};

最初,这是真的。所以状态栏样式应该是深色的。

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

切换是在滚动方法内部完成的。这里我使用 100 作为偏移量。

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});
  }
};

示例代码

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',
  },
});

于 2020-05-22T08:22:42.770 回答
2

StatusBar不是呈现状态栏的实际组件。它更像是一个方便的副作用组件,在渲染时,它将发出命令式调用以将状态栏设置为在道具中传递的颜色。出于这个原因,您无法对其进行动画处理,因为它不会渲染任何内容

此外,您不可能在“浅色内容”和“深色内容”之间制作动画,因为一个是深色背景上的白色文本,另一个是白色背景上的深色文本,它们之间没有中间值

您可以做的是您可以将背景颜色从一种更改为另一种(无需插值!)。您可以只使用命令式 api来实现它

class App extends React.Component {

  lastColor = null

  componentDidMount() {
    this.nScroll.addListener(({ value }) => {
      if (value < SCROLL_HEIGHT) {
        this.setStatusBarColor('black')
      } else {
        this.setStatusBarColor('white')
      }
    });
  }

  setStatusBarColor = (newColor) => {
    if (newColor !== this.lastColor) {
      StatusBar.setBackgroundColor(newColor)
    }
  }

  ///...
}

请注意,在这种情况下,您不需要渲染<StatusBar />,因为所有颜色更改都是强制处理的

如果您希望状态栏通过插值改变颜色,您唯一的选择是将其设置为半透明StatusBar.setTranslucent(true),然后用简单的方式绘制您自己的状态栏<View />并为其背景颜色设置动画

于 2020-05-24T01:31:11.213 回答
1

您应该使用react-native-iphone-x-helper来获取状态栏高度,以便您的应用程序可以在iphoneX和普通iphone上正常工作

代码:

import React, { Component } from "react";
import {
  View,
  StatusBar,
  StyleSheet,
  ScrollView,
  Dimensions,
  Animated,
} from "react-native";
const { height } = Dimensions.get("window");
import { getStatusBarHeight } from "react-native-iphone-x-helper";

const statusBarHeight = getStatusBarHeight();

export default class App 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 > statusBarHeight && dark) {
      this.setState({ dark: false });
    }
    if (scrollValue < statusBarHeight && !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}
          scrollEventThrottle={16}
          contentContainerStyle={styles.contentContainerStyle}
          onScroll={this.onScroll}
        >
          <View style={styles.item} />
        </ScrollView>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
  },
  ScrollView: {
    flex: 1,
  },
  contentContainerStyle: {
    height: height * 2,
    backgroundColor: "#000",
  },
  item: {
    height: 100,
    backgroundColor: "#FFFFFF",
  },
});

iphone x 苹果手机

于 2020-05-22T11:00:48.863 回答