react-native 使状态栏 'barStyle' 可动画化
react-native make status bar 'barStyle' animatable
我正在尝试使状态栏的 barStyle
动画化,以便在滚动时可以将 barStyle
类型从 'dark-content' 更改为 'light-content'。
首先,我制作了状态栏动画:
const AnimatedStatusBar = Animated.createAnimatedComponent(StatusBar);
其次,设置动画值:
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"
});
最后,如果 this.HeaderBg
已更改,请更改 barStyle:
<AnimatedStatusBar barStyle={this.headerBg === 'transparent'? 'dark-content' : 'light-content'} translucent={true} />
我觉得我的代码应该可以工作,但它没有像我预期的那样工作。
知道如何在动画更改时更改状态栏 barStyle
的类型吗?
顺便说一句,我没有使用钩子。我想知道如何使用 class 个组件。
我们只能通过使用变量来设置状态栏的动画。(通过切换)
我们以暗为变量
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',
},
});
您应该使用 react-native-iphone-x-helper 来获取状态栏高度,这样您的应用程序就可以在 iphoneX 和正常 [ 上正常工作=26=]
代码:
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",
},
});
StatusBar
不是呈现状态栏的实际组件。它更像是一个方便的副作用组件,在呈现时,将强制调用将状态栏设置为在 prop 中传递的颜色。出于这个原因,你不能为它设置动画,因为它不渲染任何东西
此外,您不可能在 "light-content" 和 "dark-content" 之间设置动画,因为一个是深色背景的白色文本,另一个是白色背景的深色文本,它们之间没有中间值
您可以将背景颜色从一种更改为另一种(无需插值!)。您可以仅使用 imperative 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 />
绘制您自己的状态栏并为其背景颜色设置动画
我正在尝试使状态栏的 barStyle
动画化,以便在滚动时可以将 barStyle
类型从 'dark-content' 更改为 'light-content'。
首先,我制作了状态栏动画:
const AnimatedStatusBar = Animated.createAnimatedComponent(StatusBar);
其次,设置动画值:
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"
});
最后,如果 this.HeaderBg
已更改,请更改 barStyle:
<AnimatedStatusBar barStyle={this.headerBg === 'transparent'? 'dark-content' : 'light-content'} translucent={true} />
我觉得我的代码应该可以工作,但它没有像我预期的那样工作。
知道如何在动画更改时更改状态栏 barStyle
的类型吗?
顺便说一句,我没有使用钩子。我想知道如何使用 class 个组件。
我们只能通过使用变量来设置状态栏的动画。(通过切换)
我们以暗为变量
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',
},
});
您应该使用 react-native-iphone-x-helper 来获取状态栏高度,这样您的应用程序就可以在 iphoneX 和正常 [ 上正常工作=26=]
代码:
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",
},
});
StatusBar
不是呈现状态栏的实际组件。它更像是一个方便的副作用组件,在呈现时,将强制调用将状态栏设置为在 prop 中传递的颜色。出于这个原因,你不能为它设置动画,因为它不渲染任何东西
此外,您不可能在 "light-content" 和 "dark-content" 之间设置动画,因为一个是深色背景的白色文本,另一个是白色背景的深色文本,它们之间没有中间值
您可以将背景颜色从一种更改为另一种(无需插值!)。您可以仅使用 imperative 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 />
绘制您自己的状态栏并为其背景颜色设置动画