Lynx UI logo
Lynx UI

<Scrollview>

一个适用于 ReactLynx 的滚动容器组件,提供滚动基础能力和回弹处理。
  • 利用 LazyComponent内置懒加载能力的滚动容器,用于优化首屏耗时;
  • 内置双端对齐的 bounces 能力。
Info

你可以查看源码来了解它的运行原理,也欢迎大家提 MR 来丰富其能力。

使用指南
如何理解 `bounceableOptions`

基础用法

使用<ScrollView>提供滚动能力

ScrollViewProps

Properties

androidTouchSlop
Android
类型default | paging
Android 触摸识别模式,当处于支持 'paging' 模式的元件中时,需要开启 'paging' 模式。
bounceable
iOS
Android
类型boolean
启用弹性效果
bounceableOptions
iOS
Android
类型boolean | {alwaysBouncing?: boolean, debugLog?: boolean, enableBounceEventInFling?: boolean, enableBounces: boolean, endBounceTriggerDistance?: number, estimatedHeight?: number, estimatedWidth?: number, lowerBounceItem?: any, onScrollToBounces?: (e: {direction: upper | lower}) => void, singleSidedBounce?: upper | lower | both | iOSBounces | none, startBounceTriggerDistance?: number, upperBounceItem?: any, validAnimationVersion?: boolean}·默认值{ enableBounces: true, singleSidedBounce: "iOSBounces" },
弹性效果的参数
children
iOS
Android
类型ReactNode
scroll-view 的子元素。
className
iOS
Android
Harmony
类型string
类名
debugLog
iOS
Android
Harmony
类型boolean·默认值false
显示回弹交互的调试日志。
enableRTL
iOS
Android
Harmony
类型boolean·默认值false
是否在 RTL 模式下镜像水平回弹方向。
enableScroll
iOS
Android
Harmony
类型boolean·默认值true
启用滚动。
enableScrollMonitor
iOS
Android
Harmony
类型boolean·默认值false
启用滚动监控。
estimatedItemStyle
iOS
Android
类型CSSProperties
需要设置 items 的预计高度和宽度。
exposureBottom
iOS
Android
类型string·默认值'10px'
曝光屏幕下方边距
exposureID
iOS
Android
Harmony
类型string
用于全局曝光的 exposure-id
exposureLeft
iOS
Android
类型string·默认值'10px'
曝光屏幕左侧边距
exposureRight
iOS
Android
类型string·默认值'10px'
曝光屏幕右侧边距
exposureScene
iOS
Android
Harmony
类型string
用于全局曝光的 exposure-scene
exposureTop
iOS
Android
类型string·默认值'10px'
曝光屏幕上方边距
firstScreenItemCount
iOS
Android
类型number·默认值1
懒加载时预计的第一页项数。剩余的子元素会基于曝光状态完成渲染。当此预估较小时,可能会导致第一屏出现空白现象。
horizontal
iOS
Android
类型boolean
水平滚动。
iOSBounces
iOS
Android
类型boolean·默认值true
开启iOS上的回弹效果。如果想在安卓上使用,请参考bounceableOption。如果设置了bounceableOption,iOSBounces属性将失效。
lazy
iOS
Android
类型boolean·默认值true
启用懒渲染。只有当用户滚动到可见区域时,才会渲染 items,从而减少初始加载时间和内存使用。
lazyOptions
iOS
Android
类型LazyOptions·默认值true
启用懒渲染。只有当用户滚动到可见区域时,才会渲染 items,从而减少初始加载时间和内存使用。
main-thread:gesture
iOS
Android
类型BaseGesture
如果想使用 gesture API,请传入该属性。
onUIAppear
iOS
Android
Harmony
类型(e: CommonEvent) => void
UI 的曝光事件。
onUIDisappear
iOS
Android
Harmony
类型(e: CommonEvent) => void
UI 的消失事件。
scene
iOS
Android
类型string
用于标记懒加载的曝光时机。请确保页面中唯一。
scrollMonitorTag
iOS
Android
Harmony
类型string·默认值false
滚动监控的标签。
scrollOrientation
iOS
Android
Harmony
类型vertical | horizontal·默认值'vertical'
设置为 'vertical' 为垂直滚动,设置为 'horizontal' 为水平滚动。
scrollPropagationBehavior
iOS
Android
类型ScrollPropagationBehaviorOption·默认值'native'
控制滚动事件是否向父级容器传递。'preventPropagate' 在 iOS 上暂时需与 temporaryBlockScrollClass 和 temporaryBlockScrollTag 配合使用。 Currently, this property has limitations because its full functionality depends on a higher native SDK version: on iOS, propagate only works if both the parent and this component are set to propagate and useRefactorList={true} does not support 'propagate'. On Android, preventPropagate only functions when the parent is x-swiper or x-viewpager-ng.
scrollviewId
iOS
Android
类型string·默认值"scrollview"
滚动视图的id。
sticky
iOS
Android
类型ReactElement
粘性元素,设计用于 Tabs
style
iOS
Android
Harmony
类型CSSProperties
样式
temporaryBlockScrollClass
iOS
类型string·默认值'BDXLynxViewPager'
当 scrollPropagationBehavior 设为 'preventPropagate' 时,被阻止滚动的容器的具体类名。'preventPropagate' 需与 temporaryBlockScrollClass 和 temporaryBlockScrollTag 配合使用。 This is a temporary props and will be deprecated on new Lynx SDK version.
temporaryBlockScrollTag
iOS
类型number·默认值0
用于指定当 scrollPropagationBehavior 设为 'preventPropagate' 时被阻止滚动的原生容器标签(对应 UIView 的 Tag 属性)。该值需由原生容器提供方指定,且 'preventPropagate' 必须与 temporaryBlockScrollClass 和 temporaryBlockScrollTag 配合使用。 This is a temporary props and will be deprecated on new Lynx SDK version.
temporaryNestedScroll
Android
类型boolean
仅 Android 生效的临时开关,用于控制嵌套滚动冲突;映射到原生属性 'enable-nested-scroll'。Android上默认开启。
testing
iOS
Android
类型boolean
测试模式

