![](/img/trans.png)
[英]Not able to access the absolute position view in react-native android
[英]react-native : change view corresponding to scroll position
我正在使用Animation.view
来更改header
的height
和background
。
我设置我的height
和background
设置是这样的:
const HeaderHeight = this.state.scrollY.interpolate({
inputRange:[0, Header_Max_Height - Header_Min_Height],
outputRange:[Header_Max_Height, Header_Min_Height],
extrapolate:'clamp'
})
const AnimateHeaderBackgroundColor = this.state.scrollY.interpolate({
inputRange: [ 0, ( Header_Max_Height - Header_Min_Height ) ],
outputRange: [ '#009688', '#00BCD4' ],
extrapolate: 'clamp'
})
这是我的动画视图。
<Animated.View style={{width:'100%', height: HeaderHeight, backgroundColor:AnimateHeaderBackgroundColor}}></Animated.View>
一切正常。
我的问题是有没有一种方法可以更改视图,例如height
和backgroundcolor
?
例如,假设我有两种观点:
//view1
<View style={{width:'100%',height:100, backgroundColor:'red'}}>
<Text>View1</Text>
</View>
//view2
<View style={{width:'100%',height:100, backgroundColor:'blue'}}>
<Text>View2</Text>
</View>
我希望view1
默认显示并在我滚动到屏幕顶部时显示view2
。 将View
放在outputRange
会使这成为可能吗?
我想如果你想改变视图,在 RN 中没有直接的方法,但是,在你的情况下,我可以想出一个混合使用opacity
, position: absolute
和interpolate()
的小技巧,这是一个最小的例子可以直接复制粘贴测试一下:
import React, { Component } from 'react';
import { StyleSheet, Animated, View, ScrollView } from 'react-native';
class AnimationExample extends Component {
constructor(props) {
super(props)
this.state = {
showBlueView: false,
animatedOpacityValue: new Animated.Value(0),
}
}
handleScroll = (event) => {
const { animatedOpacityValue, showBlueView } = this.state;
const scrollPosition = event.nativeEvent.contentOffset.y;
if (scrollPosition > 100 && !showBlueView) {
Animated.timing(animatedOpacityValue, {
toValue: 1,
}).start(() => this.setState({ showBlueView: true }))
}
if (scrollPosition < 100 && showBlueView) {
Animated.timing(animatedOpacityValue, {
toValue: 0,
}).start(() => this.setState({ showBlueView: false }))
}
}
render() {
const { animatedOpacityValue } = this.state;
return (
<ScrollView
style={styles.scrollView}
onScroll={this.handleScroll}
scrollEventThrottle={16}
>
<View style={styles.green} />
<View style={styles.animatedViewsPositioner}>
<Animated.View
style={{
...styles.red,
opacity: animatedOpacityValue.interpolate({
inputRange: [0, 1],
outputRange: [1, 0],
}),
}}
/>
<Animated.View
style={{
...styles.blue,
opacity: animatedOpacityValue.interpolate({
inputRange: [0, 1],
outputRange: [0, 1],
}),
}}
/>
</View>
</ScrollView>
)
}
}
const styles = StyleSheet.create({
scrollView: {
flex: 1,
},
green: {
height: 600,
width: '100%',
backgroundColor: 'green',
},
red: {
height: 300,
width: '100%',
backgroundColor: 'red',
},
blue: {
position: 'absolute',
height: 300,
width: '100%',
backgroundColor: 'blue',
},
animatedViewsPositioner: {
position: 'relative',
},
})
在上面的例子中,我第一接入通过施加滚动位置handleScroll
功能的scrollView
。 确保将scrollEventThrottle
设置为 16 以确保每秒触发该功能,但要注意由此可能导致的性能问题(如果您关心,可以查看此了解更多信息)。
为了实现当用户滚动到某个位置时触发的视图更改(实际上不是,但看起来像那样),我使用一个view
来包装红色和蓝色视图,红色的默认为opacity: 1
,而蓝色的默认opacity: 0
的一个,位于红色的顶部。
我通过使用interpolate()
它们的opacity
动画来隐藏红色视图并显示蓝色视图。 在此帮助下,两个不透明度值都由一个放在状态中的 animationValue animatedOpacityValue
控制。 我添加了一个状态showBlueView
通过避免不断设置由 onScroll 触发的状态来优化性能。
这是在两个视图上添加touchableOpacities
的更新,只需在未使用时隐藏蓝色视图即可实现。
首先,添加一个日志功能:
log = (stringToPrint) => () => {
console.log(stringToPrint)
}
其次,改变scrollView
通过增加两个这样touchableOpacity
<ScrollView
style={styles.scrollView}
onScroll={this.handleScroll}
scrollEventThrottle={16}
>
<View style={styles.green} />
<View style={styles.animatedViewsPositioner}>
<Animated.View
style={{
...styles.red,
opacity: animatedOpacityValue.interpolate({
inputRange: [0, 1],
outputRange: [1, 0],
}),
}}
>
<TouchableOpacity
style={{ backgroundColor: 'black', width: 80, height: 30 }}
onPress={this.log('click on red')}
/>
</Animated.View>
{showBlueView && (
<Animated.View
style={{
...styles.blue,
opacity: animatedOpacityValue.interpolate({
inputRange: [0, 1],
outputRange: [0, 1],
}),
}}
>
<TouchableOpacity
style={{ backgroundColor: 'black', width: 80, height: 30 }}
onPress={this.log('click on blue')}
/>
</Animated.View>
)}
</View>
</ScrollView>
请注意,我添加了showBlueView &&
以在不透明度为 0 时隐藏蓝色视图,以便它不会阻止应用于红色视图的任何点击事件(即使蓝色视图被隐藏,它实际上位于红色视图之上opacity: 0
)。
@Andus 对Animated.event
回答
我们的想法是获取最新的 scrollY,然后将其包装为视图的不透明度。 蓝色目标的示例输入范围为 0-50,不透明度为 1 到 0。这意味着它会在向下滚动前 50 像素时淡出。
红色的是反向的,输入范围为 0-200,不透明度为 0 到 1。(淡入)
import React, { Component } from 'react';
import { StyleSheet, Animated, View, ScrollView, SafeAreaView } from 'react-native';
export default class AnimationExample extends Component {
constructor(props) {
super(props)
this.state = {
scrollY: new Animated.Value(0)
}
}
render() {
const {scrollY} = this.state;
return (
<SafeAreaView style={{flex: 1}}>
<ScrollView
style={styles.scrollView}
onScroll={Animated.event(
[{nativeEvent: {contentOffset: {y: this.state.scrollY}}}]
)}
scrollEventThrottle={16}
>
<View style={styles.animatedViewsPositioner}>
<Animated.View
style={[styles.box, styles.target, {
opacity: scrollY.interpolate({
inputRange: [0, 50],
outputRange: [1, 0],
}),
}]}
/>
<Animated.View
style={[styles.box, styles.origin, {
opacity: scrollY.interpolate({
inputRange: [0, 200],
outputRange: [0, 1],
}),
}]}
/>
</View>
</ScrollView>
</SafeAreaView>
)
}
}
const styles = StyleSheet.create({
scrollView: {
flex: 1,
},
box: {
height: 1000,
width: '100%',
position: 'absolute'
},
origin: {
backgroundColor: 'red',
zIndex: 1
},
target: {
backgroundColor: 'blue',
zIndex: 2
},
animatedViewsPositioner: {
position: 'relative',
backgroundColor: 'pink',
height: 10000
},
})
如果您在显示View
使用ScrollView
,我相信您可以使用onScroll
回调来获取屏幕在ScrollView
的位置,并在用户滚动到顶部时动态更改高度和颜色。
<ScrollView onScroll={this.handleScroll} />
并获得职位,
handleScroll: function(event: Object) {
console.log(event.nativeEvent.contentOffset.y);
},
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.