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