Parallax / анимированный заголовок для ответа на native с scrollView onScroll

Primate спросил: 28 апреля 2018 в 08:59 в: react-native

С помощью этой справки Проблемы с заголовком parallax в ответе native

Единственное найденное решение - это просто хак, который скрывает ваш refreshкомпонент, потому что contentContainerStyle не взаимодействует с обновляемым компонентом.

Итак, единственное решение - переместить компонент scrollview, но перемещение его во время прокрутки довольно отсталое и ошеломляющее. Любое решение? Это довольно распространенный случай, я имею в виду..Facebook приложение и приложение Twitter имеют оба типа этого домашнего экрана!

, а пример анимации: анимированный заголовок из дома для магазина воспроизведения.

добавлена ​​закуска: закуска esample заголовка анимации

, как вы видите, на Android, прокрутка вверх и вниз начинается с шага, потому что две анимации (контейнер и прокрутка) являются параллельными: они не смешиваются, каждый из них пытается оживить ... исходящий с ума.


2 ответа

Community Khriz ответил: 30 апреля 2018 в 02:41

Вы можете попробовать библиотеку "реакция-весна", поскольку она поддерживает эффекты Parallax для реакции native.

Обновление: Рабочее решение из вашего примера

import React, { Component } from 'react';
import { Animated, Image, Platform, StyleSheet, View, Text, FlatList } from 'react-native';const data = [
  {
    key: 'key',
    name: 'name',
    image: 'imageUrl',
  },
];const NAVBAR_HEIGHT = 90;
const STATUS_BAR_HEIGHT = Platform.select({ ios: 20, android: 24 });const styles = StyleSheet.create({
  fill: {
    flex: 1,
  },
  navbar: {
    position: 'absolute',
    top: 0,
    left: 0,
    right: 0,
    alignItems: 'center',
    backgroundColor: 'white',
    borderBottomColor: '#dedede',
    borderBottomWidth: 1,
    height: NAVBAR_HEIGHT,
    justifyContent: 'center',
    paddingTop: STATUS_BAR_HEIGHT,
  },
  contentContainer: {
    flex: 1,
  },
  title: {
    color: '#333333',
  },
  row: {
    height: 300,
    width: null,
    marginBottom: 1,
    padding: 16,
    backgroundColor: 'transparent',
  },
  rowText: {
    color: 'white',
    fontSize: 18,
  },
});export default class App extends Component {
  constructor(props) {
    super(props);    const scrollAnim = new Animated.Value(0);    this._clampedScrollValue = 0;
    this._offsetValue = 0;
    this._scrollValue = 0;    this.state = {
      scrollAnim,
    };
  }  _renderRow(rowData, rowId) {
    return (
      <View style={{ flex: 1 }}>
        <Image key={rowId} style={styles.row} source={{ uri: rowData.image }} resizeMode="cover" />
        <Text style={styles.rowText}>{rowData.title}</Text>
      </View>
    );
  }  render() {
    const { scrollAnim } = this.state;    const navbarTranslate = scrollAnim.interpolate({
      inputRange: [0, NAVBAR_HEIGHT - STATUS_BAR_HEIGHT],
      outputRange: [0, -(NAVBAR_HEIGHT - STATUS_BAR_HEIGHT)],
      extrapolate: 'clamp',
    });
    const navbarOpacity = scrollAnim.interpolate({
      inputRange: [0, NAVBAR_HEIGHT - STATUS_BAR_HEIGHT],
      outputRange: [1, 0],
      extrapolate: 'clamp',
    });    return (
      <View style={styles.fill}>
        <View style={styles.contentContainer}>
          <FlatList
            data={data}
            renderItem={item => this._renderRow(item.item, item.index)}
            scrollEventThrottle={16}
            onScroll={Animated.event([
              { nativeEvent: { contentOffset: { y: this.state.scrollAnim } } },
            ])}
          />
        </View>
        <Animated.View style={[styles.navbar, { transform: [{ translateY: navbarTranslate }] }]}>
          <Animated.Text style={[styles.title, { opacity: navbarOpacity }]}>PLACES</Animated.Text>
        </Animated.View>
      </View>
    );
  }
}
Primate ответил: 29 апреля 2018 в 11:30
Проблема не в анимации, а на скрытом компоненте refresh. На самом деле я просто хочу анимировать заголовок, не теряя компонент обновления за заголовком абсолютной позиции.
Khriz ответил: 29 апреля 2018 в 11:42
Я не совсем понимаю вашу проблему, но если вы интерполируете позицию ScrollView на высоту заголовка, вы можете имитировать что-то вроде gif в своем справочном вопросе. Это будет примерно так: const headerHeight = this.state.scrollY.interpolate({ inputRange: [0, headerScrollDistance], outputRange: [headerMaxHeight, headerMinHeight], extrapolate: 'clamp', });
Primate ответил: 30 апреля 2018 в 07:56
И я сделал это несколько дней назад. Но теперь эта анимация лагги. Потому что вы прокручиваете + перемещаете scrollview и шатаетесь на андроиде. Любая идея?
Khriz ответил: 30 апреля 2018 в 08:10
попробуйте добавить useNativeDriver prop в заголовок Animated.View. Также попробуйте анимацию в режиме выпуска, для Android в режиме разработки некоторые анимации всегда лагги.
Primate ответил: 30 апреля 2018 в 08:36
родной драйвер не работает с высотой.
Есть решение
Primate ответил: 01 мая 2018 в 09:31

ОБНОВЛЕНИЕ 3: хорошее решение для Android и ios

: полная заправка с помощью gif-анимации

Я нашел обходной путь для первого частичного решение (абсолютный заголовок с трансляцией translate и contentContainerStyle с paddingTop)

Проблема заключается только в компоненте обновления, поэтому что делать?

const AnimatedFlatList = Animated.createAnimatedComponent(FlatList)<AnimatedFlatList
        data={data}
        renderItem={item => this._renderRow(item.item, item.index)}
        scrollEventThrottle={16}
        onScroll={Animated.event([
          { nativeEvent: { contentOffset: { y: this.state.scrollAnim } }, },
        ], { useNativeDriver: true })}
                  refreshControl={
        <RefreshControl
          refreshing={this.state.refreshing}
          onRefresh={() => {
            this.setState({ refreshing: true });
            setTimeout(() => this.setState({ refreshing: false }), 1000);
          }}
          // Android offset for RefreshControl
          progressViewOffset={NAVBAR_HEIGHT}
        />
      }
      // iOS offset for RefreshControl
      contentInset={{
        top: NAVBAR_HEIGHT,
      }}
      contentOffset={{
        y: -NAVBAR_HEIGHT,
      }}      />

Это применит смещение style на refreshController, выравнивая его с содержимым.

UPDATE2: есть проблемы на ios.

UPDATE3: исправлено и на ios.

Закуска ios и android