react-native :根据滚动位置更改视图

kir*_*imi 8 javascript react-native

我使用的Animation.view改变heightbackgroundheader

我设置我的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'
    })
Run Code Online (Sandbox Code Playgroud)

这是我的动画视图。

<Animated.View style={{width:'100%', height: HeaderHeight, backgroundColor:AnimateHeaderBackgroundColor}}></Animated.View>
Run Code Online (Sandbox Code Playgroud)

一切正常。

我的问题是有没有一种方法可以像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>
Run Code Online (Sandbox Code Playgroud)

我希望在view1默认情况下显示并view2在滚动到屏幕顶部时显示。将 放在ViewoutputRange会使这成为可能吗?

And*_*dus 7

我想如果你想改变视图的动画,在 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',
  },
})
Run Code Online (Sandbox Code Playgroud)

在上面的示例中,我首先通过将handleScroll函数应用于scrollView. 确保您已scrollEventThrottle设置为 16 以确保每秒触发该功能,但请注意由此可能导致的性能问题(如果您关心,您可以查看了解更多信息)。

为了实现当用户滚动到某个位置时触发的视图更改(实际上不是,但看起来像那样),我使用 aview来包装红色和蓝色视图,红色的默认为opacity: 1,而蓝色的默认为opacity: 0,坐在红色的上面。

我隐藏了红色视图并通过动画它们的opacityusing 来显示蓝色视图interpolate()。在此帮助下,两个不透明度值都由animatedOpacityValue放入状态的一个 animationValue 控制。我添加了一个状态showBlueView以通过避免不断设置由 onScroll 触发的状态来优化性能。


这是touchableOpacities在两个视图上添加的更新,只需在未使用时隐藏蓝色视图即可实现。

首先,添加一个日志功能:

log = (stringToPrint) => () => {
  console.log(stringToPrint)
}
Run Code Online (Sandbox Code Playgroud)

接下来,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>
Run Code Online (Sandbox Code Playgroud)

请注意,showBlueView &&当不透明度为 0 时,我添加了隐藏蓝色视图,这样它就不会阻止应用于红色视图的任何点击事件(即使蓝色视图被隐藏,它实际上位于红色视图的顶部opacity: 0)。