介绍
目前市面上常常能够看到一些很炫的UI效果,比如说,顶部显示一个图片,底部是一个列表,当滚动到顶部时,顶部的图片发生折叠。这种效果需要多个控件进行配合。
CoordinatorLayout 是这样一种控件,他能够根据一种机制,协调两个控件的操作。
AppBarLayout
AppBarLayout继承自LinearLayout,布局方向为垂直方向。它内部有个机制就是当某个可滚动View的滚动手势发生变化时,他内部的控件也发生相应的
变化。
demo:下拉时优先下拉toolbar到最大高度,上拉时有限缩小toolbar
引包
//recyclerview,测试过了listview没有协同效果
dependencies { compile 'com.android.support:recyclerview-v7:25.3.1' }
//md
compile 'com.android.support:design:25.3.1'
布局
<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.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.v7.widget.Toolbar
android:layout_width="match_parent"
android:layout_height="150dp"
//指定了最低的高度
android:minHeight="?android:attr/actionBarSize"
//通过该属性设置滚动控件和toolbar的关系
//scroll的子控件会与滚动控件一起发生移动|当滚动View向上滑动时,View先缩小到最小尺寸前,
滚动的View都不会滚动。
app:layout_scrollFlags="scroll|exitUntilCollapsed"/>
</android.support.design.widget.AppBarLayout>
//listview不行
<android.support.v7.widget.RecyclerView
android:id="@+id/lv"
android:layout_width="match_parent"
android:layout_height="match_parent"
//设置behavior,稍后解释
app:layout_behavior="@string/appbar_scrolling_view_behavior"/>
</android.support.design.widget.CoordinatorLayout>
属性介绍
scroll:值设为scroll的子控件会与滚动控件一起发生移动
enterAlways: 任何情况下先滚动子控件,再滚动可滚动的控件
enterAlwaysCollapsed:优先滚动toolbar到不可见,再滚动toolbar
exitUntilCollapsed:当滚动View向上滑动时, View先缩小到最小尺寸前,滚动View都不会滚动。
snap: 子控件滚动到一定位置的时候,自动显示和隐藏。
CollapsingToolbarLayout
包装toolbar,将toolbar和额外的控件粘合在一起.
提供ToolBar折叠的效果
//将toolbar和Imageview封装为一个可折叠的toolbar
<android.support.design.widget.CollapsingToolbarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:contentScrim="#0ff"
app:layout_scrollFlags="scroll|exitUntilCollapsed">
<ImageView
android:layout_width="match_parent"
android:layout_height="150dp"
android:scaleType="fitXY"
android:src="@mipmap/ic_launcher_round"
//设置效果为视差
app:layout_collapseMode="parallax"
//视差比例为0.6
app:layout_collapseParallaxMultiplier="0.6"/>
<android.support.v7.widget.Toolbar
android:background="#F00"
android:layout_width="match_parent"
android:layout_height="?android:attr/actionBarSize"
//将toolbar固定,设置了以后toolbar将一直存在
app:layout_collapseMode="pin"/>
</android.support.design.widget.CollapsingToolbarLayout>
完整demo
布局
<?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.support.design.widget.AppBarLayout
android:id="@+id/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:contentScrim="#0ff"
app:layout_scrollFlags="scroll|exitUntilCollapsed">
<ImageView
android:layout_width="match_parent"
android:layout_height="150dp"
android:scaleType="fitXY"
android:src="@mipmap/ic_launcher_round"
app:layout_collapseMode="parallax"
app:layout_collapseParallaxMultiplier="0.6"/>
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?android:attr/actionBarSize"/>
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
<android.support.v7.widget.RecyclerView
android:id="@+id/lv"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"/>
<android.support.design.widget.FloatingActionButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_anchor="@id/appbarlayout"
app:layout_anchorGravity="bottom|right"/>
</android.support.design.widget.CoordinatorLayout>
代码
public class MainActivity extends AppCompatActivity {
@BindView(R.id.lv)
RecyclerView mLv;
@BindView(R.id.toolbar)
Toolbar mToolbar;
@BindView(R.id.appbarlayout)
AppBarLayout mAppbarlayout;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
mToolbar.setTitle("你好啊");
ArrayList<String> strs = new ArrayList<>();
for (int i = 0; i < 50; i++) {
strs.add("上山打老虎" + i);
}
MyAdapter adapter = new MyAdapter(strs);
mLv.setAdapter(adapter);
mLv.setLayoutManager(new LinearLayoutManager(this));
}
class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
ArrayList<String> mDatas = new ArrayList<>();
public MyAdapter(ArrayList<String> datas) {
mDatas = datas;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(android.R.layout.simple_list_item_1, parent, false);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
holder.tv.setText(mDatas.get(position));
}
@Override
public int getItemCount() {
return mDatas.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
TextView tv;
public ViewHolder(View itemView) {
super(itemView);
tv = (TextView) itemView.findViewById(android.R.id.text1);
}
}
}
}
重头戏:Behavior详解
还记得我们之前给RecyleView配置了
layout_behavior。之前我们告诉大家,这个是当一个控件的位置,大小发生变化的时候,相应的控件的也会发生变化
自定义behavior
public class MyBehavior extends CoordinatorLayout.Behavior<android.support.constraint.ConstraintLayout> {
//两个构造器都要有
public MyBehavior() {
}
public MyBehavior(Context context, AttributeSet attrs) {
super(context, attrs);
}
//为true则开启协同
@Override
public boolean layoutDependsOn(CoordinatorLayout parent, ConstraintLayout child, View dependency) {
return dependency instanceof NestedScrollView;
}
int mY=0;
@Override
//大小或者位置改变时回调
public boolean onDependentViewChanged(CoordinatorLayout parent, ConstraintLayout child, View dependency) {
//上滑隐藏floatingactionbutton
int y=(int)dependency.getY();
Logger.d("y:"+y);
if ((mY-y)>0){
Log.d("meee",getClass()+":\n"+"222");
child.findViewById(R.id.fab).setVisibility(View.GONE);
mY=y;
return true;
//上滑显示floatingactionbutton
}else if((mY-y)<0){
Log.d("meee",getClass()+":\n"+"333");
child.findViewById(R.id.fab).setVisibility(View.VISIBLE);
mY=y;
return true;
}
mY=y;
return super.onDependentViewChanged(parent, child, dependency);
}
}
<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.junx.coordinatorlayout.MyBehavior.MyBehaviorActivity">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/transparent"
android:orientation="vertical">
<android.support.design.widget.CollapsingToolbarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/white"
android:minHeight="40dp"
app:layout_scrollFlags="scroll|exitUntilCollapsed|snap">
<LinearLayout
android:id="@+id/top"
android:layout_width="match_parent"
android:layout_height="400dp"
android:orientation="vertical">
</LinearLayout>
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
<android.support.v4.widget.NestedScrollView
android:id="@+id/scroll"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
app:behavior_overlapTop="10dp"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="15dp"
android:text="你\n你\n你\n你\n你\n你\n你\n你\n你\n你\n你\n你\n你\n你\n你\n你\n你\n你\n你\n你\n你\n你\n你\n你\n你\n你\n你\n你\n你\n你\n你\n你\n你\n你\n你\n你\n"/>
</android.support.v4.widget.NestedScrollView>
<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="com.junx.coordinatorlayout.MyBehavior.MyBehavior">
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintHorizontal_bias="0.77"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias="0.8"/>
</android.support.constraint.ConstraintLayout>
</android.support.design.widget.CoordinatorLayout>