【问题标题】:How to make element fixed on scroll in React Native?如何在 React Native 中将元素固定在滚动上?
【发布时间】:2019-04-18 10:18:02
【问题描述】:

这是我目前所拥有的视频https://drive.google.com/file/d/1tJMZfpe8hcqLcNMYiE-6pzwHX0eLofv1/view?usp=sharing

我正在尝试在 contentOffset.y 到达标题后修复“可用 3 个月”。类似于 css 中的 position: sticky 会做什么。

到目前为止,我想通过滚动视图组件中的 onScroll 属性来执行此操作,但问题是,我已经有了来自父子组件的动画 (Animated.Event),这对我来说是唯一的方法要做到这一点,可以通过Animated.Event 中的listener 函数来实现,但是如果useNativeDriver 选项设置为false,那么这样做会导致动画超级断断续续。

如果我将其设置为 true,那么整个事情将无法正常工作(它会崩溃)。错误是“onScroll 不是一个函数,它是 Animated.event 的一个实例”

所以,假设我们有两个组件,父组件是 Parent.js,子组件(滚动视图)是 ChildScrollView.js

ChildScrollView.js 已经在滚动视图上有动画,但是我们需要在 Parent.js 组件中添加更多,以处理 ChildScrollView.js 无法处理的导航

所以它的编码是这样的:

Parent.js

componentWillMount() {
    const { navigation } = this.props
    const { scrollY } = this.state

    const bgColor = scrollY.interpolate({
      inputRange: [HEADER_HEIGHT / 4, HEADER_HEIGHT / 2],
      outputRange: ['transparent', 'rgb(255,255,255)'],
      extrapolate: 'clamp',
    })

    const titleColor = scrollY.interpolate({
      inputRange: [0, HEADER_HEIGHT / 2],
      outputRange: ['transparent', colors.paragraphs],
      extrapolate: 'clamp',
    })

    const titleMarginTop = scrollY.interpolate({
      inputRange: [0, HEADER_HEIGHT / 2],
      outputRange: [HEADER_HEIGHT, 0],
      extrapolate: 'clamp',
    })

    navigation.setParams({
      bgColor,
      titleColor,
      titleMarginTop,
    })
}

onScroll() {
}

render() {

  return (
    <ChildScrollView
      {...childProps}
      onScroll={Animated.event([
        { nativeEvent: { contentOffset: { y: scrollY } } },
      ], {
        useNativeDriver: false, // when I do this, it become super laggy, but setting it to true makes the app crash
        listener: this.onScroll,
      })}
    >
      <MakeMeFixedOnScroll>I could do this in css with "position: sticky"</MakeMeFixedOnScroll>
    </ChildScrollView>
  )
}

和孩子差不多,

<Animated.ScrollView
 {...props}
 onScroll={Animated.event(
   [{ nativeEvent: { contentOffset: { y: scrollY } } }],
            {
              useNativeDriver: false,
              listener: event => {
                if (onScroll) onScroll(event)
              },
            }
          )}
          scrollEventThrottle={16}
        >

【问题讨论】:

  • 这个article 可能会提供一些帮助:)
  • @VilleKoo 谢谢你,我已经完成了那篇文章中的设置。问题是我需要添加一个不依赖于 Animated.Value() 而是依赖于 contentOffset 的动画。做到这一点的唯一方法是添加“监听器”函数,但是当我这样做时 - 启用“useNativeDriver”会导致错误[onScroll 不是函数,它是 Animated.event 的实例]。没有它,动画太滞后了
  • 嗨@StephenJesse,我遇到了同样的情况。您对此有任何更新或解决方案吗?如果您能帮助我,我将非常高兴
  • @marwin 抱歉,我有一段时间没有在这个网站上活跃了,我最终所做的只是为滚动 Y 值添加了一个侦听器。一旦它到达某个位置,我通过添加图像、标题等的框架高度来计算,我将横幅的位置设置为固定,并将顶部、左侧、右侧的插图设置为 0。在反向滚动中做了同样的事情.可能不是一个好的解决方案,我想现在你可以使用 React native 重新动画制作更清洁的东西,但我最终放弃了那个项目,从那以后我就再也没有回去过它了。如果你愿意,我可以把代码发给你吗?
  • @StephenJesse 非常感谢斯蒂芬的回复。我尝试使用相同的方法,但最终,它并不像我预期的那么顺利。是的,非常感谢。我很想看看你的代码

标签: javascript reactjs react-native react-animated


【解决方案1】:

我会使用 SectionList

<SectionList
  renderItem={({item, index, section}) => (
    <Text style={styles[item.type]}>{item.text}</Text>
  )}
  renderSectionHeader={({ section: { title } }) => (
    title && <Text style={styles.sticky}>{title}</Text>
  )}
  sections={[
   { title: null, data: [{
       type: 'heading', text: '133 Random Road'
     }, {
       type: 'heading', text: 'Donnybrook'
     }, {
       type: 'subtitle', text: 'Dublin 4'
     }, {
       type: 'title', text: 'From E1000/month'
     }]
   },
   { title: 'Available For 3 Month', data: [{
       type: 'text', text: 'Beautiful for bedroom...'
     }]
   }
  ]}
  stickySectionHeadersEnabled
/>

【讨论】:

  • 我实际上是通过向“Animated.Value”添加一个侦听器来实现的。但是,我需要进行一些测试,以确保它适用于所有设备。在我的 iPhone XS Max 上测试。
  • 你确定它可能适用于安卓系统吗?不要过度设计很重要
  • 这是一个公平的观点。我不知道部分列表与我已经设置的整个 Parralax Header 的工作情况如何
猜你喜欢
  • 2013-03-21
  • 2020-05-09
  • 1970-01-01
  • 2022-10-14
  • 2019-01-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多