自定义CoordinatorLayout.Behavior 实现悬浮控件动画
来源:互联网 发布:c语言中的error 编辑:程序博客网 时间:2024/06/07 09:49
一、Behavior是什么?为什么要用Behavior?
CoordinatorLayout是android support design推出的新布局,主要用于作为视图根布局以及协调子控件的行为,而Behavior就是用于直接子控件来协调自身CoordinatorLayout以及和其他子控件的关系,使用Behavior的控件必须是直接从属于CoordinatorLayout。
在传统的事件分发流程中,在子控件处理事件过程中,父控件是可以进行拦截的,但一旦父控件进行拦截,那么这次事件只能由父控件处理,而不能再由子控件处理了。
在android5.0之后新的嵌套滑动机制中,引入了:NestScrollChild和NestedScrollingParent两个接口,用于协调子父控件滑动状态,而CoordinatorLayout实现了NestedScrollingParent接口,在实现了NestScrollChild这个接口的子控件在滑动时会调用NestedScrollingParent接口的相关方法,将事件发给父控件,由父控件决定是否消费当前事件,在CoordinatorLayout实现的NestedScrollingParent相关方法中会调用Behavior内部的方法。
我们实现Behavior的方法,就可以嵌入整个CoordinatorLayout所构造的嵌套滑动机制中,可以获取到两个方面的内容:
1、某个view监听另一个view的状态变化,例如大小、位置、显示状态等需要重写layoutDependsOn和onDependentViewChanged方法
2、某个view监听CoordinatorLayout内NestedScrollingChild的接口实现类的滑动状态需要重写onStartNestedScroll和onNestedPreScroll方法。注意:是监听实现了NestedScrollingChild的接口实现类的滑动状态,这就可以解释为什么不能用ScrollView而用NestScrollView来滑动了。本文的实现效果就是通过重写onStartNestedScroll和onNestedPreScroll方法。
二、如何使用Behavior实现悬浮控件动画?
前面已经说了,如果要监听另一个view的状态变化,需要重写layoutDependsOn和onDependentViewChanged方法;如果要监听实现了NestedScrollingChild的接口实现类的滑动状态(如NestedScrollView、RecyclerView等),需要重写onStartNestedScroll和onNestedPreScroll方法。因此,要实现本文效果,采用后者实现。
效果如下:
布局xml:
<?xml version="1.0" encoding="utf-8"?><android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/behavior_demo_coordinatorLayout" android:layout_width="match_parent" android:layout_height="match_parent"> <android.support.v7.widget.RecyclerView android:id="@+id/behavior_demo_recycler" android:layout_width="match_parent" android:layout_height="match_parent"/> <android.support.design.widget.FloatingActionButton android:id="@+id/fab" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="bottom|right" android:layout_marginBottom="72dp" android:layout_marginRight="16dp" android:src="@android:drawable/ic_dialog_email" app:layout_behavior="com.example.ltcoordinatorlayout.MyFabBehavior"/> <ImageView android:layout_gravity="bottom|left" android:layout_marginBottom="72dp" android:layout_marginLeft="16dp" android:src="@mipmap/ic_launcher" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_behavior="com.example.ltcoordinatorlayout.MyFabBehavior"/></android.support.design.widget.CoordinatorLayout>
给需要动画的控件添加behavior
app:layout_behavior=”com.example.ltcoordinatorlayout.MyFabBehavior”
MyFabBehavior.java:
public class MyFabBehavior extends CoordinatorLayout.Behavior<View>{ private float viewY;//控件距离coordinatorLayout底部距离 private boolean isHideAnimate;//隐藏动画是否在进行 private boolean isShowAnimate;//显示动画是否在进行 private boolean isChildTop = true;//判断控件是否回到原始位置 private ViewPropertyAnimator animator; private static final Interpolator INTERPOLATOR = new FastOutSlowInInterpolator(); public MyFabBehavior(Context context, AttributeSet attrs) { super(context, attrs); } /** * 滑动开始前指定Behavior关注的滑动方向 */ @Override public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, View child, View directTargetChild, View target, int nestedScrollAxes) { if (child.getVisibility() == View.VISIBLE && viewY == 0) { //获取控件距离父布局(coordinatorLayout)底部距离 viewY = coordinatorLayout.getHeight() - child.getY(); } return (nestedScrollAxes & ViewCompat.SCROLL_AXIS_VERTICAL) != 0;//判断是否竖直滚动 } /** * 用来监听滑动状态,对象消费滚动距离前回调 */ @Override public void onNestedPreScroll(CoordinatorLayout coordinatorLayout, View child, View target, int dx, int dy, int[] consumed) { Log.e("LT", "===============================>>>>>>>>dy: " + dy); //速度判断 if (Math.abs(dy) > 40) { //dy大于0是向上滚动 dy小于0是向下滚动 if (dy >= 0 && !isHideAnimate && child.getVisibility() == View.VISIBLE)//如果向上滚动,隐藏动画已结束并且控件可见,则启动隐藏动画 { hide(child); } else if (dy < 0 && !isShowAnimate && !isChildTop)//如果向下滚动,显示动画已结束并且控件未回到原始位置,则启动显示动画 { show(child); } else if (dy >= 0 && isShowAnimate)//如果向上滚动,并且显示动画未结束,则先取消显示动画再启动隐藏动画 { animator.cancel(); } else if (dy < 0 && isHideAnimate)//如果向下滚动,并且显示隐藏未结束,则先取消隐藏动画再启动显示动画 { animator.cancel(); } } } /** * 隐藏时的动画 */ private void hide(final View view) { Log.e("LT", "===============================>>>>>>>>溜了溜了 "); animator = view.animate().translationY(viewY).setInterpolator(INTERPOLATOR).setDuration(1000); animator.setListener(new Animator.AnimatorListener() { @Override public void onAnimationStart(Animator animator) { isHideAnimate = true; } //每次cancel也会走onAnimationEnd方法 @Override public void onAnimationEnd(Animator animator) { //如果隐藏动画正常结束,而非取消后结束,则将布局隐藏 if (isHideAnimate) { view.setVisibility(View.GONE); isHideAnimate = false; } isChildTop = false; } @Override public void onAnimationCancel(Animator animator) { isHideAnimate = false; } @Override public void onAnimationRepeat(Animator animator) { } }); animator.start(); } /** * 显示时的动画 */ private void show(final View view) { Log.e("LT", "===============================>>>>>>>>回来啦回来啦 "); animator = view.animate().translationY(0).setInterpolator(INTERPOLATOR).setDuration(1000); animator.setListener(new Animator.AnimatorListener() { @Override public void onAnimationStart(Animator animator) { view.setVisibility(View.VISIBLE); isShowAnimate = true; } //每次cancel也会走onAnimationEnd方法 @Override public void onAnimationEnd(Animator animator) { //如果显示动画正常结束,而非取消后结束,则isChildTop = true,表示控件回到原来位置 if (isShowAnimate) { isShowAnimate = false; isChildTop = true; } } @Override public void onAnimationCancel(Animator animator) { isShowAnimate = false; } @Override public void onAnimationRepeat(Animator animator) { } }); animator.start(); }}
需要注意的是滚动控件必须实现NestedScrollingChild接口,而没有实现该接口且不调用 dispatchNestedScroll相关接口的滚动控件如ScrollView、WebView、ListView是没有作用的。
参考文章:深入理解CoordinatorLayout.Behavior
- 自定义CoordinatorLayout.Behavior 实现悬浮控件动画
- 自定义实现CoordinatorLayout.Behavior
- CoordinatorLayout.Behavior自定义效果的实现
- CoordinatorLayout: 自定义Behavior
- CoordinatorLayout自定义behavior(仿20CM动画效果)
- CoordinatorLayout使用自定义Behavior实现UC浏览器顶栏效果
- CoordinatorLayout高级用法-自定义Behavior
- CoordinatorLayout高级用法-自定义Behavior
- Iwfu-CoordinatorLayout(2)自定义Behavior
- CoordinatorLayout高级用法-自定义Behavior
- CoordinatorLayout自定义Behavior的运用
- CoordinatorLayout(从自定义Behavior开始)
- CoordinatorLayout高级用法-自定义Behavior
- CoordinatorLayout高级用法-自定义Behavior
- CoordinatorLayout自定义Behavior&源码分析
- CoordinatorLayout高级用法-自定义Behavior
- Android CoordinatorLayout 与自定义Behavior
- Andorid CoordinatorLayout中自定义Behavior以应用在任何类型控件上
- spring学习----线程池
- 使用python进行whois查询并存入数据库
- Jenkins 日程表配置
- 高阶图匹配
- C语言Define
- 自定义CoordinatorLayout.Behavior 实现悬浮控件动画
- 支持Angular4好用的文件上传组件ng2-file-upload
- EF core 2.0 调用MySql数据库存储过程
- Eclipse下 Hadoop Maven 项目log4j配置
- 安卓检测USB设备插入之后回调用户代码的小框架编写
- php
- Linux(CentOS)下安装注册中心(Zookeeper-3.4.6)
- 报错nested exception is org.springframework.core.NestedIOException: ASM ClassReader failed to...
- mysql的存储过程