使用scrollView onScroll

时间:2018-05-22 10:39:55

标签: react-native

有了这个参考 Problems with parallax header in react native

找到的唯一解决方案只是隐藏刷新组件的黑客,因为contentContainerStyle不与refreshcomponent交互。

因此,唯一的解决方案是移动scrollview组件,但在滚动时移动它是非常滞后和惊人的。 有解决方案吗 这是非常常见的情况,我的意思是.Facebook app和Twitter app都有这种类型的主屏幕!

示例动画是: animated header from play store app home

添加零食: snack esample of header animation

如你所见,在Android上,上下滚动开始交错,因为2动画(容器和滚动)是并发的:它们不混合,每个都试图动画..疯狂。

3 个答案:

答案 0 :(得分:2)

更新3 snack solution good for android and ios

更新:complete snack with gif like animation

我找到了第一个部分解决方案的解决方法(带有transform translate的绝对头文件和带有paddingTop的contentContainerStyle)

问题仅出在刷新组件上,那该怎么办?

const AnimatedFlatList = Animated.createAnimatedComponent(FlatList)

<AnimatedFlatList
        data={data}
        renderItem={item => this._renderRow(item.item, item.index)}
        scrollEventThrottle={16}
        onScroll={Animated.event([
          { nativeEvent: { contentOffset: { y: this.state.scrollAnim } }, },
        ], { useNativeDriver: true })}
                  refreshControl={
        <RefreshControl
          refreshing={this.state.refreshing}
          onRefresh={() => {
            this.setState({ refreshing: true });
            setTimeout(() => this.setState({ refreshing: false }), 1000);
          }}
          // Android offset for RefreshControl
          progressViewOffset={NAVBAR_HEIGHT}
        />
      }
      // iOS offset for RefreshControl
      contentInset={{
        top: NAVBAR_HEIGHT,
      }}
      contentOffset={{
        y: -NAVBAR_HEIGHT,
      }}

      />

这将在refreshController上应用偏移样式,使其与内容对齐。

UPDATE2: 在ios上有一些问题。

UPDATE3: 也固定在ios上。

snack working both ios and android

答案 1 :(得分:1)

您可以尝试使用react-spring library,因为它支持Parallax效果以反应原生。

更新:您的示例

中的工作解决方案
import React, { Component } from 'react';
import { Animated, Image, Platform, StyleSheet, View, Text, FlatList } from 'react-native';

const data = [
  {
    key: 'key',
    name: 'name',
    image: 'imageUrl',
  },
];

const NAVBAR_HEIGHT = 90;
const STATUS_BAR_HEIGHT = Platform.select({ ios: 20, android: 24 });

const styles = StyleSheet.create({
  fill: {
    flex: 1,
  },
  navbar: {
    position: 'absolute',
    top: 0,
    left: 0,
    right: 0,
    alignItems: 'center',
    backgroundColor: 'white',
    borderBottomColor: '#dedede',
    borderBottomWidth: 1,
    height: NAVBAR_HEIGHT,
    justifyContent: 'center',
    paddingTop: STATUS_BAR_HEIGHT,
  },
  contentContainer: {
    flex: 1,
  },
  title: {
    color: '#333333',
  },
  row: {
    height: 300,
    width: null,
    marginBottom: 1,
    padding: 16,
    backgroundColor: 'transparent',
  },
  rowText: {
    color: 'white',
    fontSize: 18,
  },
});

export default class App extends Component {
  constructor(props) {
    super(props);

    const scrollAnim = new Animated.Value(0);

    this._clampedScrollValue = 0;
    this._offsetValue = 0;
    this._scrollValue = 0;

    this.state = {
      scrollAnim,
    };
  }

  _renderRow(rowData, rowId) {
    return (
      <View style={{ flex: 1 }}>
        <Image key={rowId} style={styles.row} source={{ uri: rowData.image }} resizeMode="cover" />
        <Text style={styles.rowText}>{rowData.title}</Text>
      </View>
    );
  }

  render() {
    const { scrollAnim } = this.state;

    const navbarTranslate = scrollAnim.interpolate({
      inputRange: [0, NAVBAR_HEIGHT - STATUS_BAR_HEIGHT],
      outputRange: [0, -(NAVBAR_HEIGHT - STATUS_BAR_HEIGHT)],
      extrapolate: 'clamp',
    });
    const navbarOpacity = scrollAnim.interpolate({
      inputRange: [0, NAVBAR_HEIGHT - STATUS_BAR_HEIGHT],
      outputRange: [1, 0],
      extrapolate: 'clamp',
    });

    return (
      <View style={styles.fill}>
        <View style={styles.contentContainer}>
          <FlatList
            data={data}
            renderItem={item => this._renderRow(item.item, item.index)}
            scrollEventThrottle={16}
            onScroll={Animated.event([
              { nativeEvent: { contentOffset: { y: this.state.scrollAnim } } },
            ])}
          />
        </View>
        <Animated.View style={[styles.navbar, { transform: [{ translateY: navbarTranslate }] }]}>
          <Animated.Text style={[styles.title, { opacity: navbarOpacity }]}>PLACES</Animated.Text>
        </Animated.View>
      </View>
    );
  }
}

答案 2 :(得分:0)

万一其他人落在这个线程上,我开发了一个新程序包, react-native-animated-screen ,它完全满足您的需求

签出

https://www.npmjs.com/package/react-native-animated-screen

enter image description here