一.前言
有时候我们要实现一些复杂效果时候,系统提供的behavior并不能完全满足我们需求,这时候使用一些自定义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:id="@+id/activity_circle_image_simple_behavior"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.testdemo.king.kingtestdemo.CircleImageSimpleBehavior">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.design.widget.CollapsingToolbarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_scrollFlags="scroll|exitUntilCollapsed|snap">
<ImageView
android:layout_width="match_parent"
android:layout_height="200dp"
android:scaleType="centerCrop"
android:src="@mipmap/holder"
app:layout_collapseMode="parallax"
app:layout_collapseParallaxMultiplier="0.2" />
<FrameLayout
android:id="@+id/frameLayout"
android:layout_width="match_parent"
android:layout_height="20dp"
android:layout_gravity="bottom|center_horizontal"
android:orientation="vertical"
app:layout_collapseMode="parallax"
app:layout_collapseParallaxMultiplier="0.1">
</FrameLayout>
</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"
android:background="@android:color/transparent"
android:scrollbars="none"
app:behavior_overlapTop="30dp"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<android.support.v7.widget.CardView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="8dp"
app:cardElevation="8dp"
app:contentPadding="16dp">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="@string/test_text" />
</android.support.v7.widget.CardView>
<android.support.v7.widget.CardView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="8dp"
app:cardElevation="8dp"
app:contentPadding="16dp">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="@string/test_text" />
</android.support.v7.widget.CardView>
</LinearLayout>
</android.support.v4.widget.NestedScrollView>
<android.support.v7.widget.Toolbar
android:id="@+id/mytoolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:layout_anchor="@id/frameLayout"
app:theme="@style/ThemeOverlay.AppCompat.Dark"></android.support.v7.widget.Toolbar>
<!-- 第三方圆形图片控件,导入依赖即可,适用于头像处理 -->
<ImageView
android:id="@+id/iv_Head"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_gravity="center|right"
android:src="@mipmap/icon_caddie_unselect"
app:layout_behavior=".behivor.CustomCircleViewBehavior" />
</android.support.design.widget.CoordinatorLayout>
- layout_scrollFlags详解:
- scroll:孩子视图伴随滚动事件而滚出或滚进屏幕
- enterAlways:向下滚动时Scrolling View和Child View之间的滚动优先级,当优先滚动的一方全部滚进屏幕之后,另一方才开始滚动
- enterAlwaysCollapsed:enterAlways的附加值,这里涉及到孩子视图的高度和最小高度,向下滚动时,孩子视图会先向下滚动至最小高度值,然后Scrolling View才开始滚动,到达边界时,孩子视图再向下滚动,直至显示完全
- exitUtilCollapsed:这里也涉及最小高度,发生向上滚动事件时,孩子视图向上滚动退出直至最小高度,然后Scrolling View开始滚动,也就是,Child View不会完全退出屏幕
snap:简单理解,就是Child View的一个吸附效果,也就是说,Child View不会存在局部显示的情况,滚动Child View的部分高度,当我们松开手指时,Child View 要么向上全部滚出屏幕,要么向下全部滚进屏幕,有点类似ViewPager的左右滑动
- layout_collapseMode (折叠模式) - 有两个值:
- pin:设置为这个模式时,当CollapsingToolbarLayout完全收缩后,Toolbar还可以保留在屏幕上。
- parallax:设置为这个模式时,在内容滚动时,CollapsingToolbarLayout中的View(比如ImageView)也可以同时滚动,实现视差滚动效果,通常和layout_collapseParallaxMultiplier(设置视差因子)搭配使用
三.自定义behavior代码实现
package com.testdemo.king.kingtestdemo.behivor;
import android.content.Context;
import android.support.design.widget.CoordinatorLayout;
import android.support.v7.widget.Toolbar;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import com.testdemo.king.kingtestdemo.R;
import static android.content.ContentValues.TAG;
/**
* Created by king on 2017/9/16.
*/
public class CustomCircleViewBehavior extends CoordinatorLayout.Behavior<ImageView> {
//圆形图片的最终大小
private float mFinalHeadHeight = 50;
//圆形图片起始的y坐标
private float mStartHeadY;
//圆形图片起始的x坐标
private float mStartHeadX;
//圆形图片其实的大小
private int mOriginalHeadHeight;
public CustomCircleViewBehavior(Context context, AttributeSet attrs) {
super(context, attrs);
}
// 如果dependency为Toolbar
@Override
public boolean layoutDependsOn(CoordinatorLayout parent, ImageView child, View dependency) {
// return dependency instanceof Toolbar;
return dependency.getId()== R.id.mytoolbar;
}
//当dependency变化的时候调用
@Override
public boolean onDependentViewChanged(CoordinatorLayout parent, ImageView child, View dependency) {
//第一次执行将圆形图片其实的x,y值和圆形图片的初始大小获取到
if (mStartHeadY == 0) {
mStartHeadY = dependency.getY();
}
if (mStartHeadX == 0) {
mStartHeadX = child.getX();
}
if (mOriginalHeadHeight == 0) {
mOriginalHeadHeight = child.getHeight();
}
//设置头像的y坐标为ToolBar的y坐标
child.setY(dependency.getY());
//计算ToolBar移动后的y坐标占ToolBar初始y坐标的比例
float percent = dependency.getY() / mStartHeadY;
//x坐标的目标点设置到水平中心处,按照比例让x坐标变化
float x = -(mStartHeadX - (dependency.getWidth() / 2 - mFinalHeadHeight )) * (1 - percent) + mStartHeadX;
Log.e(TAG, "onDependentViewChanged: "+x );
child.setX(x);
//不断修改圆形图片的宽高(圆形图片宽度和高度一致)
CoordinatorLayout.LayoutParams layoutParams =
(CoordinatorLayout.LayoutParams) child.getLayoutParams();
//当前大小=最终大小+(起始大小-最终大小)x百分比
layoutParams.height = (int) ((mOriginalHeadHeight - mFinalHeadHeight) * percent + mFinalHeadHeight);
layoutParams.width = (int) ((mOriginalHeadHeight - mFinalHeadHeight) * percent + mFinalHeadHeight);
child.setLayoutParams(layoutParams);
return true;
}
}
而这样做还有一个好处 activity没有任何的处理,实现了解耦合.