Behavior简介

CoordinatorLayout是个很牛的布局容器,使用它可以很方面的实现很多效果,比如支付宝首页的折叠效果,知乎首页等等,Behavior是它的一个内部抽象类,声明Behavior属性的View可以和他它依赖的兄弟元素交互,当然,这些元素都必须是CoordinatorLayout的子元素。

what?

该类是CoordinatorLayout子View之间交互的插件,有了它CoordinatorLayout的子View就可以产生联动效果。比如一个子View跟随另一个子View的移动而移动,或者是缩放,透明度变换等。

why?

一般情况下,如果要实现子View,随着上拉消失,下拉出现,我们需要在Activity中监听滚动事件,在里边处理View的显示逻辑,这样就会导致Activity中代码量变大,滚动事件中的逻辑也会变的复杂,有了CoordinatorLayout.behavior,不需要监听滚动事件,只需要自定义一个Behavior的实现类,实现几个方法就可以达到相应的效果,不需要修改activity中的代码。

how?

Behavior是CoordinatorLayout的一个内部抽象类,里边的方法有很多,如果不是要实现特别复杂的功能,只需要实现1,2个方法就可以了。常见的有两种方式:

1. 如果要依赖于CoordinatorLayout中的某个子View实现某种变化,需要实现Behavior的layoutDependsOn()和onDependentViewChanged()方法,前者会在CoordinatorLayout中通过循环的方式,找到被依赖的View,返回true,表示找到了被依赖的View,后者在每次dependency的大小,位置变化的时候都会调用,可以在这里出child的变化逻辑。

 /*** 在CoordinatorLayout中通过循环遍历的方式找到被依赖的View** @param parent     CoordinatorLayout* @param child      设置了该Behavior的View* @param dependency 被依赖的View* @return true 标识找到了被依赖的View*/@Overridepublic boolean layoutDependsOn(CoordinatorLayout parent, View child, View dependency) {//...}/*** 每次dependency的大小或位置有所变化的时候都会调用该方法** @param parent* @param child* @param dependency* @return*/@Overridepublic boolean onDependentViewChanged(CoordinatorLayout parent, View child, View dependency) {//...}

2. 如果不需要依赖于任何子View,纯粹只是想要根据滑动距离,做一些操作,可以实现onStartNestScroll()和onNestPreScroll()。

onNestedPreScroll(CoordinatorLayout coordinatorLayout, V child, View target, int dx, int dy, int[] consumed, int type)

Called when a nested scroll in progress is about to update, before the target has consumed any of the scrolled distance.

该方法是在target消费调用任何的滚动距离之前调用的。这个时候还没有更新

onNestedScroll(CoordinatorLayout coordinatorLayout, V child, View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed, int type)

Called when a nested scroll in progress has updated and the target has scrolled or attempted to scroll.

自定义Behavior的使用方式:

1. 在res/values文件夹下定义字符串引用,然后再布局文件中引用

2.直接在布局文件中使用全路径包名

实例1:

实现上拉消失,下拉显示的效果。这个效果不需要依赖任何的View,所以重写onStartNestScroll()和onNestPreScroll()即可,

在onStartNestScroll()中判断View要位移的总距离,然后再onNestPreScroll()方法中进行边界判断并位移即可。

具体代码:

public class DownToHiddenBehavior extends CoordinatorLayout.Behavior<View> {private int mOffsetY = 0;public DownToHiddenBehavior() {super();}public DownToHiddenBehavior(Context context, AttributeSet attrs) {super(context, attrs);}@Overridepublic void onNestedPreScroll(@NonNull CoordinatorLayout coordinatorLayout, @NonNull View child, @NonNull View target, int dx, int dy, @NonNull int[] consumed, int type) {super.onNestedPreScroll(coordinatorLayout, child, target, dx, dy, consumed, type);CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) child.getLayoutParams();int total = params.bottomMargin + child.getHeight();
//        Log.i("onNestedPreScroll", "------>trans:" + child.getTranslationY() + " ,total:" + total);mOffsetY += dy;//dy<0:表示下拉,offsetY<0:表示下拉的距离已经超出View的原始位置//一定要同时成立才行,否则先向上滑动,然后再快速向下滑动,View的位置会出现偏移。//dy<0的时候,moffsetY不一定小于0,相反也一样if (dy < 0 && mOffsetY < 0) {mOffsetY = 0;}//边界判断if (dy > 0 && mOffsetY > total) {mOffsetY = total;}child.setTranslationY(mOffsetY);}
}

注意:这里的构造方法一定要重载!!!不然会报错的。因为Behavior是在CoordinatorLayout中使用反射进行调用的。需要用到两参的构造方法。

接下来在布局文件中引用即可

<android.support.design.widget.FloatingActionButtonapp:layout_behavior="@string/behavior_down_to_hidden"android:layout_width="wrap_content"android:layout_height="wrap_content"android:onClick="floatButton"android:layout_gravity="bottom|right"android:layout_marginBottom="50dp"android:layout_marginRight="50dp"/>

实例2:

实现View跟随ToolBar的消失和显示进行缩放。向上滑动的时候Toolbar逐渐移除屏幕,view逐渐缩小直到消失。下拉的时候,Toolbar逐渐出现,View逐渐放大到原始大小。

很明显,这里需要依赖于Toolbar,因此使用第一种方法,重写layoutDependsOn()和onDependentViewChanged()方法

具体代码:

public class ScaleToHiddenBehavior extends CoordinatorLayout.Behavior<View> {private float mToolbarHegiht;public ScaleToHiddenBehavior(Context context, AttributeSet attrs) {super(context, attrs);}/*** 在CoordinatorLayout中通过循环遍历的方式找到被依赖的View** @param parent     CoordinatorLayout* @param child      设置了该Behavior的View* @param dependency 被依赖的View* @return true 标识找到了被依赖的View*/@Overridepublic boolean layoutDependsOn(CoordinatorLayout parent, View child, View dependency) {if (mToolbarHegiht == 0) {mToolbarHegiht = dependency.getHeight();}return dependency instanceof AppBarLayout;}/*** 每次dependency的大小或位置有所变化的时候都会调用该方法** @param parent* @param child* @param dependency* @return*/@Overridepublic boolean onDependentViewChanged(CoordinatorLayout parent, View child, View dependency) {Log.i("onDependentViewChanged", "------->height:" + mToolbarHegiht + ", top:" + dependency.getTop());float fraction = Math.abs(dependency.getTop()) / mToolbarHegiht;child.setScaleX(1 - fraction);child.setScaleY(1 - fraction);return super.onDependentViewChanged(parent, child, dependency);}
}

同样在布局文件中引用该类

<android.support.design.widget.FloatingActionButtonapp:layout_behavior="@string/behavior_scale_to_hidden"android:layout_width="wrap_content"android:layout_height="wrap_content"android:onClick="floatButton"android:layout_gravity="top|right"android:layout_marginTop="100dp"android:layout_marginRight="50dp"/>

实例3:

使用CoordinatorLayout实现支付宝首页折叠效果 :

思路:

这里不需要自定义Behavior,但是需要监听AppbarLayout的折叠距离,控制Toolbar的显示效果。

整个Activity的布局文件activity_page_home_zfb.xml

顶部的搜索框Toolbar和需要折叠起来的布局全都放在CoolapsingToolbarLayout中,因为CoolapsingToolbarLayout继承自FrameLayout,想要让Toolbar显示在顶部,并且看起来不覆盖折叠布局,这里设置了给需要折叠的布局设置了marginTop,值刚好就是Toolbar的高度。

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"xmlns:app="http://schemas.android.com/apk/res-auto"><android.support.design.widget.AppBarLayoutandroid:id="@+id/appbarLayout"android:layout_width="match_parent"android:layout_height="wrap_content"><android.support.design.widget.CollapsingToolbarLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"app:layout_scrollFlags="scroll|exitUntilCollapsed|snap"><includeandroid:id="@+id/collapsLayout"layout="@layout/include_layout_collaps"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginTop="?attr/actionBarSize"android:orientation="horizontal"app:layout_collapseMode="parallax"app:layout_collapseParallaxMultiplier="0.7"/><android.support.v7.widget.Toolbarandroid:id="@+id/toolbarContainer"android:layout_width="match_parent"android:layout_height="?attr/actionBarSize"app:contentInsetLeft="0dp"app:contentInsetStart="0dp"app:layout_collapseMode="pin"><includelayout="@layout/include_layout_toolbar_1"android:id="@+id/toolbar1"android:layout_width="match_parent"android:layout_height="match_parent"android:gravity="center_vertical"/><includeandroid:visibility="gone"layout="@layout/include_layout_toolbar_2"android:id="@+id/toolbar2"android:layout_width="match_parent"android:layout_height="match_parent"/></android.support.v7.widget.Toolbar></android.support.design.widget.CollapsingToolbarLayout></android.support.design.widget.AppBarLayout><android.support.v4.widget.NestedScrollViewandroid:id="@+id/nestScrollView"android:layout_width="match_parent"android:layout_height="wrap_content"app:layout_behavior="@string/appbar_scrolling_view_behavior"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="vertical"><RelativeLayoutandroid:layout_width="match_parent"android:layout_height="200dp"android:background="#bac"/><RelativeLayoutandroid:layout_width="match_parent"android:layout_height="100dp"android:background="#abc"/><RelativeLayoutandroid:layout_width="match_parent"android:layout_height="100dp"android:background="#cba"/><RelativeLayoutandroid:layout_width="match_parent"android:layout_height="150dp"android:background="#bba"/><RelativeLayoutandroid:layout_width="match_parent"android:layout_height="150dp"android:background="#aab"/><RelativeLayoutandroid:layout_width="match_parent"android:layout_height="200dp"android:background="#ccb"/></LinearLayout></android.support.v4.widget.NestedScrollView>
</android.support.design.widget.CoordinatorLayout>

支付宝的效果是,刚进入页面折叠布局完全展开,并且Toolbar显示的是搜索框。上拉时搜索框逐渐隐藏,然后Toolbar开始逐渐显示4个按钮的布局,全程展开的折叠布局逐渐折叠起来,并且透明度逐渐降低。

这里参考了网上的思路,当折叠到一半高度的时候开始切换Toolbar的布局。

具体代码如下:

public class ZFBHomePageActivity extends BaseActivity {private AppBarLayout mAppbarLayout;private LinearLayout mToolbar1,mToolbar2;private LinearLayout mCollapsLayout;@Overrideprotected void initView() {mAppbarLayout=findViewById(R.id.appbarLayout);mToolbar1=findViewById(R.id.toolbar1);mToolbar2=findViewById(R.id.toolbar2);mCollapsLayout=findViewById(R.id.collapsLayout);mAppbarLayout.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() {@Overridepublic void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {float value=Math.abs(verticalOffset);int total=mAppbarLayout.getTotalScrollRange();int midHeight=total/2;if (value<=midHeight){//toolbar1的alpha值从1-0float fraction = value / midHeight * 1.0f;mToolbar1.setVisibility(View.VISIBLE);mToolbar2.setVisibility(View.GONE);mToolbar1.setAlpha(1-fraction);}else {//toolbar2的alpha值从0-1float fraction=(value-midHeight)/(total-midHeight)*1.0f;mToolbar1.setVisibility(View.GONE);mToolbar2.setVisibility(View.VISIBLE);mToolbar2.setAlpha(fraction);Log.i("onOffsetChanged","---->value:"+value+", fraction:"+fraction+(mToolbar2.getVisibility()==View.VISIBLE));}//折叠的布局alpha值从1-0mCollapsLayout.setAlpha(1-(value/total*1.0f));}});}

非常简单,只需要在给AppbarLayout注册addOffsetChangedListener()监听,根据折叠的偏移量,在偏移量小于总偏移量的1/2时,显示搜索布局,隐藏四个按钮,并降低搜索布局的透明度;当偏移量大于一半时,隐藏搜索布局,逐渐显示4个按钮。折叠布局的透明度,要开始折叠,一直到完全折叠起来逐渐降低。

自定义Behavior相关推荐

  1. 红橙Darren视频笔记 CoordinatorLayout:实现自定义behavior

    效果: 目标:利用CoordinatorLayout实现自定义behavior ,顶部的TitleBar和底部的ActionBar实现能够随着手势自由显示和隐藏 activity中使用了recycle ...

  2. WCF中使用自定义behavior提示错误的解决方法

    WCF中使用自定义behavior提示错误的解决方法 参考文章: (1)WCF中使用自定义behavior提示错误的解决方法 (2)https://www.cnblogs.com/shenba/arc ...

  3. layui totalRow 多层嵌套json_自定义 Behavior,实现嵌套滑动、平滑切换周月视图的日历...

    使用 CoordinateLayout 可以协调它的子布局,实现滑动效果的联动,它的滑动效果由 Behavior 实现.以前用过小米日历,对它滑动平滑切换日月视图的效果印象深刻.本文尝试用自定义 Be ...

  4. 自定义Behavior的艺术探索-仿UC浏览器主页

    出处:http://www.jianshu.com/p/f7989a2a3ec2 前言&效果预览 最近几个周末基本在研究CoordinatorLayout控件和自定义Behavior当中,这期 ...

  5. 自定义 behavior - 完美仿 QQ 浏览器首页,美团商家详情页

    前言 记得两年前的时候,曾写过自定义 behavior 的文章 自定义 Behavior -仿新浪微博发现页的实现,到现在差不多有一万多的阅读量吧. image 今天,对该 behavior 进行升级 ...

  6. 自定义 Behavior

    自定义Behavior 允许在WCF 构建运行时环境和消息处理管道的关键点上插入代码. 实现自定义行为的步骤: 1. 创建一个实现了 Inspector.Selector.Formatter.或Inv ...

  7. Android仿小米时钟嵌套滑动(NestedScroll, 自定义behavior)

    最近无聊刷手机的时候, 发现小米时钟的嵌套滑动很有意思, 就试着做了下 先上对比图: 分析下小米时钟的滑动 闹钟列表 向上滑动时, 时钟面 透明度上升, 快到最大滑动时逐渐显示数字时钟. 在闹钟列表向 ...

  8. Android自定义Behavior出现This graph contains cyclic dependencies

    最近刚开始学习使用CoordinatorLayout,并且自定义Behavior,因为项目要求,要在webview滑动的时候,headview要跟着滑动改变自身大小,并且要使webview在headv ...

  9. Android CoordinatorLayout 自定义Behavior 高仿美团商家详情界面 实现页面内容复杂联动效果

    内容如题 效果如下 顺带涉及到: Scroller+Handler 实现View自动滑动 View属性动画 触摸事件分发机制 ConstraintLayout约束布局 emmmm 实现参考: Cons ...

  10. CoordinatorLayout高级用法-自定义Behavior

    在新的support design中,CoordinatorLayout可以说是最重要的一个控件了,CoordinatorLayout给我们带来了一种新的事件的处理方式--behavior,你是不是还 ...

最新文章

  1. SpringMVC 学习笔记(二) @RequestMapping、@PathVariable等注解
  2. signature=8cc1e8491a741a9dc954b549013b75e5,基于小波的SAR影像纹理分析
  3. 走近分形与混沌(part4)--牛顿与混沌
  4. 如何使用ES6在JavaScript中有条件地构建对象
  5. Cacti脚本及模板---PING
  6. 20220729梦笔记
  7. GBASE监控工具简介
  8. The POM for is missing, no dependency information available
  9. 铁通dns服务器地址是多少,电信/网通/铁通dns服务器地址大全
  10. win10 电脑蓝牙无法使用无法连接问题的一种神奇解决办法
  11. 解决output directory already exists
  12. linux中tmp文件在哪,tmp是什么文件(了解linux系统目录,sys,tmp,usr,var)
  13. Meta-Weight-Net[NIPS‘2019]:关于元学习/域自适应(meta learning/domain adaptation)优化噪声标签与类别不平衡的问题
  14. 统计打印字符串arg中每个字符出现的次数
  15. Android中notifyDataSetInvalidated()和notifyDataSetChanged()
  16. 裁判文书网数据采集爬虫记录2023-03
  17. October 2007
  18. 《Saladict》谷歌!有道!我全都要! 聚合词典, 并行翻译
  19. python爬虫基础学习
  20. php手机号登陆,ecshop登录支持手机号码登录、邮箱登录

热门文章

  1. java txt转pdf乱码,openoffice将txt文本转pdf中文乱码
  2. Redis 会被Dragonfly替代?
  3. 矩阵的生成及对角线运算
  4. UE4 创建开始游戏界面UI
  5. 假设检验实例(python)
  6. Windows补丁修复- Microsoft Windows HTTP.sys远程代码执行漏洞 (MS15-034)(CVE-2015-1635)
  7. 平面设计完全手册_什么是平面设计,做平面设计都要了解哪些基础知识点?
  8. 实时调试WebDriver代码
  9. 架设自己的邮件服务器
  10. Laravel 之搜索引擎elasticsearch扩展Scout