Пользовательский раскрывающийся компонент обновления React Native PullToRefresh
Для студентов, которые спешат, можно начать с этогоВеб-сайт Expo запускает демонстрацию онлайн, чтобы увидеть эффект.
Полный код, вРепозиторий на гитхабе.
Потяните вниз, чтобы обновить, это очень распространенный способ взаимодействия. React-Native (далее RN) встроенныйFlatList
Он поддерживает раскрывающийся компонент обновления, устанавливаяrefreshControlхарактеристики. Обычно нам нужно не только настроить выпадающий компонент, но и выполнить некоторые анимации в раскрывающемся компоненте в процессе выпадающего списка.Например, в нашем сценарии логотип компании будет отображать цвета с разными штрихами в зависимости от диапазона опускания. Это требует, чтобы наш раскрывающийся компонент знал величину текущего раскрывающегося списка, чтобы рассчитать ход выполнения нашей анимации. Судя по всему, официальный RNrefreshControl
не соответствует нашим потребностям.
видите, что есть два пакета с открытым исходным кодом, которые уже существуютreact-native-pull-refreshа такжеreact-native-ptr-control, в принципе имеет историю около 2-х лет, и я реально не понимаю, зачем его использоватьдва ScrollView
вложенные для достижения.
Интуитивно у меня должен быть только одинScrollView
Вот и все, я отслеживаю расстояние до раскрывающегося списка и повторно визуализирую пользовательский раскрывающийся компонент. Ну по этой идее попробуй попробуй.
Пошаговая реализация пользовательского раскрывающегося списка
Во-первых, мы предоставляем контейнер (с именемPullToRefresh
bar ), внутренне пользователь проходит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/день….
Ссылки по теме
- Официальная документация React Native PanResponder
- PanResponder demo in Navigator
- Используйте Animated.event для автоматического сопоставления положения прокрутки ScrollView.
- lottie-react-native
коммерческое время
Блог-центр Renrendai Big End Technology
Наконец-то прорекламировали. Добро пожаловать в гостиБлог-центр Renrendai Big Front-end Technology
внутри оnodejs
react
react native
Небольшие программы, фронтенд-инжиниринг и другие сопутствующие технические статьи обновляются одна за другой. Добро пожаловать в гости и жалуйтесь~