基于多个ScrollView动画单个视图

Aze*_*sni 25 javascript animation android ios react-native

我正在开发一个应用程序,我正在尝试View基于多个ScrollViews的滚动位置进行动画处理.

这就是屏​​幕的外观.

档案画面

上面的屏幕有两个部分

  • ViewTop上的一个组件
  • TabNavigator底部的一个组件

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

问题

当我在tab1上滚动一点并移动到tab2并尝试滚动时,它会变得生涩.看到GIF了解我想说的话

React Native Animation 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*/})
Run Code Online (Sandbox Code Playgroud)

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>
    )
  }
}
Run Code Online (Sandbox Code Playgroud)

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>
    )
  }
}
Run Code Online (Sandbox Code Playgroud)

我不知道如何克服这个问题,任何建议和解决方案都表示赞赏.

谢谢.

小智 5

尝试使用Animated.add()

所以你需要在 App

const tab1ScrollY = new Animated.Value(0)
const tab2ScrollY = new Animated.Value(0)
const scrollY = Animated.add(tab1ScrollY,tab2ScrollY)
Run Code Online (Sandbox Code Playgroud)

scrollY它是tab1 scroll+ 的偏移量tab2 scroll


Obs*_*ver 2

I've never used react-native, but I can definitely say why you have this issue. I used debugging tool and I figured out that when you clicked on the tab and app calls this portion of the code every time:

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'
    });
Run Code Online (Sandbox Code Playgroud)

where this.state.scrollY = new Animated.Value(0) all the time.

基本上,这意味着当您单击选项卡并开始滚动时,它将从 0 开始滚动。您需要找到一个解决方案来记住 Animated.Value 的先前状态或更改动画的输入/输出范围。

以下是如何从 App.js 中单击选项卡的示例:

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

希望它能帮助你。