使用CoordinatorLayout打造知乎界面

這兩天在學習com.android.support:design類庫的使用,也算有些小心得。就想打造一個類似于知乎的上滑隱藏、下滑加載Toolbar和TabLayout的界面布局。用起來體驗還是很不錯的。
中間呢也借鑒了不少大神的博客。比如:
http://www.lxweimin.com/p/488283f74e69
http://androidwing.net/index.php/70
程序運行效果如下:

aa.gif

當然了,實際操作領悟還要全靠自己。那么今天,我就把大家帶進門。
1.知乎首頁是一個Activity和多個Fragment。底部導航欄和頂部Toolbar在Activity的布局中。
2.除了第一個Fragment,其余的Toolbar全部隱藏掉,換成Fragment的自身的頂部導航欄。

那么我們今天主要就是完成Activity的布局效果。
首先我們先看布局文件。我一點一點的貼,一點一點的講,免得一大片代碼讓大家煩躁。而且,我覺得難就難在可能大家對這些新的東西的屬性和API不熟悉。慢慢來

//最外層的布局,CoordinatorLayout就是我們用來協調它的各種子View
<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.sg.zhidemo.MainActivity">

之后呢,我添加了一個FrameLayout,用來替換Fragment的

<FrameLayout    android:id="@+id/main_center_fl"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    //這里要說的。如果沒有這個屬性,FrameLayout或者Fragment就會在Toolbar的下面,而如果用了這個屬性,就會根據appbar的大小來協調自身的位置
    app:layout_behavior="@string/appbar_scrolling_view_behavior">
</FrameLayout>

接下來就是頂部的AppBar了,其實他就是一個可以將各種玩意和Toolbar組合到一起使用的一個容器而已。如果這里不愿意寫的話呢,可以直接去new Moudle,創建一個ScrollViewActivity,內容大同小異

<android.support.design.widget.AppBarLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:theme="@style/AppTheme.AppBarOverlay">
        <android.support.v7.widget.Toolbar
            android:id="@+id/main_toolbar"
            android:layout_width="match_parent"
//這個barSize是Google建議的高度,是56dp
            android:layout_height="?attr/actionBarSize" 
            android:background="?attr/colorPrimary"
//前兩個屬性我就不說了,一會給大家推薦文章有,snap就是具有彈性的感覺,自己體會··
            app:layout_scrollFlags="scroll|enterAlways|snap">
//這里我就是懶省事,隨便寫的ET
            <EditText
                android:background="@drawable/shape"
                android:hint="搜索話題。。。"
                android:layout_width="wrap_content"
                android:layout_height="42dp" />
        </android.support.v7.widget.Toolbar>
</android.support.design.widget.AppBarLayout>

然后是底部導航欄

//用CardView包裹更好看了····
<android.support.v7.widget.CardView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
//設置位置和高度
    android:layout_gravity="bottom"
    app:cardElevation="8dp"
//這里是重點,這里我們使用了自定義的行為。也是著重要寫的地方。稍后講
    app:layout_behavior="com.sg.zhidemo.FooterBehavior">
    <android.support.design.widget.TabLayout
        android:id="@+id/main_bottom_tab"
        android:layout_width="match_parent"
        android:layout_height="66dp"
//去掉指示器
        app:tabIndicatorColor="@null" />
</android.support.v7.widget.CardView>

最后是一個懸浮的FAB

<android.support.design.widget.FloatingActionButton
    android:id="@+id/fab"    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="right|bottom"
    android:layout_marginBottom="80dp"
    android:layout_marginRight="30dp"
    android:src="@android:drawable/ic_dialog_email"
//用到了和上面一樣的自定義行為,都是用來協調滑動事件的
    app:layout_behavior="com.sg.zhidemo.FooterBehavior" />

布局就這么寫完了。是不是也沒有什么難的啊。。
MainActivity中無非就是尋找控件,設置點擊事件來切換Fragment,我就不寫了,這里我們著重看一下FooterBehavior。
再看之前,我還想說以下,一共有兩種Behavior。
一種是:Aview依賴Bview,在Bview移動的時候,Aview可以獲取到B的一些屬性和數據,同時調整自身的屬性。
另外一種呢就是我們要寫的這種,當布局中有滑動事件發生的時候,會通知注冊的View,是否要去處理自身的一些方法。怎么注冊呢,就是靠app:layout_behavior="com.sg.zhidemo.FooterBehavior"這種行為來注冊。

來,接下來我直接把整個代碼貼出來(摘自 簡明的博客)

//Behavior這個類就是用來協調我們的行為的。
public class FooterBehavior extends CoordinatorLayout.Behavior<View> {
    private static final Interpolator INTERPOLATOR = new FastOutSlowInInterpolator();
    private float viewY;//控件距離coordinatorLayout底部距離
    private boolean isAnimate;//動畫是否在進行
    public FooterBehavior(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
//coordinatorLayout中有滾動發生的時候會回調該方法。我們可以在該方法中獲取到滾動的方向,可以獲取到注冊該行為的view,也就是child。大家一定要Ctrl+q看看英文的文檔介紹。
    @Override
    public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, View child, View directTargetChild, View target, int nestedScrollAxes) {
        //在第一次進入的時候獲取到控件距離父布局(coordinatorLayout)底部距離。根據這個控件到底部的距離,使用插值器,來做顯示隱藏的動畫。
        if(child.getVisibility() == View.VISIBLE && viewY==0){
            viewY=coordinatorLayout.getHeight()-child.getY();
        } 
       return nestedScrollAxes == ViewCompat.SCROLL_AXIS_VERTICAL;//判斷是否豎直滾動
    }
   @Override
    public void onNestedPreScroll(CoordinatorLayout coordinatorLayout, View child, View target, int dx, int dy, int[] consumed) {
        //手指向上移動,屏幕內容上移dy>0,手指下移dy<0
        if (dy >=0 && !isAnimate && child.getVisibility()==View.VISIBLE) {
            //hide和show的代碼我就不寫了,無非就是調用動畫來顯示隱藏控件(雖然我感覺動畫的代碼才是最難的··)
            hide(child);
        } else if (dy <0 && !isAnimate && child.getVisibility()==View.GONE) {
            show(child);
        }
    }
}

這樣就結束了。
我推薦如果是想寫滾動下移上移,最好自定義一個FooterBehavior或者是HeaderBehavior。如果是Aview依賴BView最好使用比例去依賴,而不要根據具體的值去依賴。
同時給大家推薦幾篇好的文章。
本文基本就是搬運簡明的博客,只不過他用的是單個Activity。我改了一下
http://www.lxweimin.com/p/488283f74e69
這個也是大神啊,不過Demo跑起來卡
http://androidwing.net/index.php/70
還有徐宜生大神的這個,建議不會的跟著代碼走一遍,收貨頗多,超級值
http://blog.csdn.net/eclipsexys/article/details/46349721
Github地址:https://github.com/SshiGguang/SGUi
第一次用Git···

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 173,116評論 25 708
  • RandomAccessFile 隨機讀取文件內容 構造方法 RandomAccessiFile raf=new ...
    HAHAYA閱讀 500評論 0 0
  • 美好的一天從感恩開始:我感恩生命的富足美好!讓我可以自由的生活。我感恩健康!讓我可以無憂的生活。我感恩老公辛勞打拼...
    淘淘的簡書閱讀 189評論 1 0
  • 玩彩是一場華麗的遠行,只有提高功底,才會走的更遠。今天繼續前行。 好運彩吧3D第173期分析: 獨膽:5 兩碼:5...
    金穗賓館好運彩吧閱讀 192評論 0 0