美文网首页
【react-native】滑动吸顶效果 + 下拉刷新

【react-native】滑动吸顶效果 + 下拉刷新

作者: 空城皆是旧梦 | 来源:发表于2019-11-13 18:38 被阅读0次

现象:最近开发RN项目,需要开发一个页面滑动过程中的tab吸顶的效果。

解决方案: 使用Animated创建动画

具体代码如下:

  1. index.tsx
import React, { Component } from 'react'

import { View, Text, ViewStyle, StyleSheet, ImageBackground, Animated, RefreshControl } from 'react-native'
import StickyHeader from "./StickyHeader"
import { images, dimensions } from '../../../../res'

interface IState {
  refreshing: boolean,
  scrollHeight: number,
  scrollY: Animated.Value
}

export class PrivateCollectScreen extends Component<any, IState> {

  readonly state: IState = {
    scrollY: new Animated.Value(0),
    scrollHeight: -1,
    refreshing: false
  }



  render() {
    return (
      <View style={styles.container}>
        <Animated.ScrollView
          style={{ flex: 1 }}
          onScroll={
            Animated.event( // 映射动画值
              [{
                // 垂直滚动时,将 event.nativeEvent.contentOffset.y映射到this.state.scrollY,以此记录滑动距离
                nativeEvent: { contentOffset: { y: this.state.scrollY } }
              }],
              { useNativeDriver: true }) // 启用原生动画驱动。默认不启用(false)
          }
          scrollEventThrottle={1} // 滚动条距离视图边缘的坐标
          refreshControl={ // 下拉刷新功能
            <RefreshControl
              style={{ backgroundColor: 'transparent' }}
              tintColor={'white'}
              refreshing={this.state.refreshing}
              onRefresh={() => { // 再刷新时调用
                this.setState({ refreshing: true })
              }} />
          }
        >


          <View onLayout={(e) => {
            this.setState({ scrollHeight: e.nativeEvent.layout.height }) // 获取头部的高度
          }}>
            <ImageBackground
              style={{ width: dimensions.screenWidth, height: 190 }}
              source={images.icReact}
            >
              {/* 头部内容 */}
            </ImageBackground>
          </View>


          <StickyHeader
            stickyHeaderY={this.state.scrollHeight} // 将头部高度传入组件
            stickyScrollY={this.state.scrollY}  // 将滑动距离传入组件
          >
            <View style={{ height: 50, backgroundColor: '#3356d9' }}>
              <Text style={{ fontSize: 20, textAlign: 'center', color: '#fff', lineHeight: 50 }}>固定栏</Text>
            </View>
          </StickyHeader>


          {/* 底部内容 */}
          {
            [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11].map((item, index) => {
              return (<View style={{ height: 100 }}><Text>底部内容{index}</Text></View>)
            })
          }
        </Animated.ScrollView>
      </View>
    )
  }
}

interface Styles {
  container: ViewStyle
}

const styles = StyleSheet.create<Styles>({
  container: {
    flex: 1,
    backgroundColor: '#fff'
  }
})
  1. StickyHeader.tsx
import * as React from 'react'
import { StyleSheet, Animated } from 'react-native'

interface IState {
  stickyLayoutY: number,
  stickyHeaderY: number,
  stickyScrollY: Animated.Value
}

/**
 * 滑动吸顶效果组件
 * @export
 * @class StickyHeader
 */
export default class StickyHeader extends React.Component<any, IState> {


  readonly state: IState = {
    stickyHeaderY: -1,
    stickyScrollY: new Animated.Value(0),
    stickyLayoutY: 0
  }
  // 兼容代码,防止没有传头部高度
  _onLayout = (event) => {
    this.setState({
      stickyLayoutY: event.nativeEvent.layout.y,
    })
  }

  render() {
    const { stickyHeaderY, stickyScrollY, children, style } = this.props
    const { stickyLayoutY } = this.state
    let y = stickyHeaderY !== -1 ? stickyHeaderY : stickyLayoutY
    const translateY = stickyScrollY.interpolate({
      inputRange: [-1, 0, y, y + 1],
      outputRange: [0, 0, 0, 1],
    })

    return (
      <Animated.View
        onLayout={this._onLayout}
        style={
          [
            style,
            styles.container,
            { transform: [{ translateY }] }
          ]}
      >
        {children}
      </Animated.View>
    )
  }
}

const styles = StyleSheet.create({
  container: {
    zIndex: 100
  }
})
  1. 效果图


    效果图

相关文章

网友评论

      本文标题:【react-native】滑动吸顶效果 + 下拉刷新

      本文链接:https://www.haomeiwen.com/subject/heskictx.html