使用React Native和ScrollView对文本进行动画处理

时间:2019-08-10 11:46:43

标签: react-native animation text scrollview

基本上,我无法根据ScrollView滚动事件为Text设置动画。在我的应用程序中,我有一个ScrollView和一个“ Header”,当ScrollView滚动时应该会缩小。当页眉缩小时,部分文本应消失,并且仅一个Texts元素应可见(应始终可见!)。理想情况下,应该可见的文本也应该变大。这是正在发生的事情的一个图像:

enter image description here

“总计:1,667.50雷亚尔”文本应变大并保持可见,而蓝色区域中的其余文本应淡出。

那怎么实现?

该元素是:

        <View style={styles.totalContainer}>
          <Text style={styles.totalTexto}>Total</Text>
          <TextMask value={precoTotal} type="money" style={styles.preco} />
        </View>

这是我的整个ListComponent:

import React from 'react';
import { StyleSheet, ScrollView, View, Animated, Platform } from 'react-native';
import { Text } from 'react-native-paper';
import {
  widthPercentageToDP as wp,
  heightPercentageToDP as hp,
} from 'react-native-responsive-screen';

import PropTypes from 'prop-types';
import { TextMask } from 'react-native-masked-text';

import ServicoCarrinhoListItem from './ServicoCarrinhoListItem';
import colors from '../helpers/colors';

import { minutosEmHoraFormatada } from '../helpers';

const HEADER_MAX_HEIGHT = hp('18%');
const HEADER_MIN_HEIGHT = 60;
const HEADER_SCROLL_DISTANCE = HEADER_MAX_HEIGHT - HEADER_MIN_HEIGHT;
const scrollRangeForAnimation = 100;

class ServicoCarrinhoList extends React.Component {
  constructor(props) {
    super(props);

    this.renderItem = this.renderItem.bind(this);
    this.scrollViewRef = null;

    this.state = {
      scrollY: new Animated.Value(
        // iOS has negative initial scroll value because content inset...
        Platform.OS === 'ios' ? -HEADER_MAX_HEIGHT : 0
      ),
    };
  }

  renderItem(item) {
    return (
      <ServicoCarrinhoListItem
        servico={item}
        removerServico={this.props.removerItem}
        key={item.produto_fipe_id}
      />
    );
  }

  onScrollEndSnapToEdge = event => {
    const { y } = event.nativeEvent.contentOffset;
    if (y > 0 && y < scrollRangeForAnimation / 2) {
      if (this.scrollViewRef) {
        this.scrollViewRef.scrollTo({ y: 0 });
      }
    } else if (scrollRangeForAnimation / 2 <= y && y < scrollRangeForAnimation) {
      if (this.scrollViewRef) {
        this.scrollViewRef.scrollTo({ y: scrollRangeForAnimation });
      }
    }
  };

