如何基于Reanimated动画值设置ScrollView的scrollEnabled属性
Reanimated 2.4.1 动态设置ScrollView scrollEnabled 正确实现
两种写法失效的核心原因:
- 误用
useAnimatedStyle存储动画值:这个hook的作用是生成动画样式对象,不具备状态存储能力。直接读取.value给组件普通props传值时,UI线程更新的动画值不会触发JS线程组件重渲染,属性只会停留在初始值。 - 未处理属性白名单:
scrollEnabled不属于Reanimated默认支持的动画属性,就算正确写了useAnimatedProps,框架默认不会把这个属性的更新同步到原生组件层。另外把animatedProps展开传递的写法,也会导致Reanimated无法正确绑定属性更新逻辑。
实现步骤
- 提前把
scrollEnabled加入Reanimated UI属性白名单,让框架支持直接在UI线程更新这个属性,不需要走JS线程重渲染 - 用
useSharedValue存储滚动开关的动画状态,不要用useAnimatedStyle - 通过
useAnimatedProps生成属性对象,显式传给Animated组件的animatedProps属性,不要展开传递
代码示例
import React from 'react'; import { ScrollView, Button, View } from 'react-native'; import Animated, { useSharedValue, useAnimatedProps, addWhitelistedUIProps, } from 'react-native-reanimated'; // 注册scrollEnabled为UI线程可更新属性,写在组件作用域外即可 addWhitelistedUIProps({ scrollEnabled: true, }); // 生成适配后的动画ScrollView组件 const AnimatedScrollView = Animated.createAnimatedComponent(ScrollView); export default function Demo() { // 存储滚动状态,初始值设为可滚动 const isScrollEnabled = useSharedValue(true); // 定义动画属性 const scrollProps = useAnimatedProps(() => ({ scrollEnabled: isScrollEnabled.value, })); // 切换滚动状态示例 const toggleScroll = () => { isScrollEnabled.value = !isScrollEnabled.value; }; return ( <View style={{ flex: 1 }}> <Button title="切换滚动开关" onPress={toggleScroll} /> <AnimatedScrollView animatedProps={scrollProps}> {/* 滚动区域内容 */} </AnimatedScrollView> </View> ); }
注意事项
- 不要直接读取
sharedValue.value给普通scrollEnabled属性传值:sharedValue默认在UI线程更新,不会触发JS层重渲染,后续状态变化不会同步到组件。 - 如果只是普通业务逻辑控制滚动开关,不需要跟动画流程联动,直接用React state存值传递即可,没必要用Reanimated动画属性。
- 不要把
animatedProps对象展开到组件props上,必须传给组件的animatedProps专用属性,否则Reanimated无法建立更新绑定。
内容的提问来源于stack exchange,提问作者pedroGarciyaLopez
相关产品推荐
相关产品推荐

