您的位置:首页 > 其它

[置顶] CoordinatorLayout 属性详解 和 Behavior 的使用

2017-04-27 11:59 281 查看
关于 CoordinatorLayout 写过例子
 点击打开链接 链接是以前写的联动效果的例子,但是一直没有总结,其实CoordinatorLayout就是一个联动的布局动画效果,不用代码,就xml布局就能实现很多动画效果 。

1.首先来个简单的,先看效果图上推时从1到2

                  

toolbar消失

接着代码:

<?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=".activity.TabActivity">

<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

<android.support.v7.widget.Toolbar
android:id="@+id/tool_bar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:layout_scrollFlags="scroll|enterAlways|snap"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"/>

<android.support.design.widget.TabLayout
android:id="@+id/tab_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</android.support.design.widget.AppBarLayout>

<android.support.v4.view.ViewPager
android:id="@+id/view_pager"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"/>
</android.support.design.widget.CoordinatorLayout>

对上述代码分析:

 首先第一个属性:scrollflag:要和滚动联动都要设置这个标志,有一下几个值:

    1》enterAlways:跟随滚动视图的上下滚动,滚出屏幕,
    2》enterAlwaysCollapsed:当滚动视图滚动到底时,View只能以minHeight的高度滚入界面;
    3》exitUntilCollapsed:跟随滚动视图的上下滚动,但滚出时会预留minHeight的高度,实际能滚动的距离为  (layout_height-minHeight);
    4》snap:根据滚动释放时的状态来自动执行完整的enter或者exit动画;
 第二个属性:app:layout_behavior="@string/appbar_scrolling_view_behavior"-把滚动的内容设置在appbar下面,不然appbar会变为透明,并且滚动的内容会显示在(0,0)坐标

2.第二个例子上推从1到2

     


  代码:

<?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.dl7.coordinator.activity.ScrollActivity">

<android.support.design.widget.AppBarLayout
android:id="@+id/app_bar"
android:fitsSystemWindows="true"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

<android.support.design.widget.CollapsingToolbarLayout
android:id="@+id/collapsing_tool_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true"
app:contentScrim="@color/colorPrimary"
app:expandedTitleMarginStart="20dp"
app:layout_scrollFlags="scroll|exitUntilCollapsed|snap">

<ImageView
android:layout_width="match_parent"
android:layout_height="200dp"
android:fitsSystemWindows="true"
android:scaleType="centerCrop"
android:src="@mipmap/pic"
app:layout_collapseParallaxMultiplier="0.6"
app:layout_collapseMode="parallax"/>

<android.support.v7.widget.Toolbar
android:id="@+id/tool_bar"
android:layout_width="match_parent"
app:theme="@style/ThemeOverlay.AppCompat.Dark"
android:layout_height="?attr/actionBarSize"
app:layout_collapseMode="pin"/>
</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">

<!-- 滚动的内容 -->
<include layout="@layout/layout_scroll_content"/>
</android.support.v4.widget.NestedScrollView>
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_anchor="@id/app_bar"
app:layout_anchorGravity="bottom|right"
android:layout_margin="16dp"
android:src="@mipmap/ic_start"/>
</android.support.design.widget.CoordinatorLayout>

 代码分析:

      1》CollapsingToolbarLayout 会去自动获取Toolbar的高度设为滚动后的最小高度minHeight

      2》app:layout_collapseMode="parallax":视差模式,在折叠的时候会有个视差折叠的效果。与               app:layout_collapseParallaxMultiplier:配合使用。当滚动的时候设置视差滚动系数 0~1 视差显示图片是上移动的,等于
1 图片是固定不动的,大于 1 图片是向下移动,然后toolbar显示。
      3》app:layout_collapseMode="pin":固定模式,这个属性是在滚动的时候,最终在屏幕顶端固定的view,该view不会滑出屏幕,会被固定在顶端。

      4》app:expandedTitleMarginStart="20dp" - 表示头部展开时 title 距离左侧的距离大小

      5》app:layout_anchor和app:layout_anchorGravity来实现联动;

      app:layout_anchor="@id/app_bar":用来设置与id所关联的控件进行协调,即AppBarLayout;

      app:layout_anchorGravity="bottom|right":用来设置与关联控件的位置关系;

      6》app:layout_scrollFlags="scroll|exitUntilCollapsed|snap",这个属性设置滚动到顶部,此view就停止上移,被固定在顶部。

