首页 > 解决方案 > 有什么方法可以用 react native ScrollView onScroll 钩子制作动画吗?

问题描述

我想将类基础组件转换为动画的功能基础组件。 https://snack.expo.io/@wyrustaaruz/animation-test-class-base

您可以使用小吃链接更改代码。你也可以看看下面的代码。此代码在类基础组件上运行良好。

我试过 useRef,useState 但我无法解决这个问题。

这是我的功能基本链接:

https://snack.expo.io/@wyrustaaruz/animated-with-functional-base

import React, {Component} from 'react';
import {
  Animated,
  Image,
  ScrollView,
  StyleSheet,
  Text,
  View,
} from 'react-native';

const HEADER_MAX_HEIGHT = 200;
const HEADER_MIN_HEIGHT = 60;
const HEADER_SCROLL_DISTANCE = HEADER_MAX_HEIGHT - HEADER_MIN_HEIGHT;

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

  this.state = {
    scrollY: new Animated.Value(0),
  };
}
  _renderScrollViewContent() {
    const data = Array.from({length: 30});
    return (
      <View style={styles.scrollViewContent}>
        {data.map((_, i) =>
          <View key={i} style={styles.row}>
            <Text>{i}</Text>
          </View>
        )}
      </View>
    );
  }

  render() {
     const headerHeight = this.state.scrollY.interpolate({
    inputRange: [0, HEADER_SCROLL_DISTANCE],
    outputRange: [0, 1],
    extrapolate: 'clamp',
  });
    return (
      <View style={styles.fill}>
        <ScrollView
    style={styles.fill}
    scrollEventThrottle={16}
    onScroll={Animated.event(
      [{nativeEvent: {contentOffset: {y: this.state.scrollY}}}]
    )}
  >
          {this._renderScrollViewContent()}
        </ScrollView>
        <Animated.View opacity={headerHeight} style={[styles.header]}>
          <View style={styles.bar}>
            <Text style={styles.title}>Title</Text>
          </View>
        </Animated.View>
      </View>
    );
  }
}

const styles = StyleSheet.create({
  fill: {
    flex: 1,
  },
  row: {
    height: 40,
    margin: 16,
    backgroundColor: '#D3D3D3',
    alignItems: 'center',
    justifyContent: 'center',
  },
  header: {
  position: 'absolute',
  top: 0,
  left: 0,
  right: 0,
  backgroundColor: '#03A9F4',
  overflow: 'hidden',
},
bar: {
  marginTop: 28,
  height: 32,
  alignItems: 'center',
  justifyContent: 'center',
},
title: {
  backgroundColor: 'transparent',
  color: 'white',
  fontSize: 18,
},
scrollViewContent: {
  marginTop: 0,
},
});

标签: react-nativeanimationreact-hooks

解决方案


干得好 ;)

请注意,您必须使用Animated.ScrollView才能使事件正常工作。

这是更新的零食链接:https ://snack.expo.io/@milt/animated-base-with-functional-component-and-hooks

以及下面的代码:


    import React, { useRef } from 'react';
    import PropTypes from 'prop-types';
    import { View, Text, StyleSheet, Animated } from 'react-native';

    const HEADER_MAX_HEIGHT = 200;
    const HEADER_MIN_HEIGHT = 60;
    const HEADER_SCROLL_DISTANCE = HEADER_MAX_HEIGHT - HEADER_MIN_HEIGHT;

    const styles = StyleSheet.create({
      fill: {
        flex: 1,
      },
      row: {
        height: 40,
        margin: 16,
        backgroundColor: '#D3D3D3',
        alignItems: 'center',
        justifyContent: 'center',
      },
      header: {
        position: 'absolute',
        top: 0,
        left: 0,
        right: 0,
        backgroundColor: '#03A9F4',
        overflow: 'hidden',
      },
      bar: {
        marginTop: 28,
        height: 32,
        alignItems: 'center',
        justifyContent: 'center',
      },
      title: {
        backgroundColor: 'transparent',
        color: 'white',
        fontSize: 18,
      },
      scrollViewContent: {
        marginTop: 0,
      },
    });

    const data = Array.from({ length: 30 });

    const ScrollableHeader = () => {
      const animatedScrollYValue = useRef(new Animated.Value(0)).current;

      const headerHeight = animatedScrollYValue.interpolate({
        inputRange: [0, HEADER_SCROLL_DISTANCE],
        outputRange: [0, 1],
        extrapolate: 'clamp',
      });

      return (
        <View style={styles.fill}>
          <Animated.ScrollView
            style={styles.fill}
            contentContainerStyle={styles.scrollViewContent}
            scrollEventThrottle={16}
            onScroll={Animated.event([{ nativeEvent: { contentOffset: { y: animatedScrollYValue } } }])}
          >
            <View style={styles.scrollViewContent}>
              {data.map((_, i) => (
                <View key={i} style={styles.row}>
                  <Text>{i}</Text>
                </View>
              ))}
            </View>
          </Animated.ScrollView>
          <Animated.View opacity={headerHeight} style={[styles.header]}>
            <View style={styles.bar}>
              <Text style={styles.title}>Title</Text>
            </View>
          </Animated.View>
        </View>
      );
    };

    ScrollableHeader.propTypes = {
      navigation: PropTypes.shape({
        navigate: PropTypes.func.isRequired,
      }).isRequired,
    };

    export default ScrollableHeader;

推荐阅读