基于多个ScrollViewanimation单个视图

我正在尝试基于多个ScrollView的滚动位置来设置Viewanimation

这是屏幕的外观。

配置文件屏幕

上面的屏幕有2个部分

  • 顶部的View组件
  • 底部的TabNavigator组件

TabNavigator中的每个选项卡都有一个ScrollView (在这种情况下,有2个,但可以更多),我想实现的是当用户向下滚动时折叠View ,并在用户向上滚动时展开。 在一个标签上,我做得很好,它正在按照我想要的方式工作,但是当我添加第二个标签时,问题就出现了。

问题

当我在tab1上滚动一下并移动到tab2并尝试滚动时,它会变干。 看到GIF了解我想说什么

反应本机动画Jerk


更新

查看expo.io上的这个零食,看现场的问题

snack.expo.io/SytBkdBAW


我试过了

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

我不知道如何克服这个问题,任何build议和解决scheme,表示赞赏。

谢谢。

尝试使用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的偏移量

我面临这个问题。 我试过这样解决 (优化它仍然..)

 <ParentComponent> <CollapsibleHeader/> <TabNavigator/> </ParentComponent> 

scrollState位于父组件中,并且TabNavigator中的选项卡具有scrollView。 绑定Animation事件后,使用callback更新父组件中的状态。

因此,无论何时在两个选项卡之间移动,状态都位于父组件中,并且会从其他位置进行更新。

可能是这可以帮助你。

注意:仍在优化它。

– – – – -编辑 – – – –

父组件:

状态: 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中捕获的事件。 (捕获的事件然后设置状态,然后作为道具传递给实际animation。)*

对于选项卡2:与选项卡1相同。

*两者都是一样的。

仍然在做这个优化工作。 我的animation在iOS开发中很小,但在生产iOS应用程序中看起来不错。 Android在任何地方都没有词干。

我从来没有使用反原生,但我可以肯定地说,你为什么有这个问题。 我用debugging工具,我发现,当你点击标签和应用程序每次调用这部分的代码:

 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开始滚动。你需要find一个解决scheme记住Animated.Value的前一个状态,或者改变animation的input/输出范围。

这里是示例如何获得从App.js选项卡上单击:

 <Tabs removeClippedSubviews={false} screenProps={{animatedScrollY: this.state.scrollY}} onNavigationStateChange={(prevState, currentState,action) => { console.log(currentState); }} /> 

希望它会帮助你。