原文出处:http://www.jianshu.com/p/a506ee4afecb

Behavior是Android新出的Design库里新增的布局概念。Behavior只有是CoordinatorLayout的直接子View才有意义。可以为任何View添加一个Behavior。
Behavior是一系列回调。让你有机会以非侵入的为View添加动态的依赖布局,和处理父布局(CoordinatorLayout)滑动手势的机会。不过官方只有少数几个Behavior的例子。对于理解Behavior实在不易。开发过程中也是很多坑,下面总结一下CoordinatorLayout与Behavior。

依赖

首先自定义一个Behavior。

    public class MyBehavior extends CoordinatorLayout.Behavior{public MyBehavior(Context context, AttributeSet attrs) {super(context, attrs);}}

一定要重写这个构造函数。因为CoordinatorLayout源码中parseBehavior()函数中直接反射调用这个构造函数。

static final Class<?>[] CONSTRUCTOR_PARAMS = new Class<?>[] {Context.class,AttributeSet.class
};

下面反射生成Behavior实例在实例化CoordinatorLayout.LayoutParams时:

final Class<Behavior> clazz = (Class<Behavior>) Class.forName(fullName, true,context.getClassLoader());
c = clazz.getConstructor(CONSTRUCTOR_PARAMS);
c.setAccessible(true);
constructors.put(fullName, c);
return c.newInstance(context, attrs)

在任意View中添加:

app:layout_behavior=“你的Behavior包含包名的类名”

然后CoordinatorLayout就会反射生成你的Behavior。

另外一种方法如果你的自定义View默认使用一个Behavior。
在你的自定义View类上添加@DefaultBehavior(你的Behavior.class)这句注解。
你的View就默认使用这个Behavior。就像AppBarLayout一样。

@DefaultBehavior(AppBarLayout.Behavior.class)
public class AppBarLayout extends LinearLayout {}

生成Behavior后第一件事就是确定依赖关系。重写Behavior的这个方法来确定你依赖哪些View。

@Override
public boolean layoutDependsOn(CoordinatorLayout parent, View child, View dependency) {return dependency.getId() == R.id.first;
}

child 是指应用behavior的View ,dependency 担任触发behavior的角色,并与child进行互动。
确定你是否依赖于这个View。CoordinatorLayout会将自己所有View遍历判断。
如果确定依赖。这个方法很重要。当所依赖的View变动时会回调这个方法。

@Override
public boolean onDependentViewChanged(CoordinatorLayout parent, View child, View dependency) {return true;
}

下面这个例子:

    <declare-styleable name="Follow"><attr name="target" format="reference"/></declare-styleable>

先自定义target这个属性。

  public class FollowBehavior extends CoordinatorLayout.Behavior {private int targetId;public FollowBehavior(Context context, AttributeSet attrs) {super(context, attrs);TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.Follow);for (int i = 0; i < a.getIndexCount(); i++) {int attr = a.getIndex(i);if(a.getIndex(i) == R.styleable.Follow_target){targetId = a.getResourceId(attr, -1);}}a.recycle();}@Overridepublic boolean onDependentViewChanged(CoordinatorLayout parent, View child, View dependency) {child.setY(dependency.getY()+dependency.getHeight());return true;}@Overridepublic boolean layoutDependsOn(CoordinatorLayout parent, View child, View dependency) {return dependency.getId() == targetId;}
}

xml中:

<android.support.design.widget.CoordinatorLayout    xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:orientation="vertical"android:layout_width="match_parent"android:layout_height="match_parent"android:fitsSystemWindows="true"tools:context=".MainActivity"><Viewandroid:id="@+id/first"android:layout_width="match_parent"android:layout_height="128dp"android:background="@android:color/holo_blue_light"/><Viewandroid:id="@+id/second"android:layout_width="match_parent"android:layout_height="128dp"app:layout_behavior=".FollowBehavior"app:target="@id/first"android:background="@android:color/holo_green_light"/></android.support.design.widget.CoordinatorLayout>

效果是不管first怎么移动。second都会在他下面。

01.gif

滑动

Behavior最大的用处在于对滑动事件的处理。就像CollapsingToolbarLayout的那个酷炫效果一样。

主要是这3个方法,所依赖对象的滑动事件都将通知进来:

@Override
public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, View child, View directTargetChild, View target, int nestedScrollAxes) {return true;//这里返回true,才会接受到后续滑动事件。
}@Override
public void onNestedScroll(CoordinatorLayout coordinatorLayout, View child, View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed) {
//进行滑动事件处理
}@Override
public boolean onNestedFling(CoordinatorLayout coordinatorLayout, View child, View target, float velocityX, float velocityY, boolean consumed) {
//当进行快速滑动return super.onNestedFling(coordinatorLayout, child, target, velocityX, velocityY, consumed);
}

