首页 > 解决方案 > React Native - 无论滚动位置如何,都需要在滚动时隐藏/显示带有动画的标题

问题描述

目前我有这个代码:

import React, { Component, PureComponent } from 'react';
import { View, FlatList, RefreshControl, StatusBar, Animated, ScrollView, PanResponder } from 'react-native';
import { heightPercentageToDP as hp, widthPercentageToDP as wp } from 'react-native-responsive-screen';
import { connect } from 'react-redux';
import i18n from 'i18n-js';
import Post from '../components/Post';
import AppHeader from '../components/AppHeader';

class Posts extends PureComponent {
  constructor(props) {
    super(props);
    this.state = {
      curY: new Animated.Value(0),
      height: 0
    };
  }

  render() {
    const { postsReducer } = this.props,
      { container } = styles;

    return (
      <View style={container}>
        <Animated.View
          style={{
            transform: [{
              translateY: this.state.curY.interpolate({
                inputRange: [0, 1],
                outputRange: [0, -1]
              })
            }], position: 'absolute', top: 0, width: wp('100%'), marginTop: StatusBar.currentHeight
          }}
          onLayout={({ nativeEvent }) => this.setState({ height: nativeEvent.layout.height })}
        >
          <AppHeader />
        </Animated.View>

        <Animated.ScrollView
          scrollEventThrottle={16}
          refreshControl={
            <RefreshControl
              onRefresh={this._onRefresh}
              refreshing={refreshing}
              tintColor='#5E81F4'
              colors={["blue", "lightblue"]}
            />
          }
          contentContainerStyle={{ marginTop: this.state.height }}
          onScroll={Animated.event(
            [{ nativeEvent: { contentOffset: { y: this.state.curY } } }],
            { useNativeDriver: true }
          )}

        >
          {postsReducer.map((item, index) => (
            <Post
              postId={item._id}
              userId={item.owner}
              owner={item.owner}
              title={item.title}
              avatar={item.picture}
              userName={item.userName}
              updatedAt={item.updatedAt}
              image={item.photo.split(",")}
              description={item.description}
              age={item.age}
              time={item.time}
              date={item.date}
              location={item.location}
              city={item.city}
              commentCounter={item.commentCounter}
              key={index}
            />
          ))}
        </Animated.ScrollView>
      </View>
    );
  }
}

const styles = {
  container: {
    flex: 1,
    flexDirection: 'column',
    justifyContent: 'flex-start',

  }
};

const mapStateToProps = ({ registrationReducer, postsReducer, usersReducer, }) => (
  {
    registrationReducer,
    postsReducer,
    usersReducer
  }
);

export default connect(mapStateToProps, { setPosts })(Posts); 

当我开始向下滚动时,标题隐藏,当我再次向上滚动时出现。但是只有当我到达列表的开头时才会出现标题。

我需要这样的解决方案:例如,当我在列表中间并开始向上滚动时 - 标题应该出现,并且当开始向下滚动时它会再次隐藏。所以它应该独立于位置。例如,它在 Facebook 移动应用程序中以这种方式工作。

标签: react-nativeanimation

解决方案


我找到了解决方案。只需要使用 Animated.diffClamp。这是最终的代码。也许对某人有用:

import React, { Component, PureComponent } from 'react';
import { View, FlatList, RefreshControl, StatusBar, Animated, ScrollView, PanResponder } from 'react-native';
import { heightPercentageToDP as hp, widthPercentageToDP as wp } from 'react-native-responsive-screen';
import { connect } from 'react-redux';
import i18n from 'i18n-js';
import Post from '../components/Post';
import AppHeader from '../components/AppHeader';

class Posts extends PureComponent {
  constructor(props) {
    super(props);
    this.state = {
      curY: new Animated.Value(0),
      height: 0
    };
  }

  render() {
    const { postsReducer } = this.props,
      { container } = styles;
    const headerDistance = Animated.diffClamp(this.state.curY, 0, 60).interpolate({
        inputRange: [0, 1], 
        outputRange: [0, -1]
      });

    return (
      <View style={container}>
        <Animated.ScrollView
          scrollEventThrottle={16}
          refreshControl={
            <RefreshControl
              onRefresh={this._onRefresh}
              refreshing={refreshing}
              tintColor='#5E81F4'
              colors={["blue", "lightblue"]}
            />
          }
          contentContainerStyle={{ marginTop: this.state.height }}
          onScroll={Animated.event(
            [{ nativeEvent: { contentOffset: { y: this.state.curY } } }],
            { useNativeDriver: true }
          )}

        >
          {postsReducer.map((item, index) => (
            <Post
              postId={item._id}
              userId={item.owner}
              owner={item.owner}
              title={item.title}
              avatar={item.picture}
              userName={item.userName}
              updatedAt={item.updatedAt}
              image={item.photo.split(",")}
              description={item.description}
              age={item.age}
              time={item.time}
              date={item.date}
              location={item.location}
              city={item.city}
              commentCounter={item.commentCounter}
              key={index}
            />
          ))}
        </Animated.ScrollView>

        <Animated.View
          style={{
            transform: [{
              translateY: headerDistance 
            }], position: 'absolute', top: 0, width: wp('100%'), marginTop: StatusBar.currentHeight
          }}
          onLayout={({ nativeEvent }) => this.setState({ height: nativeEvent.layout.height })}
        >
          <AppHeader />
        </Animated.View>
      </View>
    );
  }
}

const styles = {
  container: {
    flex: 1,
    flexDirection: 'column',
    justifyContent: 'flex-start',

  }
};

const mapStateToProps = ({ registrationReducer, postsReducer, usersReducer, }) => (
  {
    registrationReducer,
    postsReducer,
    usersReducer
  }
);

export default connect(mapStateToProps, { setPosts })(Posts); 

推荐阅读