CoordinatorLayout用法学习
来源:互联网 发布:帧中继网络 编辑:程序博客网 时间:2024/05/01 19:18
以前我们创建项目时候,一个页面的布局是线性或者相对等,当我在AS上新建一个module时,系统默认的最外层布局不再是我们熟悉的五大布局中的一种,而是一个全新的布局:CoordinatorLayout。它是Material风格的重要组件, 作为布局的顶层控件,协调(Coordinate)其他组件, 实现联动。
activity_main.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" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:fitsSystemWindows="true" tools:context="com.example.administrator.myapplication.MainActivity"> <android.support.design.widget.AppBarLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:theme="@style/AppTheme.AppBarOverlay"> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:background="?attr/colorPrimary" app:layout_scrollFlags="scroll|enterAlways" app:popupTheme="@style/AppTheme.PopupOverlay" /> </android.support.design.widget.AppBarLayout> <include layout="@layout/content_main" /> <android.support.design.widget.FloatingActionButton android:id="@+id/fab" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="bottom|end" android:layout_margin="@dimen/fab_margin" android:src="@android:drawable/ic_dialog_email" /></android.support.design.widget.CoordinatorLayout>
content_main.xml
<?xml version="1.0" encoding="utf-8"?><android.support.v4.widget.NestedScrollView 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:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" app:layout_behavior="@string/appbar_scrolling_view_behavior" tools:context="com.example.administrator.myapplication.MainActivity" tools:showIn="@layout/activity_main"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hello World!" /></android.support.v4.widget.NestedScrollView>
看看效果图如下:
??很明显,状态栏是有问题的,我们只需要将主布局的
android:fitsSystemWindows=”true”取调即可
以下是去掉之后的显示状态
以上的布局需要注意几个点:
app:layout_scrollFlags=”scroll|enterAlways”
app:layout_behavior=”@string/appbar_scrolling_view_behavior”
其中控制ToolBar是否可以滚出屏幕的属性是由app:layout_scrollFlags=”scroll|enterAlways”
enterAlwaysCollapsed: 顾名思义,这个flag定义的是何时进入(已经消失之后何时再次显示)。假设你定义了一个最小高度(minHeight)同时enterAlways也定义了,那么view将在到达这个最小高度的时候开始显示,并且从这个时候开始慢慢展开,当滚动到顶部的时候展开完。
exitUntilCollapsed: 同样顾名思义,这个flag时定义何时退出,当你定义了一个minHeight,这个view将在滚动到达这个最小高度的时候消失
我们来了解下,如何自定义Behavior
CoordinatorLayout的工作原理是搜索定义了CoordinatorLayout Behavior 的子view,不管是通过在xml中使用app:layout_behavior标签还是通过在代码中对view类使用@DefaultBehavior修饰符来添加注解。当滚动发生的时候,CoordinatorLayout会尝试触发那些声明了依赖的子view。要自己定义CoordinatorLayout Behavior,你需要实现layoutDependsOn() 和onDependentViewChanged()两个方法。
<string name="appbar_scrolling_view_behavior" translatable="false">android.support.design.widget.AppBarLayout$ScrollingViewBehavior</string>
其实它并不是一个字符串资源,而它代表的是一个类
public static class ScrollingViewBehavior extends ViewOffsetBehavior<View>class ViewOffsetBehavior<V extends View> extends Behavior<V>
1.某个view需要根据监听另一个的行为来控制自己的行为,这个时候我们需要重写2个方法
public boolean layoutDependsOn(CoordinatorLayout parent, V child, View dependency) { return false; }
public boolean onDependentViewChanged(CoordinatorLayout parent, V child, View dependency) { return false; }
结合我们一个列子来理理思路,首先看例子的效果图:
先看这个例子的主布局activity_main.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" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.example.administrator.myapplication.MainActivity"> <android.support.design.widget.AppBarLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:theme="@style/AppTheme.AppBarOverlay"> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:background="?attr/colorPrimary" app:layout_scrollFlags="scroll|enterAlways" app:popupTheme="@style/AppTheme.PopupOverlay" /> </android.support.design.widget.AppBarLayout> <include layout="@layout/content_main" /> <android.support.design.widget.FloatingActionButton android:id="@+id/fab" android:layout_width="50dp" android:layout_height="50dp" android:layout_gravity="bottom|center" app:layout_behavior="com.example.administrator.myapplication.FooterBehavior" android:src="@android:drawable/ic_dialog_email" /></android.support.design.widget.CoordinatorLayout>
上面的主布局中,我们为FloatingActionButton增加了一个自定义的属性行为
app:layout_behavior="com.example.administrator.myapplication.FooterBehavior"
意思就是:这个FloatingActionButton根据监听AppBarLayout滑动的行为来控制自己的行为
content_main.xml
<?xml version="1.0" encoding="utf-8"?><android.support.v4.widget.NestedScrollView 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:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" app:layout_behavior="@string/appbar_scrolling_view_behavior" tools:context="com.example.administrator.myapplication.MainActivity" tools:showIn="@layout/activity_main"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Hello World!" /></android.support.v4.widget.NestedScrollView>
FooterBehavior
package com.example.administrator.myapplication;import android.content.Context;import android.support.design.widget.AppBarLayout;import android.support.design.widget.CoordinatorLayout;import android.util.AttributeSet;import android.view.View;public class FooterBehavior extends CoordinatorLayout.Behavior<View>{ public FooterBehavior(Context context,AttributeSet attributeSet){ super(context,attributeSet); } @Override public boolean layoutDependsOn(CoordinatorLayout parent, View child, View dependency) { return dependency instanceof AppBarLayout; } @Override public boolean onDependentViewChanged(CoordinatorLayout parent, View child, View dependency) { float scaleY = Math.abs(dependency.getY()) / dependency.getHeight(); child.setTranslationY(child.getHeight() * scaleY); return true; } }
这两个方法的参数都是一样的,解释一下,第一个不用说,就是当前的CoordinatorLayout,第二个参数是我们设置这个Behavior的View,也就是FloatingActionButton, 第三个是我们关心的那个View。如何知道关心的哪个呢?layoutDependsOn的返回值决定了一切!
我们的例子layoutDependsOn方法中,return dependency instanceof AppBarLayout;是关心的AppBarLayout,也就是Toolbar(AppBarLayout)变化位置,引起FloatingActionButton的位置变化
onDependentViewChanged方法意思是什么呢?
先计算出Toolbar(AppBarLayout)暴露在屏幕的比例大小
然后计算出FloatingActionButton需要移动到的位置
以下是log日志
Log.i("TAG","scaleY-->>"+scaleY+",,child.getHeight() * scaleY-->>"+child.getHeight() * scaleY);
I/TAG: scaleY-->>0.05952381,,child.getHeight() * scaleY-->>8.928572I/TAG: scaleY-->>0.31547618,,child.getHeight() * scaleY-->>47.321426I/TAG: scaleY-->>0.8214286,,child.getHeight() * scaleY-->>123.21429 I/TAG: scaleY-->>1.0,,child.getHeight() * scaleY-->>150.0 I/TAG: scaleY-->>0.875,,child.getHeight() * scaleY-->>131.25 I/TAG: scaleY-->>0.10119048,,child.getHeight() * scaleY-->>15.178572 I/TAG: scaleY-->>0.0,,child.getHeight() * scaleY-->>0.0
2、第二种情况,滑动。因为这个是根据CoordinatorLayout里子view的滚动行为来改变我们的状态的,所以情况1中的2个方法我们就不需要重写了。下面,我们用情况2来实现上面的效果。
package com.example.administrator.myapplication;import android.content.Context;import android.support.design.widget.CoordinatorLayout;import android.support.v4.view.ViewCompat;import android.util.AttributeSet;import android.view.View;public class FooterBehavior extends CoordinatorLayout.Behavior<View>{ private float targetY = -1; private static final String TAG = "FooterBehavior"; public FooterBehavior(Context context,AttributeSet attributeSet){ super(context, attributeSet); } @Override public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, View child, View directTargetChild, View target, int nestedScrollAxes) { if(targetY == -1){ targetY = target.getY(); } return (nestedScrollAxes & ViewCompat.SCROLL_AXIS_VERTICAL) != 0; } @Override public void onNestedPreScroll(CoordinatorLayout coordinatorLayout, View child, View target, int dx, int dy, int[] consumed) { super.onNestedPreScroll(coordinatorLayout, child, target, dx, dy, consumed); float scrooY = targetY - Math.abs(target.getY()); float scaleY = scrooY / targetY; child.setTranslationY(child.getHeight() * scaleY); }}
在方法onStartNestedScroll中,首先获取target在Y轴上距离屏幕顶端的距离,然后判断是否是在Y轴上滚动。
方法onNestPreScroll中,就是时时根据target距离屏幕顶端的距离计算出滚动的距离,然后根据比例计算出child移动的距离。
我们简单看下源码
* @param coordinatorLayout the CoordinatorLayout parent of the view this Behavior is * associated with * @param child the child view of the CoordinatorLayout this Behavior is associated with * @param directTargetChild the child view of the CoordinatorLayout that either is or * contains the target of the nested scroll operation * @param target the descendant view of the CoordinatorLayout initiating the nested scroll * @param nestedScrollAxes the axes that this nested scroll applies to. See * {@link ViewCompat#SCROLL_AXIS_HORIZONTAL}, * {@link ViewCompat#SCROLL_AXIS_VERTICAL} * @return true if the Behavior wishes to accept this nested scroll * * @see NestedScrollingParent#onStartNestedScroll(View, View, int) */ public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, V child, View directTargetChild, View target, int nestedScrollAxes) { return false; }
百度翻译如下:
child:coordinatorlayout孩子的这种行为是与(本例就是FloatingActionButton)
target :启动嵌套滚动coordinatorlayout后裔的观点(本例就是AppBarLayout)
directTargetChild 这个涉及到深层次的布局问题,我们的布局中只有一个控件FloatingActionButton
- CoordinatorLayout用法学习
- MaterialDesign学习笔记3:CoordinatorLayout基本用法
- CoordinatorLayout用法
- Android学习之CoordinatorLayout
- CoordinatorLayout高级用法-自定义Behavior
- CoordinatorLayout高级用法-自定义Behavior
- CoordinatorLayout高级用法-自定义Behavior
- CoordinatorLayout高级用法-自定义Behavior
- CoordinatorLayout高级用法-自定义Behavior
- CoordinatorLayout结合Behavior高级用法
- CoordinatorLayout高级用法-自定义Behavior
- 学习Android CoordinatorLayout(一)
- 学习Android CoordinatorLayout(二)
- 关于嵌套滑动 CoordinatorLayout 学习
- CoordinatorLayout和Toolbar的学习
- Material Design学习之CoordinatorLayout
- CoordinatorLayout
- CoordinatorLayout
- HashMap遍历的两种方式
- 我的七年IT奋斗纪实及感悟
- hadoop学习笔记之二:安装伪分布式
- javascript_lesson4_函数
- jQuery使用ajaxSubmit()提交表单示例
- CoordinatorLayout用法学习
- 用Linux命令查看Linux的最大可用内存
- clone failed. Could not read from remote repository".
- tjut 2851
- oracle中与mysql中的命令 show databases, show tables, desc table类似的命令集
- 笔刷载入路径&光照实现立体化——电缆
- 【zzulioj 1913 小火山的计算能力】
- HDU1028——Ignatius and the Princess III(背包问题dp)
- 无法远程访问Mysql