Android Behavior
原文出处: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都会在他下面。
滑动
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的上滑隐藏都可以这样实现。
事件处理
这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相关推荐
- android behavior 自定义,自定义Behavior
1.这是效果 二.使用注意 1.某个view需要监听另一个View的状态(位置.大小.显示状态等) (需要重写layoutDependsOn( 用来决定需要监听那些控件或者容器的状态),onDepen ...
- Android Behavior之相关解析
如果不了解Android嵌套滚动,最好看一下我之前的文章 Android 嵌套滑动--NestedScrolling完全解析,当然不了解对本篇文章的阅读也不会有太大的阻塞. 第一个简单的自定义Beha ...
- android浮动标题栏,GitHub - DARTTTTT/LBehavior: 跟随手势滑动,显示隐藏标题栏、底部导航栏及悬浮按钮的Android Behavior Library...
LBehavior 简单实现标题栏.导航栏滑动动画 效果图 博客介绍 Download allprojects { repositories { ... maven { url 'https://ji ...
- Android源码-高质量开发库
借鉴:秀源码http://www.xiufm.com/forum.php?mod=viewthread&tid=14873&highlight=Android%E6%BA%90%E7% ...
- 25000字总结Android优秀的第三方框架、各种学习资料汇集 一 系统组件、Design组件、自定义组件等等
说明 以下内容博主很多也没有用过 分享出来大家一起学习 用到的时候 可以来查看 有问题可以沟通 希望大家不要污染了学习环境 如果觉得有帮助 点个赞 支持一下 系统控件 TextView Github ...
- 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 ...
- 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 ...
- android底部滑出view,Android CoordinatorLayout与NestedScrollView基于Behavior几行代码实现底部View滑入滑出...
Android CoordinatorLayout与NestedScrollView基于Behavior几行代码实现底部View滑入滑出 在CoordinatorLayout的Behavior出现之前 ...
- Android 中 Behavior, NestedScrollingParent, NestedScrollingChild 关系
NestedScroll 相关接口:NestedScrollingParent, NestScrollingChild 顶层布局需要用CoordinatorLayout, Behavior 是Coor ...
- Android开发笔记(一百三十七)自定义行为Behavior
协调布局CoordinatorLayout能够让内部的子控件互相配合着移动,这跟以往孤立的控件运动截然不同,协调运动的结果,意味着App画面更加流畅.自然,也更符合日常生活中的动作场景.如果你对Coo ...
最新文章
- python的下载和安装步骤-PyCharm下载和安装详细步骤
- Unable to find the ncurses libraries的解决办法
- 使用BeetleX在Linux下部署.NET多站点服务
- 5G网络什么时候普及,5G手机可以用4G的手机卡吗,5G和4G什么区别
- matlab仿真二元等幅边射阵,MATLAB仿真天线阵代码.doc
- Android Multimedia框架总结(十七)音频开发基础知识
- [一个简单的.NET逆向工程]给没有源代码的.NET程序打补丁
- java 多线程单例模式
- 计算机考研408考试科目及备考指南
- sql盲注特点_sql盲注
- php ppt如何转换成pdf,PHP将Word,Wps,Excel,PPT转成PDF
- Java 应用压测性能问题定位经验分享
- Windowsnbsp;XP/Vista/Windows7常见蓝…
- Android App屏幕旋转要点
- ffmpeg播放器声音效果1-淡入淡出
- angularjs表单验证_AngularJS表单验证
- 异构计算的两大派别 为什么需要异构计算?
- 【csdn涨粉秘籍】亲身体验从一年才涨80粉到20天涨粉800多,规则内设置,一个步骤助你快速涨粉
- “解决Python软件包安装问题 - 修改pip源地址“
- gradle教程(一)
热门文章
- (附源码)springboot菠萝大学课室预约系统分析与设 毕业设计 641656
- php web helloworld,webim_server.php
- NES模拟器开发笔记(001)缘起、资料及开发准备
- linux修改ip配置文件路径,Linux系统更改IP地址及连接XShell5
- 一文掌握项目经理和PMO线上会议汇报流程规范和注意事项
- Modern Standby 调试的准备
- Visual Studio 各版本下载
- winrar.exe 命令行参数
- dvanced Installer Architect
- 浏览器份额及其历史以及内核变迁总结