  render() {
    const { servicos, veiculoSelecionado, precoTotal, duracaoTotal } = this.props;

    const scrollY = Animated.add(this.state.scrollY, Platform.OS === 'ios' ? HEADER_MAX_HEIGHT : 0);
    const headerTranslate = scrollY.interpolate({
      inputRange: [0, HEADER_SCROLL_DISTANCE],
      outputRange: [0, -HEADER_SCROLL_DISTANCE],
      extrapolate: 'clamp',
    });

    return [
      <Animated.ScrollView
        contentContainerStyle={styles.listaServicos}
        key="list"
        ref={scrollView => {
          this.scrollViewRef = scrollView ? scrollView._component : null;
        }}
        contentInset={{
          top: HEADER_MAX_HEIGHT,
        }}
        contentOffset={{
          y: -HEADER_MAX_HEIGHT,
        }}
        scrollEventThrottle={1}
        onScroll={Animated.event([{ nativeEvent: { contentOffset: { y: this.state.scrollY } } }], {
          useNativeDriver: true,
        })}
        onScrollEndDrag={this.onScrollEndSnapToEdge}
        onMomentumScrollEnd={this.onScrollEndSnapToEdge}
      >
        <View style={styles.separator} />
        <View style={styles.listHeader}>
          <Text style={[styles.listHeaderText, styles.listHeaderServico]}>Serviço</Text>
          <Text style={[styles.listHeaderText, styles.listHeaderValor]}>Valor</Text>
          <View style={styles.listHeaderEmptySpace} />
        </View>
        {servicos.map(this.renderItem)}
      </Animated.ScrollView>,
      <Animated.View
        style={[styles.header, { transform: [{ translateY: headerTranslate }] }]}
        key="header"
        pointerEvents="none"
      >
        <View style={styles.veiculoContainer}>
          <View style={styles.veiculoInfoContainer}>
            <Text style={styles.veiculoTitulo}>Veiculo</Text>
            <Text>{veiculoSelecionado.nome_fabricante}</Text>
            <Text>{veiculoSelecionado.nome_modelo}</Text>
            <Text>{veiculoSelecionado.nome_ano_modelo}</Text>
          </View>
        </View>
        <View style={styles.totalContainer}>
          <Text style={styles.totalTexto}>Total</Text>
          <TextMask value={precoTotal} type="money" style={styles.preco} />
        </View>
        <Text style={styles.duracaoTexto}>
          Duração aproximada para realização do servico é de {minutosEmHoraFormatada(duracaoTotal)}
        </Text>
      </Animated.View>,
    ];
  }
}

export default ServicoCarrinhoList;

const styles = StyleSheet.create({
  header: {
    position: 'absolute',
    top: 0,
    left: 0,
    right: 0,
    backgroundColor: '#03A9F4',
    overflow: 'hidden',
    height: HEADER_MAX_HEIGHT,
    justifyContent: 'center',
    alignItems: 'center',
  },
  listaServicos: {
    // backgroundColor: 'red',
    // paddingTop: hp('2%'),
    flexGrow: 1,
    width: wp('100%'),
    alignItems: 'center',
    // paddingTop: HEADER_MAX_HEIGHT,
  },
  listHeader: {
    flexDirection: 'row',
    justifyContent: 'space-between',
    width: wp('100%'),
    marginBottom: hp('2%'),
    paddingLeft: wp('5%'),
    paddingRight: wp('5%'),
    marginTop: hp('1.5%'),
  },
  listHeaderText: {
    fontWeight: '900',
    fontSize: hp('1.99%'),
  },
  listHeaderServico: {
    flex: 12,
  },
  listHeaderValor: {
    flex: 4,
  },
  listHeaderEmptySpace: {
    flex: 1,
  },
  separator: {
    borderBottomWidth: 0.7,
    borderBottomColor: colors.cinza2,
    width: wp('92%'),
  },
  veiculoContainer: {
    flexDirection: 'row',
    marginBottom: hp('1%'),
    paddingLeft: wp('5%'),
    paddingRight: wp('5%'),
  },
  veiculoInfoContainer: {
    flex: 1,
    alignItems: 'center',
  },
  veiculoTrocarContainer: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
  veiculoTitulo: {
    fontWeight: '900',
    textAlign: 'center',
    marginBottom: hp('0.6%'),
  },
  trocarTexto: {
    fontSize: hp('1.99%'),
    color: colors.azul3,
  },
  totalContainer: {
    flexDirection: 'row',
    marginBottom: hp('1%'),
    alignItems: 'center',
    justifyContent: 'center',
  },
  totalTexto: {
    fontWeight: '600',
    marginRight: wp('4%'),
  },
  preco: {
    fontWeight: '600',
    fontSize: hp('2.19%'),
    color: colors.verde,
  },
  duracaoTexto: {
    width: wp('90%'),
    textAlign: 'center',
    marginBottom: hp('1%'),
    fontSize: 13,
  },
});

ServicoCarrinhoList.propTypes = {
  servicos: PropTypes.arrayOf(PropTypes.object),
  removerItem: PropTypes.func.isRequired,
  veiculoSelecionado: PropTypes.object.isRequired,
  precoTotal: PropTypes.number,
  duracaoTotal: PropTypes.number,
};

0 个答案:

没有答案