如何平滑 ScrollView 中的动画 marginTop 过渡?

How can I smoothen Animated marginTop transitions in a ScrollView?

对于我的项目,我希望实现一个显示项目的 ScrollView,就好像您正在浏览一盒名片一样。我当前的实现基于 Albert Brand's article on Animated ScrollViews(在尝试了许多其他方法之后)。

然而,现在整个事情变得非常紧张。谁能告诉我如何使当前的实施更加顺利?或者,有没有人知道如何以不同的方式获得这种行为?任何解决方案都应该适用于 iOS 和 Android.

此 gif 显示了我当前的实现,包括抖动问题。它还应该清楚地说明我所追求的行为: screencapture of the ScrollView in iOS simulator

这是我当前的实现:

import React from 'react'
import {
  Animated,
  Dimensions,
  ScrollView,
  StyleSheet,
  Text,
  View,
  StatusBar,
} from 'react-native'

const SCREEN_HEIGHT = Dimensions.get('window').height

const yOffset = new Animated.Value(0)

const onScroll = Animated.event(
  [{ nativeEvent: { contentOffset: { y: yOffset } } }],
)

function CardView(props: { children?: ReactElement<*> }) {
  return (
    <Animated.ScrollView
      scrollEventThrottle={16}
      onScroll={onScroll}
      pagingEnabled
    >
      {props.children}
    </Animated.ScrollView>
  )
}

function Page(props: { children?: ReactElement<*>, index: 1 }) {
  return (
    <Animated.View style={[style.scrollPage]}>
      {props.children}
    </Animated.View>
  )
}

function Card(props: { text: string, index: number }) {
  return (
    <Animated.View style={[style.card, marginTransform(props.index)]}>
      <Text>
        {props.text}
      </Text>
    </Animated.View>
  )
}

function marginTransform(index: number) {
  return {
    marginTop: yOffset.interpolate({
      inputRange: [
        (index - 1) * SCREEN_HEIGHT,
        index * SCREEN_HEIGHT,
        (index + 1) * SCREEN_HEIGHT,
        (index + 2) * SCREEN_HEIGHT,
        (index + 3) * SCREEN_HEIGHT,
      ],
      outputRange: [
        -40,
        80,
        SCREEN_HEIGHT + 40,
        2 * SCREEN_HEIGHT + 20,
        3 * SCREEN_HEIGHT,
      ],
      extrapolate: 'clamp',
    }),
  }
}

export default function App() {
  return (
    <CardView>
      {[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10].map((i) => {
        return(
          <Page key={i}>
            <Card text={`Card ${i}`} index={i}>
            </Card>
          </Page>
        )
      })}
    </CardView>
  )
}

const style = StyleSheet.create({
  scrollPage: {
    height: SCREEN_HEIGHT,
    backgroundColor: 'transparent',
  },
  card: {
    height: SCREEN_HEIGHT,
    alignItems: 'center',
    borderRadius: 4,
    borderWidth: 1,
    backgroundColor: '#F5FCFF',
  }
})

确保 Debug JS Remote 已禁用。您还应该删除 class 中的所有 console.log() (例如,如果您出于调试原因记录 yOffset)。这应该会加快速度。

我找到的简短答案:如果您在滚动时弄乱它的高度,ScrollViews 将永远不会流畅地动画。在旁注中,我确实发现当我设置 scrollEventThrottle={1}

时性能显着提高

我最终实施的解决方案是制作自己的组件;在元素列表的顶部渲染 ScrollView。我将这些元素的动画高度值连接到 ScrollView 的滚动 y 偏移量。

如果有人遇到相同的用例实现问题,请随时使用我的作品:https://github.com/isilher/react-native-card-scroll

嘿,试试这个 useNativeDriver: true 将帮助您摆脱滞后

onScroll={Animated.event(
   [{ nativeEvent: { contentOffset: { x: xOffset } } }],
   { useNativeDriver: true }
)}