第三个例子,CoordinatorLayout 与 Behavior 联动

效果图


 

代码:

<?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.dl7.coordinator.activity.CustomBehaviorActivity">

<android.support.design.widget.AppBarLayout
android:id="@+id/app_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

<android.support.design.widget.CollapsingToolbarLayout
android:id="@+id/collapsing_tool_bar"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:contentScrim="@color/colorPrimary"
app:expandedTitleGravity="bottom|center_horizontal"
app:layout_scrollFlags="scroll|exitUntilCollapsed|snap">

<ImageView
android:id="@+id/iv_head"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="fitXY"
android:src="@mipmap/bane"
app:layout_collapseMode="parallax"
app:layout_collapseParallaxMultiplier="0.6"/>

<!-- 设置app:navigationIcon="@android:color/transparent"给头像预留位置 -->
<android.support.v7.widget.Toolbar
android:id="@+id/tool_bar"
android:layout_width="match_parent"
android:layout_height="@dimen/toolbar_height"
app:layout_collapseMode="pin"
app:navigationIcon="@android:color/transparent"
app:theme="@style/ThemeOverlay.AppCompat.Dark"
app:title="Tom Hardy"/>
</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">

<include layout="@layout/layout_content_tom"/>
</android.support.v4.widget.NestedScrollView>

<!-- layout_anchor属性5.0以上需要设置为CollapsingToolbarLayout,不然头像最后会被覆盖 -->
<de.hdodenhof.circleimageview.CircleImageView
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_margin="16dp"
android:src="@mipmap/tom"
app:border_color="@android:color/white"
app:border_width="1dp"
app:layout_anchor="@id/collapsing_tool_bar"
app:layout_anchorGravity="bottom|right"
app:layout_behavior="com.dl7.coordinator.behavior.AvatarBehavior"/>
</android.support.design.widget.CoordinatorLayout>


app:layout_behavior="com.dl7.coordinator.behavior.AvatarBehavior"
AvatarBehavior的布局:

package com.dl7.coordinator.behavior;

import android.content.Context;
import android.content.res.TypedArray;
import android.os.Build;
import android.support.design.widget.AppBarLayout;
import android.support.design.widget.CollapsingToolbarLayout;
import android.support.design.widget.CoordinatorLayout;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.View;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.DecelerateInterpolator;
import android.widget.FrameLayout;

import com.dl7.coordinator.R;
import com.dl7.coordinator.utils.AnimHelper;

import de.hdodenhof.circleimageview.CircleImageView;

