Есть ли способ «затухания» элементов в flatlist?

#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), };