Пользовательский раскрывающийся компонент обновления React Native

React Native
Пользовательский раскрывающийся компонент обновления React Native

Пользовательский раскрывающийся компонент обновления React Native PullToRefresh

Для студентов, которые спешат, можно начать с этогоВеб-сайт Expo запускает демонстрацию онлайн, чтобы увидеть эффект.

Полный код, вРепозиторий на гитхабе.

Потяните вниз, чтобы обновить, это очень распространенный способ взаимодействия. React-Native (далее RN) встроенныйFlatListОн поддерживает раскрывающийся компонент обновления, устанавливаяrefreshControlхарактеристики. Обычно нам нужно не только настроить выпадающий компонент, но и выполнить некоторые анимации в раскрывающемся компоненте в процессе выпадающего списка.Например, в нашем сценарии логотип компании будет отображать цвета с разными штрихами в зависимости от диапазона опускания. Это требует, чтобы наш раскрывающийся компонент знал величину текущего раскрывающегося списка, чтобы рассчитать ход выполнения нашей анимации. Судя по всему, официальный RNrefreshControlне соответствует нашим потребностям.

видите, что есть два пакета с открытым исходным кодом, которые уже существуютreact-native-pull-refreshа такжеreact-native-ptr-control, в принципе имеет историю около 2-х лет, и я реально не понимаю, зачем его использоватьдва ScrollViewвложенные для достижения.

Интуитивно у меня должен быть только одинScrollViewВот и все, я отслеживаю расстояние до раскрывающегося списка и повторно визуализирую пользовательский раскрывающийся компонент. Ну по этой идее попробуй попробуй.

Пошаговая реализация пользовательского раскрывающегося списка

Во-первых, мы предоставляем контейнер (с именемPullToRefreshbar ), внутренне пользователь проходитchildrenпрошел вFlatList, который также удобен для изменения пользователями. В сценарии, где требуется настраиваемое раскрывающееся обновление, используйте наш контейнер дляFlatListЭто нормально, чтобы упаковать его, и изменения довольно малы. Конечно, поскольку это настраиваемый заголовок обновления раскрывающегося списка, пользователь также должен передать компонент пользовательского заголовка обновления раскрывающегося списка, который называетсяprops.HeaderComponentЧто ж, на данный момент структура DOM, отображаемая в нашем контейнере, вероятно, выглядит так:

<View>
  <Animated.View><HeaderComponent /></Animated.View>
	<FlatList />
</View>

крайнийViewобласть отображения и собственныеFlatListточно так же. Итак, вот в чем проблема, наш заголовок HeaderComponent для обновления по запросу должен быть невидимым по умолчанию и постепенно входить в видимую область контейнера сверху вниз в процессе вытягивания пользователем. Тогда по умолчанию HeaderComponent абсолютно позиционируется за пределами видимой области контейнера, но насколько он смещается вверх?Для этого пользователь должен сообщить нам высоту выпадающего компонента в контейнере.props.headerHeight, на данный момент стиль, отображаемый контейнером, примерно следующий:

<View>
  <Animated.View style={{position: 'absolute', top: - this.props.headerHeight}}>
    <HeaderComponent />
  </Animated.View>
	<FlatList />
</View>

После завершения первоначального стиля структуры DOM следующей проблемой является время раскрывающегося списка контейнеров.

Во-первых, когда пользователь тянет вниз, вызывает ли он операцию раскрывающегося списка нашего контейнера, а не раскрывающийся список по умолчанию внутреннего FlatList? Это кажется относительно простым.Когда внутренний FlatList переместился наверх и больше не может быть вытянут вниз, действие пользователя по вытягиванию вниз должно вызвать раскрывающийся список контейнера. Затем нам нужно знать текущую позицию раскрывающегося списка внутреннего FlatList, которую можно получить с помощью функции FlatList.onScrollСвойство для получения прокрутки из текущего FlatList.

Когда время для запуска раскрывающегося выпадающего контейнера определяется, какие компоненты нам нужно обновить во время раскрывающегося процесса контейнера? 1) Пользовательский компонент заголовка должен быть обновлен, а последнее раскрывающееся расстояние передается на компонент заголовка. 2. Положение плоскости также необходимо ответить на переезд.

