#react-native
#react-native
Вопрос:
Я настраиваю компонент, который отображает flatlist, и пытаюсь сделать анимацию элементов flatlist «затухающей» для более впечатляющего отображения
Это компонент для отображения предложений поиска, в которых отображаются элементы
import React, { Component } from 'react'
import { View, Text, TextInput, FlatList, Image, TouchableOpacity } from 'react-native'
import { inject, observer } from 'mobx-react/native'
import { Button } from '../../components'
import Style from './style'
import I18n from '../../i18n'
import Icon from 'react-native-vector-icons/MaterialIcons'
import Api from '../../utils/Api'
import _ from 'lodash'
let mounted = false
@inject('UserStore', 'NavigationStore')
@observer
class SearchProducts extends Component {
constructor(props) {
super(props)
this.state = {
searchAutoComplete: [],
showAutoComplete: false,
currentSearch: '',
searchTimeoutId: null,
}
this.autoCompleteTimeout = null
this.storedResults = []
}
componentWillMount() {
mounted = true
}
componentWillUnmount() {
mounted = false
clearTimeout(this.autoCompleteTimeout)
}
_renderCategory = ({ item }) => {
return (
<View style={Style.featuredView}>
<Image source={item.image} style={Style.featuredImage} />
<Text style={{ textAlign: 'center', color: '#9B999A' }}>{item.title}</Text>
</View>
)
}
_renderSuggestion = ({ item, index }) => {
const splittedName = item.split(' ')
let splittedSearch = this.state.currentSearch.toUpperCase().split(' ')
splittedSearch = splittedSearch.map(x => x.trim()).filter(x => x.length > 1)
let suggestion = []
if (splittedSearch.length == 0) {
suggestion = splittedName.map((word, index) => <Text key={index}>{word} </Text>)
} else {
let highlightedWords = []
splittedName.forEach((word, index) =>
splittedSearch.forEach(wordFromSearch => {
const currentWord = word.toUpperCase()
const isAlreadyHighlighted = highlightedWords.includes(currentWord)
if ((currentWord.includes(wordFromSearch.toUpperCase()) amp;amp; this.state.currentSearch.length > 0) || isAlreadyHighlighted) {
let v = (
<Text key={index} style={{ color: '#2eb872' }}>
{word}{' '}
</Text>
)
if (!isAlreadyHighlighted) {
highlightedWords.push(currentWord)
}
suggestion[index] = v
} else {
let v = <Text key={index}>{word} </Text>
suggestion[index] = v
}
})
)
}
return (
<TouchableOpacity
style={Style.suggestionView}
onPress={() => {
this.props.UserStore.addRecentSearch(item)
this.props.NavigationStore.navigate({ routeName: 'SearchResult', params: { search: item } })
this.autoCompleteTimeout = setTimeout(() => {
if (mounted) this.setState({ showAutoComplete: false })
}, 400)
}}
>
<Icon name='search' size={20} style={{}} />
<Text style={{ marginLeft: 20, textAlign: 'left', color: '#9B999A' }}>{suggestion}</Text>
</TouchableOpacity>
)
}
getSuggestions = async currentSearch => {
try {
const response = await Api.serachOutoCompleate(currentSearch)
let searchAutoComplete = response.suggestions.products.map(product => product.product_title)
response.suggestions.categories.forEach(categories => searchAutoComplete.push(categories))
response.suggestions.warehouses.forEach(warehouse => searchAutoComplete.push(warehouse.warehouse_name))
response.suggestions.upcs.forEach(upcs => searchAutoComplete.push(upcs.product_title))
response.suggestions.tags.forEach(tags => searchAutoComplete.push(tags.product_title))
this.storedResults[currentSearch] = searchAutoComplete
if (mounted amp;amp; currentSearch amp;amp; searchAutoComplete) this.setState({ currentSearch: currentSearch, searchAutoComplete: searchAutoComplete })
else this.setState({ currentSearch: currentSearch })
} catch (error) {
console.log(error)
}
}
_onSearchChange = _.debounce(currentSearch => {
if (currentSearch === '') {
this.setState({ filter: [], currentSearch })
} else {
if (this.storedResults[currentSearch]) {
this.setState({ currentSearch })
let searchAutoComplete = this.storedResults[currentSearch]
if (mounted amp;amp; currentSearch amp;amp; searchAutoComplete) this.setState({ searchAutoComplete })
} else {
this.getSuggestions(currentSearch)
}
}
}, 250)
render() {
I18n.locale = this.props.UserStore.user.lang
const recent = this.props.UserStore.RecentSearches
return (
<View style={Style.container}>
<View style={Style.search_container}>
<TextInput
style={Style.search_input}
underlineColorAndroid='transparent'
placeholder={I18n.t('search_products')}
returnKeyType='search'
autoCorrect={false}
onChangeText={this._onSearchChange}
onFocus={() => this.setState({ showAutoComplete: true })}
onSubmitEditing={event => {
if (event.nativeEvent.text.length) this.props.UserStore.addRecentSearch(event.nativeEvent.text)
this.props.NavigationStore.navigate({ routeName: 'SearchResult', params: { search: event.nativeEvent.text } })
}}
onKeyPress={() => this.suggestionTimeout amp;amp; clearTimeout(this.suggestionTimeout)}
blurOnSubmit
/>
</View>
{this.state.currentSearch.length > 0 amp;amp; this.state.showAutoComplete amp;amp; this.state.searchAutoComplete.length > 0 ? (
<View style={{ paddingVertical: 10 }}>
<FlatList initialNumToRender={20} data={this.state.searchAutoComplete} keyExtractor={(item, index) => item.toString()} renderItem={this._renderSuggestion} keyboardShouldPersistTaps='always' />
</View>
) : (
<View>
{recent.length > 0 ? (
<View>
<View style={Style.whiteBorder} />
<View style={Style.searchHistory}>
<Text style={Style.searchHistory_header}>{I18n.t('recent_searches')}</Text>
{recent.map((title, index) => (
<Button
key={index}
style={Style.recentSearch}
onPress={() => {
this.props.UserStore.addRecentSearch(title)
this.props.NavigationStore.navigate({ routeName: 'SearchResult', params: { search: title } })
}}
>
<Icon name='schedule' style={Style.recentSearchIcon} />
<Text style={Style.recentSearchText}>{title}</Text>
</Button>
))}
</View>
</View>
) : null}
</View>
)}
</View>
)
}
}
export default SearchProducts
Я ожидаю, что на выходе будет отображаться анимация затухания в flatlist,
и я не знаю, как это реализовать
Ответ №1:
Это может быть достигнуто с помощью анимированного API. Сначала импортируйте Animated
из react-native, затем добавьте fade: new Animated.Value(0)
в свое состояние внутри конструктора.
Теперь измените представление, окружающее FlatList, с этого
<View style={{ paddingVertical: 10 }}>
к этому
<Animated.View style={{ paddingVertical: 10, opacity: this.state.fade }}>
Наконец, добавьте этот блок, чтобы запустить анимацию при монтировании списка:
componentDidMount() {
Animated.timing(this.state.fade, {
duration: 500,
toValue: 1,
useNativeDrivers: true
}).start();
}
Если вы хотите анимировать FlatList каждый раз, когда пользователь выполняет поиск, вам придется переместить этот блок в другую часть логики вашей программы и не забудьте вернуть fade
значение 0 перед анимацией.
Комментарии:
1. я сделал, как вы сказали, но это не работает.
<Animated.View style={{ paddingVertical: 10, opacity: this.state.fade }}/> <FlatList initialNumToRender={20} data={this.state.searchAutoComplete} keyExtractor={(item, index) => item.toString()} renderItem={this._renderSuggestion} keyboardShouldPersistTaps='always' /> </View> ) : ( <View> {recent.length > 0 ? ( <View>
2. Не забудьте также установить закрытие
</View>
как a</Animated.View >
!3. Моя цель — выполнить анимацию «затухания» для каждого продукта и продукта, показанного из flatlist..
4. Вам нужно установить состояние затухания в качестве анимированного значения: this.state = { затухание: новое анимированное. Значение (0), };