注意被依赖的View只有实现了NestedScrollingChild接口的才可以将事件传递给CoordinatorLayout。
但注意这个滑动事件是对于CoordinatorLayout的。所以只要CoordinatorLayout有NestedScrollingChild就会滑动,他滑动就会触发这几个回调。无论你是否依赖了那个View。
下面就是一个简单的View跟随ScrollView滑入滑出屏幕的例子。可以是Toolbar或其他任何View。

public class ScrollToTopBehavior extends CoordinatorLayout.Behavior<View>{int offsetTotal = 0;boolean scrolling = false;public ScrollToTopBehavior(Context context, AttributeSet attrs) {super(context, attrs);}@Overridepublic boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, View child, View directTargetChild, View target, int nestedScrollAxes) {return true;}@Overridepublic void onNestedScroll(CoordinatorLayout coordinatorLayout, View child, View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed) {offset(child, dyConsumed);}public void offset(View child,int dy){int old = offsetTotal;int top = offsetTotal - dy;top = Math.max(top, -child.getHeight());top = Math.min(top, 0);offsetTotal = top;if (old == offsetTotal){scrolling = false;return;}int delta = offsetTotal-old;child.offsetTopAndBottom(delta);scrolling = true;}}

xml中:

<android.support.design.widget.CoordinatorLayoutxmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:orientation="vertical"android:layout_width="match_parent"android:layout_height="match_parent"android:fitsSystemWindows="false"tools:context=".MainActivity"><android.support.v4.widget.NestedScrollViewandroid:id="@+id/second"android:layout_width="match_parent"android:layout_height="match_parent"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"><TextViewandroid:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginTop="128dp"style="@style/TextAppearance.AppCompat.Display3"android:text="A\nB\nC\nD\nE\nF\nG\nH\nI\nJ\nK\nL\nM\nN\nO\nP\nQ\nR\nS\nT\nU\nV\nW\nX\nY\nZ"android:background="@android:color/holo_red_light"/></LinearLayout></android.support.v4.widget.NestedScrollView><Viewandroid:id="@+id/first"android:layout_width="match_parent"android:layout_height="128dp"app:layout_behavior=".ScrollToTopBehavior"android:background="@android:color/holo_blue_light"/></android.support.design.widget.CoordinatorLayout>

当NestedScrollView滑动的时候,first也能跟着滑动。toolbar和fab的上滑隐藏都可以这样实现。

02.gif

事件处理

这2个回调与View中的事件分发是一样的。所有Behavior能在子View之前收到CoordinatorLayout的所有触摸事件。可以进行拦截,如果拦截事件将不会流经子View。因为这2个方法都是在CoordinatorLayout的 回调中

@Override
public boolean onInterceptTouchEvent(CoordinatorLayout parent, View child, MotionEvent ev) {return super.onInterceptTouchEvent(parent, child, ev);
}@Override
public boolean onTouchEvent(CoordinatorLayout parent, View child, MotionEvent ev) {return super.onTouchEvent(parent, child, ev);
}

AppBarLayout的收缩原理分析

