1. 简单使用
CoordinatorLayout作为一个中间桥梁性质的布局,协调着内部的childView。之前对CoordinatorLayout有点误解,以为需要配合AppBarLayout才有一些比较炫酷的特效,大错特错,Behavior是CoordinatorLayout能够有协调作用以及能支持各种炫酷特效的的关键因素

1.1 布局文件中使用
1 | <android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" |
最关键的地方就在于app:layout_behavior,利用这个属性来确定的绑定的目标childView
指定绑定目标有3种方式:
1.在xml布局通过app:layout_behavior
2.在Java代码中,child.getLayoutParams().setBehavior()来指定
3.在目标childView类上,通过@DefaultBehavior来指定
1.2 MoveView
MoveView就是一个继承TextView的很简单的自定义View1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27public class MoveView extends TextView {
private float lastX, lastY;
public MoveView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public boolean onTouchEvent(MotionEvent event) {
int action = event.getAction();
float x = event.getRawX();
float y = event.getRawY();
if (action == MotionEvent.ACTION_MOVE) {
CoordinatorLayout.MarginLayoutParams layoutParams = (CoordinatorLayout.MarginLayoutParams) getLayoutParams();
//计算当前的左上角坐标
float left = layoutParams.leftMargin + x - lastX;
float top = layoutParams.topMargin + y - lastY;
//设置坐标
layoutParams.leftMargin = (int) left;
layoutParams.topMargin = (int) top;
setLayoutParams(layoutParams);
}
lastX = x;
lastY = y;
return true;
}
}
主要就是重写onTouchEvent()来使MoveView可以根据手指滑动在屏幕改变位置
1.3 一个简单的自定义Behavior
1 | public class SampleTitleBehavior extends CoordinatorLayout.Behavior<View> { |
CoordinatorLayout.Behavior
注意:
当在布局文件中使用了Behavior后,Behavior代码中确定的交互行为便直接奏效,初始化第一次加载CoordinatorLayout时,使用了Behavior的ChildView受到onDependentViewChanged()方法的影响,第一次加载的位置也会受到影响,导致和布局文件中指定的位置不相同
官方有好几个非常好的学习资料,例如:
android.support.design.widget.AppBarLayout$ScrollingViewBehavior
一个依赖AppBarLayout后,处理滑动事件的Behavior,对Behavior中的属性及方法有了大概了解后,可以学习具体细节的设计和优化
2. Behavior 行为
需要注意的是Behavior可以几乎包括所有的交互行为,配合ViewDragHelper应该能够实现出一些很炫酷的交互效果
2.1 常用的方法
构造方法有两个:
默认:public Behavior() {}
布局:public Behavior(Context context, AttributeSet attrs) { }
两个构造方法也比较容易理解,一个是默认的空参的构造方法,一个是带有布局属性AttributeSet的方法,有了这个构造方法,可以直接在布局文件中使用
根据Behavior的特性,可以将内部的方法分以下类:
测量与布局:1
2测量:public boolean onMeasureChild(){}
布局:public boolean onLayoutChild(){}
特定状态:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26//当Behavior添加到参数实例时,回调
public void onAttachedToLayoutParams(){}
//当Behavior与参数实例分离时,回调
public void onDetachedFromLayoutParams(){}
//当Behavior关联的对象想要定位到特定的矩形时,回调
public boolean onRequestChildRectangleOnScreen(){}
//当一个ChildView设置为回避属性时,回调
public boolean getInsetDodgeRect(){}
//当窗口发生改变时,回调
public WindowInsetsCompat onApplyWindowInsets(){}
//需要保存临时状态信息,回调
public Parcelable onSaveInstanceState(){}
//需要恢复临时状态信息,回调
public void onRestoreInstanceState(){}
//作用未知
public int getScrimColor(){}
//作用未知
public float getScrimOpacity(){}
确定依赖与绑定对象:1
2//根据参数来确定依赖与绑定对象
public boolean layoutDependsOn(){}
当依赖对象发生改变时:1
2
3
4
5//当依赖对象发生改变,包括位置,大小,颜色,进行回调
public boolean onDependentViewChanged(){}
//当依赖对象被移除时,进行回调
public void onDependentViewRemoved(){}
事件相关:1
2
3
4
5//拦截事件,在CoordinatorLayout把事件分发到childView之前
public boolean onInterceptTouchEvent(){}
//消费事件
public boolean onTouchEvent(){}
嵌套滑动:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20//CoordinatorLayout中的滑动嵌套childView开始启动一次嵌套滚动时,回调
public boolean onStartNestedScroll(){}
//嵌套滑动结束时,回调
public void onStopNestedScroll(){}
//当一次嵌套滑动被CoordiantorLayout识别并确定时,进行回调
public void onNestedScrollAccepted(){}
//嵌套滚动正在进行中并且绑定目标childView已经开始滚动或者被CoordinatorLayout接受后试图滚动
public void onNestedScroll(){}
//嵌套滚动正在准备更新进度,并且是在绑定目标childView已经出现滚动距离之前,回调
public void onNestedPreScroll(){}
//当嵌套滚动的childView正在开始fling或者一个动作确认为fling
public boolean onNestedFling(){}
//当滑动嵌套childView检测到适当的条件,马上开始一次fling事件前回调
public boolean onNestedPreFling(){}
暂时就这么分,分类并不算合理,也无所谓,目的是以后自己回头来看时,能比较清晰能快速定位方法是干嘛的
转:https://www.jianshu.com/p/9fdd271541d9