CoordinatorLayout是Material Design包中的用来协调子View的位置,实现联动的动画效果,实现了许多滚动效果
* 让浮动操作按钮上下滑动,为Snackbar留出空间。
* 扩展或者缩小(隐藏)Toolbar或者头部,让主内容区域有更多的空间。
* 控制哪个view应该扩展还是收缩,以及其显示大小比例,包括视差滚动效果动画。
首先添加依赖
compile 'com.android.support:design:22.2.0'
compile 'com.android.support:recyclerview-v7:22.2.0'
compile 'com.android.support:cardview-v7:22.2.0'
直接上代码 activity_main.xml
<?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:id="@+id/main_content"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.AppBarLayout
android:id="@+id/appbar"
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/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:layout_scrollFlags="scroll|enterAlways"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />
<android.support.design.widget.TabLayout
android:id="@+id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabIndicatorColor="#ADBE107E"
app:tabMode="scrollable" />
</android.support.design.widget.AppBarLayout>
<android.support.v4.view.ViewPager
android:id="@+id/viewpager"
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"
android:layout_margin="10dp"
android:clickable="true"
android:onClick="checkin"
android:src="@android:drawable/ic_dialog_email"
app:layout_anchor="@id/main_content"
app:layout_anchorGravity="bottom|right|end" />
</android.support.design.widget.CoordinatorLayout>
list_fragment.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.RecyclerView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />
list_item_card_main.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:paddingLeft="8dp"
android:paddingRight="8dp"
android:paddingTop="8dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:orientation="horizontal">
<ImageView
android:layout_width="120dp"
android:layout_height="70dp"
android:background="@mipmap/girl" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:ellipsize="end"
android:gravity="center_vertical"
android:maxLines="2"
android:text="真正的科学家应当是个幻想家;谁不是幻想家,谁就只能把自己称为实践家。"
android:textSize="18sp" />
</LinearLayout>
</android.support.v7.widget.CardView>
activity_detail.xml
<?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:id="@+id/main_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true">
<android.support.design.widget.AppBarLayout
android:id="@+id/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/collapsing_toolbar"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
app:contentScrim="?attr/colorPrimary"
app:expandedTitleMarginEnd="64dp"
app:expandedTitleMarginStart="48dp"
app:layout_scrollFlags="scroll|exitUntilCollapsed">
<ImageView
android:id="@+id/backdrop"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:scaleType="centerCrop"
android:src="@mipmap/girl" />
<android.support.v7.widget.Toolbar
android:id="@+id/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.v7.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="none"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
</android.support.design.widget.CoordinatorLayout>
java代码:
MainActivity.java
package com.jd.coordinatorlayout;
import android.os.Bundle;
import android.support.design.widget.Snackbar;
import android.support.design.widget.TabLayout;
import android.support.v4.app.Fragment;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.View;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
private ViewPager mViewPager;
private TabLayout mTabLayout;
private List<String> titles;
private List<Fragment> fragments;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
mViewPager = (ViewPager) findViewById(R.id.viewpager);
mTabLayout = (TabLayout) findViewById(R.id.tabs);
initData();
initTabs(titles);
initFragmens();
bindViewpager();
}
private void initData() {
titles = new ArrayList<>();
titles.add("推荐");
titles.add("热点");
titles.add("阳光宽屏");
titles.add("北京");
titles.add("社会");
titles.add("娱乐");
titles.add("问答");
titles.add("图片");
titles.add("科技");
titles.add("汽车");
titles.add("体育");
titles.add("财经");
titles.add("军事");
titles.add("国际");
titles.add("段子");
titles.add("趣图");
titles.add("美女");
titles.add("健康");
titles.add("正能量");
titles.add("特卖");
titles.add("房产");
titles.add("中国新唱将");
}
private void bindViewpager() {
FragmentAdapter mFragmentAdapteradapter =
new FragmentAdapter(getSupportFragmentManager(), fragments, titles);
//给ViewPager设置适配器
mViewPager.setAdapter(mFragmentAdapteradapter);
//将TabLayout和ViewPager关联起来。
mTabLayout.setupWithViewPager(mViewPager);
//给TabLayout设置适配器
mTabLayout.setTabsFromPagerAdapter(mFragmentAdapteradapter);
}
private void initFragmens() {
fragments = new ArrayList<>();
for (int i = 0; i < titles.size(); i++) {
fragments.add(new ListFragment());
}
}
private void initTabs(List<String> titles) {
for (int i = 0; i < titles.size(); i++) {
mTabLayout.addTab(mTabLayout.newTab().setText(titles.get(i)));
}
}
public void checkin(View view) {
Snackbar.make(view, "点击成功", Snackbar.LENGTH_SHORT).show();
}
}
ListFragment.java
package com.jd.coordinatorlayout;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class ListFragment extends Fragment {
private RecyclerView mRecyclerView;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
mRecyclerView =
(RecyclerView) inflater.inflate(R.layout.list_fragment, container, false);
return mRecyclerView;
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mRecyclerView.setLayoutManager(new LinearLayoutManager(mRecyclerView.getContext()));
mRecyclerView.setAdapter(new RecyclerViewAdapter(getActivity()));
}
}
FragmentAdapter.java
package com.jd.coordinatorlayout;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentStatePagerAdapter;
import java.util.List;
public class FragmentAdapter extends FragmentStatePagerAdapter {
private List<Fragment> mFragments;
private List<String> mTitles;
public FragmentAdapter(FragmentManager fm, List<Fragment> fragments, List<String> titles) {
super(fm);
mFragments = fragments;
mTitles = titles;
}
@Override
public Fragment getItem(int position) {
return mFragments.get(position);
}
@Override
public int getCount() {
return mFragments.size();
}
@Override
public CharSequence getPageTitle(int position) {
return mTitles.get(position);
}
}
RecyclerViewAdapter.java
package com.jd.coordinatorlayout;
import android.content.Context;
import android.content.Intent;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.ViewHolder> {
private Context mContext;
public RecyclerViewAdapter(Context mContext) {
this.mContext = mContext;
}
@Override
public RecyclerViewAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view =
LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_card_main, parent, false);
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(final RecyclerViewAdapter.ViewHolder holder, int position) {
final View view = holder.mView;
view.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent mIntent = new Intent(mContext, CollapsingToolbarActivity.class);
mContext.startActivity(mIntent);
}
});
}
@Override
public int getItemCount() {
return 20;
}
public static class ViewHolder extends RecyclerView.ViewHolder {
public final View mView;
public ViewHolder(View view) {
super(view);
mView = view;
}
}
}
CollapsingToolbarActivity.java
package com.jd.coordinatorlayout;
import android.os.Bundle;
import android.support.design.widget.CollapsingToolbarLayout;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.StaggeredGridLayoutManager;
import android.support.v7.widget.Toolbar;
public class CollapsingToolbarActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_detail);
Toolbar toolbar = (Toolbar) this.findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
CollapsingToolbarLayout collapsingToolbar =
(CollapsingToolbarLayout) findViewById(R.id.collapsing_toolbar);
collapsingToolbar.setTitle("美女图片");
RecyclerView mRecyclerView = (RecyclerView) findViewById(R.id.recyclerView);
mRecyclerView.setLayoutManager(new StaggeredGridLayoutManager(1, StaggeredGridLayoutManager.VERTICAL));
mRecyclerView.setItemAnimator(new DefaultItemAnimator());
mRecyclerView.setAdapter(new RecyclerViewAdapter(CollapsingToolbarActivity.this));
}
}
style.xml
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style>
</resources>
下面就依次解读一下关键的代码
实现FloatingActionButton与Snackbar的联动效果
<android.support.design.widget.FloatingActionButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="10dp"
android:clickable="true"
android:onClick="checkin"
android:src="@android:drawable/ic_dialog_email"
app:layout_anchor="@id/main_content"
app:layout_anchorGravity="bottom|right|end" />
只要使用CoordinatorLayout作为基本布局,将自动产生向上移动的动画.浮动操作按钮有一个 默认的 behavior来检测Snackbar的添加并让按钮在Snackbar之上呈现上移与Snackbar等高的动画。
Toolbar的显示与隐藏
首先使用Toolbar代替Actionbar,同样使用CoordinatorLayout作为布局容器,要想Toolbar能够响应滚动事件,需要在Toolbar的外面包裹一层AppBarLayout,而且AppBarLayout必须是CoordinatorLayout的直接子View,Tollbar中添加app:layout_scrollFlags=”scroll|enterAlways”,AppBarLayout里面定义的view只要设置了app:layout_scrollFlags属性,就可以在RecyclerView滚动事件发生的时候被触发:
- enterAlways: 一旦向上滚动这个view就可见。
- enterAlwaysCollapsed: 顾名思义,这个flag定义的是何时进入(已经消失之后何时再次显示)。假设你定义了一个最小高度(minHeight)同时enterAlways也定义了,那么view将在到达这个最小高度的时候开始显示,并且从这个时候开始慢慢展开,当滚动到顶部的时候展开完。
- exitUntilCollapsed: 同样顾名思义,这个flag时定义何时退出,当你定义了一个minHeight,这个view将在滚动到达这个最小高度的时候消失。
<android.support.design.widget.AppBarLayout
android:id="@+id/appbar"
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/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:layout_scrollFlags="scroll|enterAlways"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />
</android.support.design.widget.AppBarLayout>
在RecyclerView或者任意支持嵌套滚动的view添加app:layout_behavior属性,并引用@string/appbar_scrolling_view_behavior,这里用的是Viewpager来嵌套recyclerview
<android.support.v4.view.ViewPager
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
控制哪个view应该扩展还是收缩,以及其显示大小比例,包括视差滚动效果动画
要实现这个下过就需要在Toolbar外面包裹一层CollapsingToolbarLayout
<android.support.design.widget.AppBarLayout
android:id="@+id/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/collapsing_toolbar"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
app:contentScrim="?attr/colorPrimary"
app:expandedTitleMarginEnd="64dp"
app:expandedTitleMarginStart="48dp"
app:layout_scrollFlags="scroll|exitUntilCollapsed">
<ImageView
android:id="@+id/backdrop"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:scaleType="centerCrop"
android:src="@mipmap/girl" />
<android.support.v7.widget.Toolbar
android:id="@+id/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>
recyclerview中添加app:layout_behavior
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="none"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
给CollapsingToolbarLayout 设置Title
CollapsingToolbarLayout collapsingToolbar =
(CollapsingToolbarLayout) findViewById(R.id.collapsing_toolbar);
collapsingToolbar.setTitle("美女图片");