如何使用CoordinatorLayout搭配AppBarLayout

如何使用CoordinatorLayout搭配AppBarLayout

情境

如何使用RecylerView+CardView以及
如何使用Toolbar+DrawerLayout+Tab+SwipRefresh

示範了TabLayout跟RecyclerView的使用
這個範例來結合這兩個元件
加入CoordinatorLayout跟AppBarLayout完成一個往上推Tab會縮上去的效果

完整程式碼

你可以到 GitHub 上面觀看或下載完整的程式碼

最終結果

先來看最後呈現出來的效果
效果如下圖






會看到當我們的 RecyclerView 往上滾動的時候
TabLayout 就會自動的往 Toolbar 的下方縮進去
感覺就像是被 Toolbar 收納起來一樣
這樣的好處就是在觀看 RecyclerView 的時候
有更多的空間可以展示出 RecyclerView 的內容物

程式碼說明

import library

我們在這個 Layout 會用到 RecyclerView 以及 CardView
因此需要透過 Gradle 將所需要的 library import 進來

compile 'com.android.support:recyclerview-v7:22.2.0'
compile 'com.android.support:cardview-v7:22.2.0'
...

布局

一開始的布局決定了這個 Layout 的呈現方式

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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.v7.widget.Toolbar
        android:layout_alignParentTop="true"
        android:id="@+id/toolbar"
        android:background="#994455"
        android:layout_height="wrap_content"
        android:layout_width="match_parent"
        android:minHeight="?attr/actionBarSize" />
    <android.support.design.widget.CoordinatorLayout
        android:layout_below="@id/toolbar"
        android:id="@+id/coordinator_layout"
        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:fitsSystemWindows="true"
            android:id="@+id/appbar_layout">
            <android.support.design.widget.TabLayout
                android:clickable="true"
                android:background="#887755"
                app:layout_scrollFlags="scroll|enterAlways"
                android:id="@+id/tabs"
                app:tabMaxWidth="0dp"
                app:tabGravity="fill"
                app:tabMode="fixed"
                android:layout_width="match_parent"
                android:layout_height="wrap_content" />

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

從這個布局我們可以看出 CoordinatorLayout 包覆著 AppBarLayout 以及 ViewPager






在 ViewPager 當中可以看到一個屬性 app:layout_behavior="@string/appbar_scrolling_view_behavior"
這代表著 ViewPager 在滾動的時候會順勢將 AppBarLayout 一起往上推
就會出現我們前面展示的效果





在程式碼內我們可以看到兩個元件必須實作它們的 adpater才能運作
分別是 RecyclerView 以及 ViewPager
在 ViewPager 的部分如下

private class SamplePagerAdapter extends PagerAdapter {

    @Override
    public int getCount() {
        return 2;
    }

    @Override
    public boolean isViewFromObject(View view, Object o) {
        return o == view;
    }


    @Override
    public Object instantiateItem(ViewGroup container, int position) {
        View view = new View(MainActivity.this);
        switch(position){
            case 0:
                view = getLayoutInflater().inflate(R.layout.pager_item1,
                        container, false);
                MyAdapter myAdapter = new MyAdapter(myDataset);
                RecyclerView mList = (RecyclerView) view.findViewById(R.id.list_view);
                final LinearLayoutManager layoutManager = new LinearLayoutManager(MainActivity.this);
                layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
                mList.setLayoutManager(layoutManager);
                mList.setAdapter(myAdapter);
                break;
            case 1:
                view = getLayoutInflater().inflate(R.layout.pager_item2,
                        container, false);
                container.addView(view);
                TextView title = (TextView) view.findViewById(R.id.item_title);
                title.setText(String.valueOf(position + 1));
        }
        container.addView(view);
        return view;
    }
    @Override
    public void destroyItem(ViewGroup container, int position, Object object) {
        container.removeView((View) object);
    }
}

為了簡單的示範這個範例
因此我們在 ViewPager 內部塞了兩個頁面
透過 ViewPager 的 Adapter 其中一頁塞入了 RecyclerView
另外一個則是很單純的 View 頁面
只顯示一個2






至於 RecyclerView Adapter的部分如下

public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
   private List<String> mData;

    public class ViewHolder extends RecyclerView.ViewHolder {
        public TextView mTextView;
        public ViewHolder(View v) {
            super(v);
            mTextView = (TextView) v.findViewById(R.id.info_text);
        }
    }

    public MyAdapter(List<String> data) {
        mData = data;
    }

    @Override
    public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View v = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.recycler_view_item, parent, false);
        ViewHolder vh = new ViewHolder(v);
        return vh;
    }

    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        holder.mTextView.setText(mData.get(position));

    }

    @Override
    public int getItemCount() {
        return mData.size();
    }
}

從這邊可以看出 RecyclerView 只需要呈現出 item 的文字即可
在初始化的時候
我們就給定了 RecyclerView 的 item 數量

private void initData(){
    myDataset = new ArrayList<>();
    for(int i = 0; i < 100; i++){
        myDataset.add(i + "");
    }
}

因此在 RecyclerView 滑動的時候就會有 100 個子項目






接著我們要初始化 View

private void initView(){
    toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);

    getSupportActionBar().setDisplayHomeAsUpEnabled(true);
    getSupportActionBar().setHomeButtonEnabled(true);

    mTabs = (android.support.design.widget.TabLayout) findViewById(R.id.tabs);
    mTabs.addTab(mTabs.newTab().setText("Tab 1"));
    mTabs.addTab(mTabs.newTab().setText("Tab 2"));
    mTabs.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
        @Override
        public void onTabSelected(TabLayout.Tab tab) {
            mViewPager.setCurrentItem(tab.getPosition());
        }

        @Override
        public void onTabUnselected(TabLayout.Tab tab) {

        }

        @Override
        public void onTabReselected(TabLayout.Tab tab) {

        }
    });
    mViewPager = (ViewPager) findViewById(R.id.viewpager);
    mViewPager.setAdapter(new SamplePagerAdapter());
    mViewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(mTabs) {
        @Override
        public void onPageSelected(int position) {
            super.onPageSelected(position);
            mViewPager.setCurrentItem(position);
        }
    });
}

就可以完成我們所需要的功能
這樣就是一個簡單的 CoordinatorLayout 搭配 AppBarLayout 的範例了