Events

catchLongPress
iOS
Android
Harmony
类型(e: EventHandler | undefined) => void
与 onLongPress 相同,但会阻止事件冒泡。
catchTouchCancel
iOS
Android
Harmony
类型(e: EventHandler | undefined) => void
与 onTouchCancel 相同,但会阻止事件冒泡。
catchTouchEnd
iOS
Android
Harmony
类型(e: EventHandler | undefined) => void
与 onTouchEnd 相同,但会阻止事件冒泡。
catchTouchMove
iOS
Android
Harmony
类型(e: EventHandler | undefined) => void
与 onTouchMove 相同,但会阻止事件冒泡。
catchTouchStart
iOS
Android
Harmony
类型(e: EventHandler | undefined) => void
与 onTouchStart 相同,但会阻止事件冒泡。
onContentSizeChange
iOS
Android
类型(res: Record<string, unknown>) => void
滚动内容变化时触发。
onLayoutChange
iOS
Android
Harmony
类型(e: EventHandler | undefined) => void
当 UI 视口大小改变时发送。
onLongPress
iOS
Android
Harmony
类型(e: EventHandler | undefined) => void
当触摸点在 UI 上按住一段时间后发送。
onScroll
iOS
Android
类型(e: ScrollEvent) => void
滚动时触发。
onScrollEnd
iOS
Android
类型(e: [object Object] | undefined) => void·默认值undefined
滚动停止时触发。
onScrollToLower
iOS
Android
类型(e: [object Object] | undefined) => void·默认值undefined
滚动到底部时触发。
onScrollToUpper
iOS
Android
类型(e: [object Object] | undefined) => void·默认值undefined
滚动到顶部时触发。
onTap
iOS
Android
Harmony
类型(e: EventHandler | undefined) => void
当触摸点在 UI 上轻触时发送。
onTouchCancel
iOS
Android
Harmony
类型(e: EventHandler | undefined) => void
当触摸事件在完成前被中断或取消时发送。
onTouchEnd
iOS
Android
Harmony
类型(e: EventHandler | undefined) => void
当触摸点从 UI 上移除时发送。
onTouchMove
iOS
Android
Harmony
类型(e: EventHandler | undefined) => void
当触摸点在 UI 上移动时发送。
onTouchStart
iOS
Android
Harmony
类型(e: EventHandler | undefined) => void
当触摸点放置在 UI 上时发送。

