CoordinatorLayout学习
效果图展示
布局代码:
<?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:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/background_light"
android:fitsSystemWindows="true">
<android.support.design.widget.AppBarLayout
android:id="@+id/id_main_appbar"
android:layout_width="match_parent"
android:layout_height="200dp"
android:fitsSystemWindows="true"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
<android.support.design.widget.CollapsingToolbarLayout
android:id="@+id/id_main_collapsing"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
app:collapsedTitleGravity="center"
app:contentScrim="?attr/colorPrimary"
app:expandedTitleMarginEnd="64dp"
app:expandedTitleMarginStart="48dp"
app:layout_scrollFlags="scroll|exitUntilCollapsed">
<ImageView
android:id="@+id/id_main_backdrop"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:contentDescription="@null"
android:fitsSystemWindows="true"
android:scaleType="centerCrop"
android:src="@mipmap/beijing"
app:layout_collapseMode="parallax" />
<android.support.v7.widget.Toolbar
android:id="@+id/id_main_toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:layout_collapseMode="pin"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:lineSpacingExtra="8dp"
android:padding="@dimen/activity_horizontal_margin"
android:text="@string/lorem"
android:textSize="20sp" />
</android.support.v4.widget.NestedScrollView>
<android.support.design.widget.FloatingActionButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="@dimen/activity_horizontal_margin"
android:src="@mipmap/ic_launcher"
app:layout_anchor="@id/id_main_appbar"
app:layout_anchorGravity="bottom|right|end" />
</android.support.design.widget.CoordinatorLayout>
代码中设置:
在代码中设置一下标题,在布局文件中设置标题,折叠之后标题不显示
idMainCollapsing.setTitle("我是标题···");
idMainCollapsing.setCollapsedTitleTextColor(Color.WHITE);
idMainCollapsing.setExpandedTitleColor(Color.YELLOW);
参数属性解释:
layout_scrollFlags说明
- scroll 想滚动必须设置
- enterAlways:实现quick return效果, 当向下移动时,立即显示View(比如Toolbar)。
- exitUntilCollapsed:向上滚动时收缩View,但可以固定Toolbar一直在上面。
- enterAlwaysCollapsed : 当你的View已经设置minHeight属性又使用此标志时,你的View只能以最小高度进入,只有当滚动视图到达顶部时才扩大到完整高度。
contentScrim - 设置当完全CollapsingToolbarLayout折叠(收缩)后的背景颜色。
- expandedTitleMarginStart - 设置扩张时候(还没有收缩时)title向左填充的距离。
- expandedTitleMarginEnd : 扩张状态下title距离下边的距离。
collapsedTitleGravity : 折叠时文字收缩的方向
layout_collapseMode有两个值
- pin :设置为这个模式时,当CollapsingToolbarLayout完全收缩后,Toolbar还可以保留在屏幕上。
- parallax - 设置为这个模式时,在内容滚动时,CollapsingToolbarLayout中的View(比如ImageView)也可以同时滚动,实现视差滚动效果,通常和layout_collapseParallaxMultiplier(设置视差因子)搭配使用。
- layout_collapseParallaxMultiplier(视差因子) - 设置视差滚动因子,值为:0~1。
- 已fab解释锚点属相
- app:layout_anchor=”@id/id_main_appbar” : fab控件显示在哪片位置。
- app:layout_anchorGravity=”bottom|right|end” :在该区域的具体位置。
- 只有设置了这两个属性,fab才能跟随折叠消失出现。
自定义Behavior
在自定义Behavior的时候,我们需要关心两种情况
某个view监听另一个view的状态变化,例如大小、位置、显示状态等
某个view监听CoordinatorLayout里的滑动状态
对于第一种情况,我们关心的是:
layoutDependsOn和onDependentViewChanged方法,
对于第二种情况,我们关心的是:
onStartNestedScroll和onNestedPreScroll方法。
这里先介绍第一种情况:
先上效果图:
拖动绿色按钮,界面上的所有控件都会受到影响,使用一般方式也可做到,不过没有使用自定义Behavior来的简洁一些。
实现步骤
1. 先自定义一个可拖动的view,也就是图中的绿色自定义View。
public class TempView extends View {
private int lastX;
private int lastY;
private int mWidth;
private int mHeight;
private int screenWidth;
private int screenHeight;
public TempView(Context context) {
super(context);
DisplayMetrics display = context.getResources().getDisplayMetrics();
screenWidth = display.widthPixels;
screenHeight = display.heightPixels;
}
public TempView(Context context, AttributeSet attrs) {
super(context, attrs);
mWidth = getMeasuredWidth();
mHeight = getMeasuredHeight();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
int x = (int) event.getRawX();
int y = (int) event.getRawY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN: {
break;
}
case MotionEvent.ACTION_MOVE: {
CoordinatorLayout.MarginLayoutParams layoutParams = (CoordinatorLayout.MarginLayoutParams) getLayoutParams();
int left = layoutParams.leftMargin + x - lastX;
int top = layoutParams.topMargin + y - lastY;
layoutParams.leftMargin = left;
layoutParams.topMargin = top;
setLayoutParams(layoutParams);
requestLayout();
break;
}
case MotionEvent.ACTION_UP: {
break;
}
}
lastX = x;
lastY = y;
return true;
}
}
2 编写布局文件
- 布局文件中的每一个Button下面的layout_behavior属性就是我们将要绑定的自定义Behavior:
- 另外也可以在代码中进行绑定:btn5这个按钮是在代码中绑定的,绑定方法如下:
CoordinatorLayout.LayoutParams layoutParams = (CoordinatorLayout.LayoutParams) mBtn5.getLayoutParams();
layoutParams.setBehavior(new MyBehavior());
<?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:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_anchorGravity="center">
<Button
android:id="@+id/btn2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="点击我进入第二个演示"
app:layout_behavior="ceo.yangqing.meimaobing.studynotes.fragment.CoordinatorLayout.MyBehavior"/>
<Button
android:id="@+id/btn3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="50dp"
android:text="点击我进入第三个演示"
app:layout_behavior="ceo.yangqing.meimaobing.studynotes.fragment.CoordinatorLayout.MyBehavior"/>
<Button
android:id="@+id/btn4"
android:layout_width="60dp"
android:layout_height="60dp"
android:background="#f00"
android:text="点击我进入第四个演示"
app:layout_behavior="ceo.yangqing.meimaobing.studynotes.fragment.CoordinatorLayout.MyBehavior"/>
<Button
android:id="@+id/btn5"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:layout_gravity="center"
app:layout_behavior="ceo.yangqing.meimaobing.studynotes.fragment.CoordinatorLayout.MyBehavior"/>
<ceo.yangqing.meimaobing.studynotes.fragment.CoordinatorLayout.TempView
android:id="@+id/myview"
android:layout_width="120dp"
android:layout_height="120dp"
android:layout_marginLeft="300dp"
android:background="#79f179"
android:text="拖动我试试"/>
</android.support.design.widget.CoordinatorLayout>
3 编写自定义Behavior
public class MyBehavior extends CoordinatorLayout.Behavior<Button> {
private int height;
private int width;
public MyBehavior(Context context, AttributeSet attrs) {
super(context, attrs);
DisplayMetrics display = context.getResources().getDisplayMetrics();
height = display.heightPixels;
width = display.widthPixels;
}
@Override
public boolean layoutDependsOn(CoordinatorLayout parent, Button child, View dependency) {
//如果dependency是TempView的实例,说明它就是我们所需要的Dependency
return dependency instanceof TempView;
}
@Override
public boolean onDependentViewChanged(CoordinatorLayout parent, Button child, View dependency) {
int distanceTop = dependency.getTop();
float f = distanceTop / (height * 1.0f);
parent.getChildAt(0).setAlpha(f);
parent.getChildAt(1).setScaleX(f);
parent.getChildAt(3).setRotation(720*f);
//根据dependency的位置,设置Button的位置
int top = dependency.getTop();
int left = dependency.getLeft();
int x = width - left - parent.getChildAt(2).getWidth();
int y = top;
setPosition(parent.getChildAt(2), x, y);
return true;
}
private void setPosition(View v, int x, int y) {
CoordinatorLayout.MarginLayoutParams layoutParams = (CoordinatorLayout.MarginLayoutParams) v.getLayoutParams();
layoutParams.leftMargin = x;
layoutParams.topMargin = y;
v.setLayoutParams(layoutParams);
}
}