Перевести представление внутри Scrollview в React Native - PullRequest
0 голосов
/ 08 января 2020

Я пытаюсь создать эту панель навигации в моем RN-приложении. По сути, горизонтальный вид прокрутки категорий, которые выделяют текущую категорию на основе прокрутки Y.

image

Благодаря видео великого Уильяма Кэндильона ( https://www.youtube.com/watch?v=xutPT1oZL2M&t=1369s) Я довольно близко, но у меня есть главная проблема.

Я использую интерполяцию для перевода позиции X категории View при прокрутке. И тогда у меня есть Scrollview, оборачивающий этот Анимированный Вид. Проблема в том, что Scrollview не работает, так как он не имеет ссылки на позицию анимированного представления. Как вы можете видеть в gif ниже (синий -> Animated.View / red -> Scrollview)

My Caption

Мне нравится подход интерполяции, поскольку он декларативный и работает в собственном потоке, поэтому я постарался максимально избежать создания слушателя, подключенного к функции scrollTo ().

Какой подход вы бы рассмотрели?

export default ({ y, scrollView, tabs }) => {
  const index = new Value(0);

  const [measurements, setMeasurements] = useState(
    new Array(tabs.length).fill(0)
  );

  const indexTransition = withTransition(index);

  const width = interpolate(indexTransition, {
    inputRange: tabs.map((_, i) => i),
    outputRange: measurements
  });

  const translateX = interpolate(indexTransition, {
    inputRange: tabs.map((_tab, i) => i),
    outputRange: measurements.map((_, i) => {
      return (
        -1 *
          measurements
            .filter((_measurement, j) => j < i)
            .reduce((acc, m) => acc + m, 0) -
        8 * i
      );
    })
  });

  const style = {
    borderRadius: 24,
    backgroundColor: 'black',
    width,
    flex: 1
  };

  const maskElement = <Animated.View {...{ style }} />;

  useCode(
    () =>
      block(
        tabs.map((tab, i) =>
          cond(
            i === tabs.length - 1
              ? greaterOrEq(y, tab.anchor)
              : and(
                  greaterOrEq(y, tab.anchor),
                  lessOrEq(y, tabs[i + 1].anchor)
                ),
            set(index, i)
          )
        )
      ),
    [index, tabs, y]
  );
  return (
    <Animated.View style={[styles.container, {}]}>
      <Animated.ScrollView
        scrollEventThrottle={16}
        horizontal
        style={{ backgroundColor: 'red', flex: 1 }}
      >
        <Animated.View
          style={{
            transform: [{ translateX }],
            backgroundColor: 'blue'
          }}
        >
          <Tabs
            onPress={i => {
              if (scrollView) {
                scrollView.getNode().scrollTo({ y: tabs[i].anchor + 1 });
              }
            }}
            onMeasurement={(i, m) => {
              measurements[i] = m;
              setMeasurements([...measurements]);
            }}
            {...{ tabs, translateX }}
          />
        </Animated.View>
      </Animated.ScrollView>
    </Animated.View>
  );
};
...