BounceableBasicProps

alwaysBouncing
iOS
Android
Harmony
类型boolean·默认值true
当可滚动容器的内容区域小于视口区域时,是否允许容器回弹。
debugLog
iOS
Android
Harmony
类型boolean·默认值false
显示调试日志。当您发现错误时,请打开此选项。
enableBounceEventInFling
iOS
Android
Harmony
类型boolean·默认值false
在快速滑动(fling)时触发回弹效果
enableBounces
iOS
Android
Harmony
类型boolean
是否开启回弹效果
endBounceTriggerDistance
iOS
Android
Harmony
类型number·默认值0
触发 scrollToBounces 事件时,下部回弹的阈值距离(单位:px)
estimatedHeight
iOS
Android
Harmony
类型number
单位:px。可选的回弹效果尺寸提示。在列表或 <list/> 中使用时推荐设置。
estimatedWidth
iOS
Android
Harmony
类型number
单位:px。可选的回弹效果尺寸提示。在列表或 <list/> 中使用时推荐设置。
lowerBounceItem
iOS
Android
Harmony
类型any
下部回弹视图的内容,将在下部回弹效果期间显示。
singleSidedBounce
iOS
Android
Harmony
类型upper | lower | both | iOSBounces | none·默认值'both'
回弹效果的方向。'both' 表示两端都回弹,'none' 表示禁用回弹,'upper'/'lower' 表示只在上端或下端回弹。
startBounceTriggerDistance
iOS
Android
Harmony
类型number·默认值0
触发 scrollToBounces 事件时,上部回弹的阈值距离(单位:px)
upperBounceItem
iOS
Android
Harmony
类型any
上部回弹视图的内容,将在上部回弹效果期间显示。
validAnimationVersion
iOS
Android
Harmony
类型boolean·默认值false
requestAnimationFrame 在 lynx 2.15.2 以下版本中不起作用。当版本高于 2.15.2 时,应打开此开关。
onScrollToBounces
iOS
Android
Harmony
类型(e: {direction: upper | lower}) => void·默认值0
当触发回弹效果并且回弹距离在上侧或下侧大于 startBounceDistanceendBounceDistance 时,将触发 scrollToBounces 事件。

scrollToBouncesInfo

direction
类型upper | lower

属性解析

让我们来看看 useBounces 是如何实现的。这个 hooks 能绑定在任何一个可滚动容器上。

输入和输出

