移动端,tab内的组件有滚动条时,tab滚动不了的问题

问题背景,我们的移动端tab设计支持滚动,而当内部组件有滚动条时,手机端会有默认的橡皮筋回弹效果,导致滑动到内部有滚动条的内容时,触发内部滚动条的橡皮筋回弹,如果不等待这个回弹效果消失,则无法触发外部滚动条。

问题:怎么优化这个体验解决问题。

竞品调研,观远采用了tab设计为不支持滚动,自适应的方案,因此通常不存在内外都有滚动条的场景,除了内嵌html的场景,但观远内嵌html下,发现他们的表格仍然不会触发滚动回弹,这一部分对比了观远的表格的设计,分析发现问题出在我们的滚动条,对比观远,观远是滚动条是独立组件,滚动时动态设定高度,而我们没有特殊处理滚动条,仅仅通过计算高度渲染需要显示的元素,在滚动效果上,我们的滚动条没法避开弹性效果。【观远是滚动时修改滚动条的属性计算,因为动态改变滚动条高度的同时,会阻止掉弹性回弹的效果,所以观远没有触发弹性回弹】下面是观远的,滚动条的位置,是动态设置的。

Untitled

解决方案

所有场景处理

方案1:

尝试方案1:处理所有场景,全局代理滚动条,自己实现一套滚动链,即所有滚动手势都由统一的代理处理,全局判断当前滚动组件和滚动方向,js控制滚动。针对这个方案,由于原生模块对手势也有类似的全局代理、图表模块的业务有屏蔽事件传递,整体评估会有风险。最终回退掉了该方案。

从业务层面处理使用场景下的滚动冲突问题

主要处理表格,为什么没有在图表实践这个方案,一是大部分场景不是浏览器滚动而是canvas内部滚动,不需要考虑,只有在图表canvas,超出组件高度导致浏览器出现了默认滚动条,才会出现这种弹性滚动的场景,有碰到,但这类问题可以归类为图表自适应高度的bug,图表自适应组件高度,能够解决这个问题。图表的业务需要在某些场景下阻止滚动手势的传递,直接针对修改图表业务,或者在事件传递阶段处理,方案都不合适,因此评估结果是不处理图表场景的问题。

方案2:表格和观远一样,滚动条用采用独立的组件,方案存在业务风险,并且调整较大,首先需要屏蔽默认滚动条,重新做滚动条需要对已有场景做归纳【滑动,惯性滚动,移动端全局对一些原生操作的屏蔽】,这块内容相对较多,适合作为长期实践方案考虑,不适合处理当下问题。

方案3:表格自己控制滚动,滚动事件里适当时机加上e.preventDefault或者stopPropagation的方式,preventDefault可以让滚动条消失,自然没有滚动回弹,边界时取消preventDefault以便滚动链传递。stopPropagation,不会屏蔽滚动条,也不用考虑滚动链,但会在保留弹性回弹的时候仍然滚动,不会只回弹而滚不动。这两个方向由于交互的不友好废弃了。

方法4:利用css:overscroll-behavior,但这个方法会屏蔽到滚动链的传递,所以需要js在滚动时做判定,表格的纵向滚动条用js控制,使其不走浏览器默认的滚动条逻辑。屏蔽掉后,用手势控制计算滚动条位置 ( overflow:hiden 、scrollTop、scrollHeight)。比如当滚动到底部时,去掉overscroll-behavior:none屏蔽掉的滚动回弹效果以识别触发滚动链判断(这个属性会同时屏蔽掉滚动链,因为要保证滚动到表格底部时,外部正常滚动不被影响,这个操作是抬手再滑动的操作,因此在边缘时,通过延迟一个操作时间,将属性移除以响应滚动链)【目前已经采用这种设计】

Untitled

最终实现效果是:内外侧都有滚动条,当内测是可滚动表格时,内测滚动到底部,且不触发回弹,当抬起手重新滚动时,因为内部滚动到底,触发滚动外部滚动条。

0f4efb81f9a05f89c37fb57e0ddf28be.mov

所有场景处理

方案5:这个方案是参考观远,将tab设计为自适应方式,目前认为该方案是最合适的方案,自适应逻辑方案调整会对整体有比较大影响,【布局插件、移动端h5】,所以优先排功能迭代,再做这个优化,先用方案2处理大部分场景。