示例中给可滑动View设的Behavior是
@string/appbar_scrolling_view_behavior(android.support.design.widget.AppBarLayout$ScrollingViewBehavior)。
ScrollingViewBehavior的源码不多,看得出唯一的作用是把自己放到AppBarLayout的下面...(不能理解为什么叫ScrollingViewBehavior
所有View都能使用这个Behavior。

AppBarLayout自带一个Behivior。直接在源码里注解声明的。这个Behivior也只能用于AppBarLayout。
作用是让他根据CoordinatorLayout上的滚动手势进行一些效果(比如收缩)。与ScrollingViewBehavior是无关的,加不加ScrollingViewBehavior不影响收缩。
只不过只有某些可滑动View才会把滑动事件响应给CoordinatorLayout才能继而响应给AppBarLayout。

Android Behavior相关推荐

  1. android behavior 自定义,自定义Behavior

    1.这是效果 二.使用注意 1.某个view需要监听另一个View的状态(位置.大小.显示状态等) (需要重写layoutDependsOn( 用来决定需要监听那些控件或者容器的状态),onDepen ...

  2. Android Behavior之相关解析

    如果不了解Android嵌套滚动,最好看一下我之前的文章 Android 嵌套滑动--NestedScrolling完全解析,当然不了解对本篇文章的阅读也不会有太大的阻塞. 第一个简单的自定义Beha ...

  3. android浮动标题栏,GitHub - DARTTTTT/LBehavior: 跟随手势滑动,显示隐藏标题栏、底部导航栏及悬浮按钮的Android Behavior Library...

    LBehavior 简单实现标题栏.导航栏滑动动画 效果图 博客介绍 Download allprojects { repositories { ... maven { url 'https://ji ...

  4. Android源码-高质量开发库

    借鉴:秀源码http://www.xiufm.com/forum.php?mod=viewthread&tid=14873&highlight=Android%E6%BA%90%E7% ...

  5. 25000字总结Android优秀的第三方框架、各种学习资料汇集 一 系统组件、Design组件、自定义组件等等

    说明 以下内容博主很多也没有用过 分享出来大家一起学习 用到的时候 可以来查看 有问题可以沟通 希望大家不要污染了学习环境 如果觉得有帮助 点个赞 支持一下 系统控件 TextView Github ...

  6. Android webview 69,android-9.0-pie-env(safe-area-inset-top)无法在Android Pie WebView 69上运行

    在 Chrome 69中引入了对env()常量的支持.虽然我观察到的行为与iOS不同.在iPhone 8屏幕上没有凹口env(安全区域插入顶部)等于20px,而在Moto G屏幕上,没有凹口,它等于0 ...

  7. Android webview 69,env(safe-area-inset-top) not working on Android Pie + WebView 69

    问题 I have a fullscreen cordova app, I used to use the css below for iPhone X's notch, padding-top: 2 ...

  8. android底部滑出view,Android CoordinatorLayout与NestedScrollView基于Behavior几行代码实现底部View滑入滑出...

    Android CoordinatorLayout与NestedScrollView基于Behavior几行代码实现底部View滑入滑出 在CoordinatorLayout的Behavior出现之前 ...

  9. Android 中 Behavior, NestedScrollingParent, NestedScrollingChild 关系

    NestedScroll 相关接口:NestedScrollingParent, NestScrollingChild 顶层布局需要用CoordinatorLayout, Behavior 是Coor ...

  10. Android开发笔记(一百三十七)自定义行为Behavior

    协调布局CoordinatorLayout能够让内部的子控件互相配合着移动,这跟以往孤立的控件运动截然不同,协调运动的结果,意味着App画面更加流畅.自然,也更符合日常生活中的动作场景.如果你对Coo ...

最新文章

  1. python的下载和安装步骤-PyCharm下载和安装详细步骤
  2. Unable to find the ncurses libraries的解决办法
  3. 使用BeetleX在Linux下部署.NET多站点服务
  4. 5G网络什么时候普及,5G手机可以用4G的手机卡吗,5G和4G什么区别
  5. matlab仿真二元等幅边射阵,MATLAB仿真天线阵代码.doc
  6. Android Multimedia框架总结(十七)音频开发基础知识
  7. [一个简单的.NET逆向工程]给没有源代码的.NET程序打补丁
  8. java 多线程单例模式
  9. 计算机考研408考试科目及备考指南
  10. sql盲注特点_sql盲注
  11. php ppt如何转换成pdf,PHP将Word,Wps,Excel,PPT转成PDF
  12. Java 应用压测性能问题定位经验分享
  13. Windowsnbsp;XP/Vista/Windows7常见蓝…
  14. Android App屏幕旋转要点
  15. ffmpeg播放器声音效果1-淡入淡出
  16. angularjs表单验证_AngularJS表单验证
  17. 异构计算的两大派别 为什么需要异构计算?
  18. 【csdn涨粉秘籍】亲身体验从一年才涨80粉到20天涨粉800多,规则内设置,一个步骤助你快速涨粉
  19. “解决Python软件包安装问题 - 修改pip源地址“
  20. gradle教程(一)

热门文章

  1. (附源码)springboot菠萝大学课室预约系统分析与设 毕业设计 641656
  2. php web helloworld,webim_server.php
  3. NES模拟器开发笔记(001)缘起、资料及开发准备
  4. linux修改ip配置文件路径,Linux系统更改IP地址及连接XShell5
  5. 一文掌握项目经理和PMO线上会议汇报流程规范和注意事项
  6. Modern Standby 调试的准备
  7. Visual Studio 各版本下载
  8. winrar.exe 命令行参数
  9. dvanced Installer Architect
  10. 浏览器份额及其历史以及内核变迁总结