首先让我们把这个 hooks 当作一个黑盒,这个盒子会接收组件设置,然后返回一系列能够响应滚动容器事件的操作方法:

  • 输入:options

  • id: 可滚动容器的 id。我们认为这个 id 是必须设置的,这是为了避免同一页面下存在相同的可滚动容器之间的混淆。

  • scrollOrientation: 可滚动容器的方向。可以为横向或纵向。

  • bounceableOptions: 对 hook 的额外设置属性,包括这一些子项:

    • enableBounces: 是否开启弹性效果。
    • startBounceTriggerDistance/endBounceTriggerDistance: onScrollToBounces 的设置,只有当弹性效果超出该阈值,这个事件才会触发。一般用于 ”右滑跳转“ 这种场景。
    • enableBounceEventInFling: 是否在滚动容器的惯性滚动过程中触发弹性效果。
    • upperBounceItem/lowerBounceItem: 出现在弹性区域的内容。
    • alwaysBouncing: 在滚动容器实际不可滚动时是否也能够出现弹性效果。
    • singleSidedBounce: 让弹性效果只在单端生效。
    • onScrollToBounces: 在弹性效果超出指定阈值后触发事件,让小幅度的回弹效果不触发这个事件。
  • 输出:一系列用于绑定在滚动容器上的函数。

    • main-thread:bindtouchstart/main-thread:bindtouchend/main-thread:bindtouchmove: 用于接收滚动容器的触摸事件并进行处理。
    • main-thread:bindlayoutchange: 用于获取滚动容器的实际宽高
    • main-thread:bindscroll/main-thread:bindscrollend: 用于接收滚动容器的滚动事件并进行处理。
    • onUpperExposure/onUpperDisexposure/onLowerExposure/onLowerDisexposure: 用于处理滚动容器是否处于边界,弹性效果仅出现在滚动容器触边的情况下。

如何形成滚动

我们在这里使用了 MTS 调用 transform 来模拟弹性效果。

  1. 使用 id,通过 lynx.querySelector 找到节点。
lynx.querySelector(`#${containerID}`)
  1. 从滚动曲线函数中获取 touchmove 所对应的滚动曲线,然后进行相应 transform

useBounces 将滚动曲线分为了三段:

  1. 响应 touchmove 的橡皮筋效果
  2. 惯性滚动效果
  3. 回弹效果

bounceableOptions 的各属性如何使用?

onScrollToBounces 事件和 startBounceTriggerDistance/endBounceTriggerDistance

该事件只在完成回弹效果之后触发,这代表着它需要两个前提条件:

  1. touchEnd 时滚动容器处于顶部回弹区域或底部回弹区域,不在正常区域。这保证了回弹可以触发,需要在这个事件里完成的效果都应在真实的回弹效果触发之后。如果用户拖动到回弹区域,又再次拖拽至非回弹区域,这意味着对 onScrollToBounces 事件的取消,这个事件不应被触发。
  2. 当前这个回弹效果已经结束,滚动容器重新处于正常滚动区域边缘。

为了不让微小的回弹效果也能触发这个事件,导致事件触发过于灵敏,我们为它添加了回弹距离阈值,也就是 startBounceTriggerDistance/endBounceTriggerDistance。 只有当最远的回弹距离超过设定的阈值时,这次回弹结束时才会触发 onScrollToBounces 事件。

enableBounceEventInFling

滚动容器在正常滚动区域发生触摸滑动时,如果在触摸结束时滚动容器的速度过大,就会进入惯性滚动阶段。在这个惯性滚动阶段中,滚动容器也可能中途滚动到边缘。这种情况下,我们可以让这个惯性滚动的剩余速度直接触发回弹效果,enableBounceEventInFling属性将为你触发这种回弹模式,这也是默认的回弹模式。考虑到有一些场景可能需求更明确的回弹交互 —— 回弹效果不能发生在一次惯性滚动中,而必须由一次触摸滑动行为触发,我们将这个行为设定成了可配置项。

upperBounceItem/lowerBounceItem 会出现在哪里?

它们只会出现在回弹区域。一旦弹性效果触发,用户将能看到你在这里渲染的节点。它们不是必须设置的,在未设置的情况下,回弹区域将展示滚动容器下层渲染的内容,因为滚动容器仍然被 translate,离开了原本的位置。

alwaysBouncing

在一些情况下,滚动容器本身可能并不能滚动。开启这个属性能让回弹效果的边缘检测仍然生效,这意味着即使滚动容器无法真正发生滚动行为,它仍然能够出现回弹效果。

除非另有说明,本项目采用知识共享署名 4.0 国际许可协议进行许可,代码示例采用 Apache License 2.0 许可协议进行许可。