关于 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>
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; } } }
看了一个人的例子,然后总结了一下。