vue实现上下滑动翻页_知乎里的一些特效实现 无缝拖拽的 Layout

本文作者

作者:JarvisGG

链接:https://jarvisgg.github.io/

本文由作者授权发布。

1 前言

今年年初接触回答页面改版,由之前的左右滑动回答改为上下滑动回答,由于当时回答页的代码太过于庞大,所以第一次改版复用了之前的 UI 框架,外层 ViewPager + Fragment,内层是 WebView 嵌套 Hybrid 页面。

问题出现了,WebView 可以滚动的时候,会持有整个 Touch 事件流程,导致当 webView 拖拽到底部,手指不脱离屏幕继续拖拽的时候,无法将当前的拖拽操作给翻页器,产生体验上的割裂感。

接下来就是 UI 交互优化的历程。

2 调研

1.NestedScrolling:

Support V4 提供了一套 API 来支持嵌入的滑动效果。NestedScrolling 提供了一套父 View 和子 View 滑动交互机制。要完成这样的交互,父 View 需要实现 NestedScrollingParent 接口,而子 View 需要实现 NestedScrollingChild 接口。

作为一个可以嵌入 NestedScrollingChild 的父 View,需要实现 NestedScrollingParent,这个接口方法和 NestedScrollingChild 大致有一一对应的关系。同样,也有一个 NestedScrollingParentHelper 辅助类来默默的帮助你实现和 Child 交互的逻辑。滑动动作是 Child 主动发起,Parent 就收滑动回调并作出响应。

从上面的 Child 分析可知,滑动开始的调用 startNestedScroll(),Parent 收到 onStartNestedScroll() 回调,决定是否需要配合 Child 一起进行处理滑动,如果需要配合,还会回调 onNestedScrollAccepted()。

每次滑动前,Child 先询问 Parent 是否需要滑动,即 dispatchNestedPreScroll(),这就回调到 Parent 的 onNestedPreScroll(),Parent 可以在这个回调中“劫持”掉 Child 的滑动,也就是先于 Child 滑动。

Child 滑动以后,会调用 onNestedScroll(),回调到 Parent 的 onNestedScroll(),这里就是 Child 滑动后,剩下的给 Parent 处理,也就是 后于 Child 滑动。

最后,滑动结束,调用 onStopNestedScroll() 表示本次处理结束。
这个方案其实很不错,但最后被 pass 了,因为由于工程的原因,我们的 webview 是被包裹起来的,不可以任意去继承 NestedScrollingChild 并做定制修改。

2.自定义 ViewGroup

其实目前的问题是当子 View scroll 到顶部或者底部的时候,无法将 Touch 事件流交还给父布局。
因此这里我采用的思路是通过我的 ViewGroup 去统一 dispatchTouchEvent 给我的子 View,条件就是,假如子 View 可以滚动,我就会构造一套完整的 touch 时间流分发给他。否则我会自己消化。

解决方案

step 1:

通过第二种方式的思路,我们第一步需要在我的 ViewGroup 拦截所有的 Touch 事件。所以…

@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
    if (isParentDispatchTouchEvent) {
        return true;
    } else {
        return super.onInterceptTouchEvent(ev);
    }
}

上来我们就拦截出所有的 Touch 事件。

step2:

开始在 ViewGroup 的 onTouchEvent 处理所有相关的 Event。

// 1.初始记录 Touch 坐标
int mDownY = event.getY();
int deltaY = 0;
// 2.默认子 View 持有事件流起始点 isHoldTouch = true,通过 isChildCanScroll 来判别当前子 View 是否可以滚动。
if (isHoldTouch && !isChildCanScroll(event, deltaY) && deltaY != 0) {
    // 3.假如子 View 不可以滚动,当前 ViewGroup 需要阻断 Touch 的下发,为了遵循 Touch 事件流的规范,当被外部阻断时,需要对其下发 ACTION_CANEL。同时 isHoldTouch = false。
    isHoldTouch = false;
    MotionEvent canc
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值