Если мы используем контейнерstate.containerTopэтоAnimated.ValueЧтобы сохранить раскрывающееся расстояние текущего контейнера, текущие результаты DOM нашего рендеринга контейнера выглядят следующим образом:

const headerStyle = {
  position: 'absolute',
  left: 0,
  width: '100%',
  top: -this.props.headerHeight,
  transform: [{ translateY: this.state.containerTop }],
};
<View>
  <Animated.View style={[{ flex: 1, transform: [{ translateY: this.state.containerTop }] }]}>
  	<FlatList />
  </Animated.View>
  <Animated.View style={headerStyle}>
  	<HeaderComponent />
  </Animated.View>
</View>

Таким образом, процесс раскрытия контейнера в основном завершается, а настраиваемый заголовок и внутренний FlatList извлекаются синхронно.

Действие раскрывающегося списка реализовано, тогда где может быть раскрывающееся меню для запуска обновления? Это требует, чтобы пользователь прошел еще одно раскрывающееся расстояние, которое запускает обновление, которое называетсяprops.refreshTriggerHeightХорошо, когда пользователь отпускает, если текущее выпадающее расстояние >=props.refreshTriggerHeight, он вызовет функцию обновления, переданную пользователемprops.onRefresh. Обычно, если пользователь тянет вниз на большое расстояние, действие обновления запускается, когда пользователь отпускает палец. В это время весь компонент сначала возвращается в обновленное положение. В этом положении пользователь может использоватьprops.refreshingHoldHeightуказать.props.refreshTriggerHeightа такжеprops.refreshingHoldHeightявляются необязательными, если пользователь не передает их, по умолчаниюprops.headerHeight.

One More Thing

На самом деле, часть работы опущена выше.Самое главное, как передать расстояние вытягивания (прогресс вытягивания) пользовательскому компоненту заголовка HeaderComponent во время процесса вытягивания контейнера? на контейнере вышеstate.containerTopНа самом деле это расстояние выпадающего списка текущего контейнера, но этоAnimated.Value,НАСне можемПрочитайте его текущее значение. Поэтому я добавилсвойства экземпляра this.containerTranslateYЧтобы сохранить расстояние, на которое опускается текущий контейнер, мы будем отслеживатьstate.containerTopИзменение значения в функции обратного вызова, изменениеthis.containerTranslateY.

так далее! !containerTranslateYПочему бы не положить его в контейнерstateчто о? не должно бытьthis.state.containerTranslateYКакой? ? Ну я сначала поставилstateна контейнере, а затем, когда пользователь опускает контейнер,setState, запустите контейнер для повторного рендеринга, а затем поместитеcontainerTranslateYПроходя через заголовок. Тем не менее, такой контейнер поsetStateСпособ запуска обновления заголовка в моем тесте показал, что страница будет больше зависать. Итак, пока пользователь опускает контейнер инетизменить контейнерstate, но черезвызов методаМетод команды передает текущее расстояние раскрывающегося списка пользователя компоненту заголовка. Здесь можно оптимизировать. Я не уверен.

Таким образом, пользовательский компонент заголовка,долженвыставить метод экземпляраsetProgressЧтобы получить некоторые параметры в раскрывающемся процессе контейнера, текущая сигнатура этого метода выглядит следующим образом:

// pullDistance 表示容器下拉的距离;percent 代表下拉的进度,[0, 1]
setProgress({pullDistance, percent}){}

Полную демонстрацию компонента заголовка см.Запуск демонстрации на выставке.

The End

Наконец я услышал,анимация микровзаимодействий,использоватьlottieОн более совместим с RN.

Изначально хотел попробовать использовать AE, чтобы сделать логотип компанииlottieАнимация, но почему не подержали...

Полный код есть на гитхабе:GitHub.com/sophister/день….

Ссылки по теме

коммерческое время

Блог-центр Renrendai Big End Technology

Наконец-то прорекламировали. Добро пожаловать в гостиБлог-центр Renrendai Big Front-end Technology

внутри оnodejs react react nativeНебольшие программы, фронтенд-инжиниринг и другие сопутствующие технические статьи обновляются одна за другой. Добро пожаловать в гости и жалуйтесь~