我正在开发一个应用程序,我正在尝试根据多个View
的滚动位置动画ScrollView
。
这就是屏幕的外观。
以上屏幕有两部分
View
组件
TabNavigator
组件 TabNavigator
中的每个标签都有一个ScrollView
(在这种情况下有2个但可以更多),我想要实现的是以用户身份折叠View
当用户向上滚动时向下滚动并展开它。
在一个标签上,我做得很好,它正是我想要它的工作方式,但是当我添加第二个标签时出现问题。
问题
当我在tab1上滚动一下并移动到tab2并尝试滚动时,它会变得生涩。看GIF了解我想说的是什么
在expo.io上查看这个小吃以查看问题
我尝试了什么
App.js
export default class App extends Component {
constructor (props) {
super(props)
this.state = {
/* omitted - not related */
scrollY: new Animated.Value(0)
}
}
render () {
let translateY = this.state.scrollY.interpolate({
inputRange: [0, 600],
outputRange: [0, -290],
extrapolate: 'clamp'
});
let TabsTranslateY = this.state.scrollY.interpolate({
inputRange: [0, 600],
outputRange: [0, -290],
extrapolate: 'clamp'
});
return (
<View style={styles.container}>
<Animated.View style={{transform: [{translateY: translateY}], overflow: 'hidden'}}>
<Text style={styles.welcome}>
Welcome to React Native!!
</Text>
<Text style={styles.time}>
{this.state.hour} : {this.state.minute}
</Text>
<TouchableOpacity onPress={() => { /* omitted */ }} style={styles.button}><Text style={styles.buttonText}>Set Time</Text></TouchableOpacity>
</Animated.View>
<Animated.View style={{
flex: 0,
transform: [{translateY: TabsTranslateY}],
height: Dimensions.get('window').height
}}>
<Tabs removeClippedSubviews={false} screenProps={{animatedScrollY: this.state.scrollY}}/>
</Animated.View>
</View>
)
}
}
const styles = StyleSheet.create({/* omitted styles*/})
Home.js(Tab1)
/* omitted imports */
export default class Home extends Component {
/* omitted navigation options */
constructor (props) {
super(props)
this.state = {
scrollY: this.props.screenProps.animatedScrollY
}
}
render () {
return (
<View>
<Animated.ScrollView onScroll={Animated.event(
[{nativeEvent: {contentOffset: {y: this.state.scrollY}}}],
{useNativeDriver: true}
)} scrollEventThrottle={16}>
{Array(90).fill().map((v, i) => {
return <Text key={i}
style={{flex: 1, backgroundColor: '#333', padding: 20, marginVertical: 10, color: 'white'}}>Item
#{i + 1}</Text>
})}
</Animated.ScrollView>
</View>
)
}
}
Photos.js(Tab2)
/* omitted imports */
export default class Photos extends Component {
/* omitted navigation options */
constructor (props) {
super(props)
this.state = {
PhotosScrollY: this.props.screenProps.animatedScrollY
}
}
render () {
return (
<Animated.ScrollView onScroll={Animated.event(
[{nativeEvent: {contentOffset: {y: this.state.PhotosScrollY}}}],
{useNativeDriver: true}
)} scrollEventThrottle={16}>
<View style={{flex: 1,}}>
{Array(90).fill().map((v, i) => {
return <View key={i} style={/* omitted */}>
<Text style={/* omitted */}>
Photo #{i + 1}
</Text>
</View>
})}
</View>
</Animated.ScrollView>
)
}
}
我不确定如何克服这个问题,我们非常感谢任何建议和解决方案。
感谢。
答案 0 :(得分:4)
尝试使用Animated.add()
所以你需要App
const tab1ScrollY = new Animated.Value(0)
const tab2ScrollY = new Animated.Value(0)
const scrollY = Animated.add(tab1ScrollY,tab2ScrollY)
scrollY
tab1 scroll
+ tab2 scroll
答案 1 :(得分:3)
我遇到了这个问题。我试着这样解决它。 (优化它仍然..)
<ParentComponent>
<CollapsibleHeader/>
<TabNavigator/>
</ParentComponent>
scrollState位于Parent Component中,TabNavigator中的选项卡具有scrollView。 我在绑定Animation事件后使用回调更新父组件中的状态。
因此,无论何时在两个选项卡之间移动,状态都位于父组件中,并从另一个位置更新。
可能这可以帮到你。
注意:仍在优化它。
--------- --------编辑
父组件:
州:scrollY: new Animated.Value(0)
componentDidMount(){
binding event.
}
componentWillUnmount(){
Unbind event.
}
onScrollEventCaptured(){
(update parent state and send it to <CollapsibleHeader/>)*
}
标签1: 这有当地的州。 (优化这部分) ,scrollY:new Animated.Value(0)
有一个ListView
ListView上的onScroll函数:
onScroll={Animated.event([{
nativeEvent: {
contentOffset: {
y: this.state.scrollY
}
}
}], {
listener: (event) => {
AppEvents.fire("topBar", this.state.scrollY);
},
})}
AppEvents.fire()是在Parent中捕获的事件。 (捕获的事件然后设置状态,然后作为道具传递给实际动画的。)*
对于标签2: 与标签1相同。
*两者都相同。
仍在对此进行优化工作。对我来说动画在iOS开发中有点不稳定,但在iOS应用程序中看起来很棒。 Android无处不在它的生涩。
答案 2 :(得分:2)
我从未使用过本地反应,但我可以肯定地说你为什么会遇到这个问题。我使用了调试工具,我发现当你点击选项卡时,应用程序每次都会调用这部分代码:
let translateY = this.state.scrollY.interpolate({
inputRange: [0, 600],
outputRange: [0, -290],
extrapolate: 'clamp'
});
let TabsTranslateY = this.state.scrollY.interpolate({
inputRange: [0, 600],
outputRange: [0, -290],
extrapolate: 'clamp'
});
始终this.state.scrollY = new Animated.Value(0)
。
基本上,这意味着当您单击选项卡并开始滚动时,它将从0滚动。您需要找到一个解决方案,记住Animated.Value的先前状态或更改动画的输入/输出范围。
以下是如何点击App.js中的标签的示例:
<Tabs removeClippedSubviews={false} screenProps={{animatedScrollY: this.state.scrollY}}
onNavigationStateChange={(prevState, currentState,action) => {
console.log(currentState);
}}
/>
希望它会对你有帮助。