React native 如何在ScrollView中平滑动画marginTop过渡?

React native 如何在ScrollView中平滑动画marginTop过渡?,react-native,react-native-scrollview,React Native,React Native Scrollview,对于我的项目,我希望实现一个ScrollView,它可以像浏览一盒名片一样显示项目。在尝试了许多其他方法之后,我基于当前的实现 然而,整个事情现在变得非常紧张。有人能告诉我如何使当前的实施顺利进行吗?或者,有没有人知道如何以不同的方式获得这种行为?任何解决方案都应该在iOS和安卓系统中运行 这个gif显示了我当前的实现,包括抖动问题。它还应该清楚地说明我所追求的行为: 这是我当前的实现: import React from 'react' import { Animated, Dime

对于我的项目,我希望实现一个ScrollView,它可以像浏览一盒名片一样显示项目。在尝试了许多其他方法之后,我基于当前的实现

然而,整个事情现在变得非常紧张。有人能告诉我如何使当前的实施顺利进行吗?或者,有没有人知道如何以不同的方式获得这种行为?任何解决方案都应该在iOS和安卓系统中运行

这个gif显示了我当前的实现,包括抖动问题。它还应该清楚地说明我所追求的行为:

这是我当前的实现:

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',
  }
})
从“React”导入React
进口{
有生气的
尺寸,
滚动视图,
样式表,
文本,
看法
状态栏,
}从“反应本机”
const SCREEN_HEIGHT=尺寸。获取(“窗口”)。高度
const yOffset=新的动画值(0)
const onScroll=Animated.event(
[{nativeEvent:{contentOffset:{y:yOffset}}}}],
)
函数CardView(props:{children?:ReactElement}){
返回(
{props.children}
)
}
函数页(props:{children?:ReactElement,索引:1}){
返回(
{props.children}
)
}
功能卡(道具:{文本:字符串,索引:编号}){
返回(
{props.text}
)
}
功能表(索引:编号){
返回{
marginTop:yOffset.interpolate({
输入范围:[
(索引-1)*屏幕高度,
索引*屏幕高度,
(索引+1)*屏幕高度,
(索引+2)*屏幕高度,
(索引+3)*屏幕高度,
],
输出范围:[
-40,
80,
屏幕高度+40,
2*屏幕高度+20,
3*屏幕高度,
],
外推:“夹具”,
}),
}
}
导出默认函数App(){
返回(
{[0,1,2,3,4,5,6,7,8,9,10].map((i)=>{
返回(
)
})}
)
}
const style=StyleSheet.create({
滚动页面:{
高度:屏幕高度,
背景色:“透明”,
},
卡片:{
高度:屏幕高度,
对齐项目:“居中”,
边界半径:4,
边框宽度:1,
背景颜色:“#F5FCFF”,
}
})

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

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

我找到了一个简短的答案:如果你在滚动时弄乱了滚动视图的高度,滚动视图将永远无法顺利进行动画制作。另一方面,当我设置
scrollEventThrottle={1}

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


如果有人遇到过相同的用例实现问题,请随意使用我的作品:

我找到的简短答案是:如果在滚动时弄乱了滚动视图的高度,滚动视图将永远无法顺利动画化。另一方面,当我设置
scrollEventThrottle={1}

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


如果有人遇到相同的用例实现问题,请随意使用我的作品:

嘿,试试这个
useNativeDriver:true
将帮助您克服延迟

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

嘿,试试这个
useNativeDriver:true
将帮助您克服滞后

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

谢谢你,卢卡,我试过了,但优化不是问题所在。我认为抖动的原因是,在滚动时更新marginTop也会扰乱整个ScrollView的渲染。我不知道如何解决这个问题。尝试更新top(而不是marginTop)并将位置设置为“绝对”,这似乎有相同的结果。另一个缺点是,marginTop和top offset都会将卡渲染到其容器之外:Android会将它们切断。恐怕我将不得不寻找一个完全不同的实现。谢谢你的帮助!另一方面,当我设置
scrollEventThrottle={1}
而不是16时,这种紧张的行为变得更加平稳。但是对于实际使用来说还是太不稳定了。谢谢你,卢卡,我试过了,但是优化不是问题所在。我认为抖动的原因是,在滚动时更新marginTop也会扰乱整个ScrollView的渲染。我不知道如何解决这个问题。尝试更新top(而不是marginTop)并将位置设置为“绝对”,这似乎有相同的结果。另一个缺点是,marginTop和top offset都会将卡渲染到其容器之外:Android会将它们切断。恐怕我将不得不寻找一个完全不同的实现。谢谢你的帮助!另一方面,当我设置
scrollEventThrottle={1}
而不是16时,这种紧张的行为变得更加平稳。但对于实际使用来说仍然太不稳定。出于某种原因,在我的情况下,将scrollEventThrottle设置为1..16会使它结巴。将其设置为16以上(例如18)可使其完全平滑。进一步增加它,会慢慢引入另一种口吃,因为它错过了太多的事件。出于某种原因,在我的情况下,将scrollEventThrottle设置为1..16会导致口吃。将其设置为16以上(例如18)可使其完全平滑。再增加一点,慢慢地就会出现另一种口吃