/**
* Created by long on 2016/7/11.
* 头像Behavior
*/
public class AvatarBehavior extends CoordinatorLayout.Behavior<CircleImageView> {

// 缩放动画变化的支点
private static final float ANIM_CHANGE_POINT = 0.2f;

private Context mContext;
// 整个滚动的范围
private int mTotalScrollRange;
// AppBarLayout高度
private int mAppBarHeight;
// AppBarLayout宽度
private int mAppBarWidth;
// 控件原始大小
private int mOriginalSize;
// 控件最终大小
private int mFinalSize;
// 控件最终缩放的尺寸,设置坐标值需要算上该值
private float mScaleSize;
// 原始x坐标
private float mOriginalX;
// 最终x坐标
private float mFinalX;
// 起始y坐标
private float mOriginalY;
// 最终y坐标
private float mFinalY;
// ToolBar高度
private int mToolBarHeight;
// AppBar的起始Y坐标
private float mAppBarStartY;
// 滚动执行百分比[0~1]
private float mPercent;
// Y轴移动插值器
private DecelerateInterpolator mMoveYInterpolator;
// X轴移动插值器
private AccelerateInterpolator mMoveXInterpolator;
// 最终变换的视图,因为在5.0以上AppBarLayout在收缩到最终状态会覆盖变换后的视图,所以添加一个最终显示的图片
private CircleImageView mFinalView;
// 最终变换的视图离底部的大小
private int mFinalViewMarginBottom;

public AvatarBehavior(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
mMoveYInterpolator = new DecelerateInterpolator();
mMoveXInterpolator = new AccelerateInterpolator();
if (attrs != null) {
TypedArray a = mContext.obtainStyledAttributes(attrs, R.styleable.AvatarImageBehavior);
mFinalSize = (int) a.getDimension(R.styleable.AvatarImageBehavior_finalSize, 0);
mFinalX = a.getDimension(R.styleable.AvatarImageBehavior_finalX, 0);
mToolBarHeight = (int) a.getDimension(R.styleable.AvatarImageBehavior_toolBarHeight, 0);
a.recycle();
}
}

@Override
public boolean layoutDependsOn(CoordinatorLayout parent, CircleImageView child, View dependency) {
return dependency instanceof AppBarLayout;
}

@Override
public boolean onDependentViewChanged(CoordinatorLayout parent, CircleImageView child, View dependency) {

if (dependency instanceof AppBarLayout) {
_initVariables(child, dependency);

mPercent = (mAppBarStartY - dependency.getY()) * 1.0f / mTotalScrollRange;

float percentY = mMoveYInterpolator.getInterpolation(mPercent);
AnimHelper.setViewY(child, mOriginalY, mFinalY - mScaleSize, percentY);

if (mPercent > ANIM_CHANGE_POINT) {
float scalePercent = (mPercent - ANIM_CHANGE_POINT) / (1 - ANIM_CHANGE_POINT);
float percentX = mMoveXInterpolator.getInterpolation(scalePercent);
AnimHelper.scaleView(child, mOriginalSize, mFinalSize, scalePercent);
AnimHelper.setViewX(child, mOriginalX, mFinalX - mScaleSize, percentX);
} else {
AnimHelper.scaleView(child, mOriginalSize, mFinalSize, 0);
AnimHelper.setViewX(child, mOriginalX, mFinalX - mScaleSize, 0);
}
if (mFinalView != null) {
if (percentY == 1.0f) {
// 滚动到顶时才显示
mFinalView.setVisibility(View.VISIBLE);
} else {
mFinalView.setVisibility(View.GONE);
}
}
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && dependency instanceof CollapsingToolbarLayout) {
// 大于5.0才生成新的最终的头像,因为5.0以上AppBarLayout会覆盖变换后的头像
if (mFinalView == null && mFinalSize != 0 && mFinalX != 0 && mFinalViewMarginBottom != 0) {
mFinalView = new CircleImageView(mContext);
mFinalView.setVisibility(View.GONE);
// 添加为CollapsingToolbarLayout子视图
((CollapsingToolbarLayout) dependency).addView(mFinalView);
FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) mFinalView.getLayoutParams();
// 设置大小
params.width = mFinalSize;
params.height = mFinalSize;
// 设置位置,最后显示时相当于变换后的头像位置
params.gravity = Gravity.BOTTOM;
params.leftMargin = (int) mFinalX;
params.bottomMargin = mFinalViewMarginBottom;
mFinalView.setLayoutParams(params);
mFinalView.setImageDrawable(child.getDrawable());
mFinalView.setBorderColor(child.getBorderColor());
int borderWidth = (int) ((mFinalSize * 1.0f / mOriginalSize) * child.getBorderWidth());
mFinalView.setBorderWidth(borderWidth);
}
}

return true;
}

/**
* 初始化变量
* @param child
* @param dependency
*/
private void _initVariables(CircleImageView child, View dependency) {
if (mAppBarHeight == 0) {
mAppBarHeight = dependency.getHeight();
mAppBarStartY = dependency.getY();
}
if (mTotalScrollRange == 0) {
mTotalScrollRange = ((AppBarLayout) dependency).getTotalScrollRange();
}
if (mOriginalSize == 0) {
mOriginalSize = child.getWidth();
}
if (mFinalSize == 0) {
mFinalSize = mContext.getResources().getDimensionPixelSize(R.dimen.avatar_final_size);
}
if (mAppBarWidth == 0) {
mAppBarWidth = dependency.getWidth();
}
if (mOriginalX == 0) {
mOriginalX = child.getX();
}
if (mFinalX == 0) {
mFinalX = mContext.getResources().getDimensionPixelSize(R.dimen.avatar_final_x);
}
if (mOriginalY == 0) {
mOriginalY = child.getY();
}
if (mFinalY == 0) {
if (mToolBarHeight == 0) {
mToolBarHeight = mContext.getResources().getDimensionPixelSize(R.dimen.toolbar_height);
}
mFinalY = (mToolBarHeight - mFinalSize) / 2 + mAppBarStartY;
}
if (mScaleSize == 0) {
mScaleSize = (mOriginalSize - mFinalSize) * 1.0f / 2;
}
if (mFinalViewMarginBottom == 0) {
mFinalViewMarginBottom = (mToolBarHeight - mFinalSize) / 2;
}
}
}


看了一个人的例子,然后总结了一下。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: