改版前的结构比较简单,头部显示圈子的基本信息比如图片、标题和简介等信息,底部展示圈子内的消息列表,向上滑动可折叠头部区域让用户更加专注地浏览消息列表,结构如下:
CoordinatorLayout
作为容器负责两部分的布局和联动滑动,AppBarLayout
负责展示头部信息,底部通过 ViewPager
和Fragment
实现多 tab
页面,Fragment
内部通过 RecyclerView
实现消息列表。
改版后:
改版后头部新增了一些元素比如插件、创建者,原有的元素展示区域扩大,导致头部高度增大。使得用户刚进入圈子页时几乎看不到消息列表区域,为了解决这个问题我们需要页面支持快速地在头部和列表之间切换,并且当头部超过一屏时也可以滑动。简单总结下我们的需求:
1、当头部信息较少,即没有达到一屏时表现和原有实现一致,头部随列表滑动可以折叠。
2、当头部信息较多,即超过一屏时除了头部随着列表滑动折叠外,还可以在头部和列表之间快速切换。
解决方案
第一条需求原有的 CoordinatorLayout
就可以支持,问题是第二条中的快速切换如何实现,最终我们的产品同事给出的解决方案如下:
从这个截图看上去好像和原来的将头部折叠一样,其实不然。将头部折叠需要先将头部滑到界面外,而这里头部其实没有滑动,列表是盖在头部上面,当想查看头部时再将列表滑下去。
有人可能会说,这和原来的有什么区别,都需要滑动。这种实现的好处主要有三点:
-
列表只会存在展开和隐藏两种状态,不会存在显示一半的情况,当将列表拖到屏幕中间松手时会自动滑动到展开或隐藏,降低头部和列表切换的难度。
-
当列表滑动几屏后,此时仍然可以拖动 scroll bar 将列表滑出展示头部,不需要将列表滑到最顶部再拉出头部。
-
当头部很长时,头部内容滑动在任何位置都可以拖动 scrollbar 滑出列表,不需要将头部滑到最底部。
这里的 scrollbar
是个辅助组件,后面会讲到,这里先不展开。原有的 CoordinatorLayout
不能满足上述需求,所以我们需要实现一个自定义组件,由于这个组件的主要功能就是将页面底部滑出滑进,所以我们将这个组件命名为SlideLayout
。
嵌套滚动
不管是原有逻辑还是新增的,都属于一对嵌套组件的联动交互,不难看出需要用到嵌套滚动机制来实现。首先我们简单了解下嵌套滚动的机制:
图中 Parent 表示实现了 NestedScrollingParent
接口的组件,Child 表示实现了 NestedScrollingChild
接口的组件,Parent
接受 Child
分发的滚动事件,而且他们不直接关联。
SlideLayout 结构
如上图在 SlideLayout 中当下拉出刷新动画时可以看到三个组件:refresh、header 和 slider,它们的含义如下:
-
refresh
:当用户下拉刷新页面时 refresh 负责展示加载动画。 -
header
:负责页面头部,需要包含实现NestedScrollingChild
的组件从而向SlideLayout
分发滚动事件。 -
slider
:负责列表区域,也需要包含实现NestedScrollingChild
的组件,原因同header
。
实现 NestedScrollingChild
的组件有NestedScrollView
、RecyclerView
等,就圈子详情页这个页面来说,NestedScrollView
实现了页面头部,RecyclerView
实现了消息 列表。
操作状态
在处理 SlideLayout
中的滚动事件时,我们用一个枚举类型定义了三个状态:
enum class SlideGesture { SCROLL, SLIDE, REFRESH }
SCROLL
slider
和 header
处于连接的状态,即 header
的底边连着 slider
的顶边没有重叠。此状态时需要和老版本保持一致,即头部随着列表的滚动而滚动。如下图:
SLIDE
slider
盖在 header
上面,slider
此时有可能展示也有可能隐藏,主要工作是将 slider
滑出或者隐藏。如下图:
REFRESH
展示刷新动画,即刷新动画部分高度大于0
。下图只展示了从 Scroll
状态转换而来的情况,其实从 Slide
状态也可以进入 Refresh
状态,和这个类似会在头部上面出现一个刷新动画展示区域,这里就不列出了。
三个状态的彼此转换关系如下图:
确认了状态定义后剩下的工作基本就分为两部分:状态识别和滚动处理。
状态识别
根据前面讲的状态定义可得出状态判断逻辑如下:
我们将 Refresh 状态的优先级设为最高,先判断刷新区域的高度是否大于 0
来检查是不是 Refresh 状态。由于 Slide 的定义是 slider
和 header
有重叠,而 slider
在 SlideLayout
中是通过 sliderTop
来表示位置的,所以我们可以通过 sliderTop < headerHeight
来判断是不是 Slide 状态。最后两个条件都不满足的话就是 Scroll
状态了。
滚动处理
针对不同状态,对滚动事件定义了不同的处理规则,从而实现我们需要的交互效果。具体的处理逻辑见下表:
横向表示三种状态,竖向表示两种滚动事件类型,组合出六种不同的 case。这里给出的逻辑处理比较简单,实际实现时会遇到很多需要特殊处理的情况,这里就不一一列出了,感兴趣的同学可以查看项目源码,项目地址会在最后给出。
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)
总结
其实客户端开发的知识点就那么多,面试问来问去还是那么点东西。所以面试没有其他的诀窍,只看你对这些知识点准备的充分程度。so,出去面试时先看看自己复习到了哪个阶段就好。
然而Android架构学习进阶是一条漫长而艰苦的道路,不能靠一时激情,更不是熬几天几夜就能学好的,必须养成平时努力学习的习惯。所以:贵在坚持!
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
QxaJ-1713528898472)]
[外链图片转存中…(img-IdIdJooe-1713528898473)]
然而Android架构学习进阶是一条漫长而艰苦的道路,不能靠一时激情,更不是熬几天几夜就能学好的,必须养成平时努力学习的习惯。所以:贵在坚持!
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!