CoordinatorLayout效果展示
CoordinatorLayout工作原理
CoordinatorLayout,可译为协调者布局,用于协调多个子View进行滑动交互
CoordinatorLayout实现滑动交互逻辑的核心是Behavior类,Behavior类规定子View间如何进行交互
CoordinatorLayout实现了一个自己的LayoutParam
CoordinatorLayout会为每个子View的LayoutParam设置一个Behavior
子View具体使用哪个Behavior,可以在xml布局中,通过自定义属性layout_behavior来指定
CoordinatorLayout在处理onTouchEvent时,会将事件转交给Behavior去处理,具体如何处理事件,是由Behavior中的逻辑来决定的
CoordinatorLayout交互动画
具体如何交互取决于Behavior代码,这里主要是介绍我们的Demo的动画逻辑
CoordinatorLayout包含三个子View,Text + Image + Toolbar
其中Text被NestedScrollView包裹,可以滑动
Toolbar在Image上层叠加显示,二者通过大小和透明度变化,形成滑动动画效果
默认状态:
Image完全展示,Toolbar透明度为0,Text滑动到顶端
Text向上滑动:
Toolbar透明度逐渐增加到100,Image逐渐变小,当Image和Toolbar一样大小时,不再变小,Toolbar透明度仍然继续增加
Text向下滑动:
Toolbar透明度逐渐减小到0,当Toolbar透明度为0时,Image逐渐变大,直到最大为止
NestedScrollView和CoordinatorLayout的关联
NestedScrollView是一个可以滚动的容器,它继承自FrameLayout,在基类的基础上增加了滑动功能
CoordinatorLayout继承自ViewGroup,它不处理任何布局功能,只是把布局工作转交给Behavior去处理
NestedScrollView和CoordinatorLayout联系起来的纽带在于
NestedScrollView实现了NestedScrollingChild接口,CoordinatorLayout实现了NestedScrollingParent接口
当Child进行滑动时,它会通知Parent,仅此而已
通过以上分析,我们基本可以确定这样一个事实
NestedScrollView仅负责滑动,CoordinatorLayout负责将布局事件和滑动事件等全部工作转发给子View
Behavior才是决定,子View如何进行布局,如何进行滑动交互的关键类
CoordinatorLayout的简单替代方案
其实,上面的动画,我们就算不用CoordinatorLayout,也可以很轻松地手动实现
无非就是监听ScrollView的滑动距离变化,然后控制Image大小和Toolbar透明度,这么简单的事情而已
其实CoordinatorLayout最终的工作,也就是这么简单而已
CoordinatorLayout出现的真正意义在于,它抽象了一套关于滑动交互逻辑的接口
使用CoordinatorLayout的话,全部的工作最后是交给Behavior去处理的
当我们需要使用新的子View,新的交互动画时,只要替换Behavior的实现类即可
可以看出,CoordinatorLayout的真正意义在于解耦,将交互动画的逻辑和控件解耦了,无需修改控件
如果我们用最简单的方法去实现,那么只要子View类型换一下,布局换一下,交互动画换一下,就得重新写一套控件
核心代码
@SuppressWarnings("all")
public class CoordinatorLayout extends RelativeLayout implements NestedScrollingParent, ViewTreeObserver.OnGlobalLayoutListener {
float lastX;
float lastY;
public CoordinatorLayout(Context context) {
super(context);
}
public CoordinatorLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public LayoutParams generateLayoutParams(AttributeSet attrs) {
return new LayoutParams(getContext(), attrs);
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
getViewTreeObserver().addOnGlobalLayoutListener(this);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
for (int i = 0; i
关注
打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?