仿知乎首頁學習CoordinateLayout
前言
最近一段時間經常上知乎APP看各種神回復,發現其內部的滑動動畫挺有意思,就研究了一下。并使用CoordinateLayout模仿了一下,效果如下。

index

discovery

message

userCenter
這里用到圖片及IOCN均來自于網絡搜索。
手機截取gif貌似永遠都是這樣模糊不清
有興趣的同學可以點 github 查看源碼。
綜述
CoordinateLayout是Android Design Support Library提供的一種布局方式。
**
- CoordinatorLayout is a super-powered FrameLayout
*
- CoordinatorLayout is intended for two primary use cases:
- <ol>
- <li>As a top-level application decor or chrome layout</li>
- <li>As a container for a specific interaction with one or more child views</li>
- </ol>
- *</code></pre> 
 - 查看源碼我們可以看到 CoordinateLayout繼承及ViewGroup,是一個“超級強大”的FrameLayout,FrameLayout 相信大家都很熟悉,使用也很簡單,FrameLayout可以說是讓Android布局中有了“ 層 ”的概念,那么這個CoordinateLayout又有什么神奇之處呢,下面我們就學習一下。 - Coordinate 按照字面意思理解,就是協調。它可以方便的實現布局內view協調 - 那么究竟是怎么個調節法呢,我們來看一下。 - CoordinateLayout 使用- 結合Snackbar - 關于CoordinateLayout最經典的例子就是其結合Snackbar的使用了。 - 
- <?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
 xmlns:android="
- <android.support.design.widget.FloatingActionButton -  android:id="@+id/fab"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:layout_gravity="end|bottom"
 android:layout_margin="16dp"
 android:src="@drawable/ic_done" />
 
 
</android.support.design.widget.CoordinatorLayout></code></pre> 
  
Activity
 
  
@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        findViewById(R.id.fab).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
            Snackbar.make(view,"FAB",Snackbar.LENGTH_LONG)
                    .setAction("cancel", new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            //這里的單擊事件代表點擊消除Action后的響應事件
                        }
                    })
                    .show();
        }
    });
}</code></pre> 
這里實現的效果就是如上圖中message中那樣,一個底部彈出的view。
 
  這就是所謂的協調,協調FloatingActionButton上移,不被頂部彈出的view所遮擋。
 
  這里如果沒有使用CoordinateLayout作為根布局,而是使用LinearLayout或RelativeLayout等,那么FloatingActionButton將會被底部彈出的Snackbar所遮擋。
 
  結合AppBarLayout使用
 
  說到CoordinateLayout就不得不提這個AppBarLayout,他們倆簡直就是天生一對,二者結合使用,那畫面真是太美了,想想都覺得刺激。
 
  這里看一下我們模仿首頁頂部搜索欄的代碼:
 
  
<?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/coordinatorLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".fragments.IndexFragment">
    <android.support.design.widget.AppBarLayout
        android:id="@+id/index_app_bar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/AppTheme.AppBarOverlay">
        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="@color/colorPrimary"
            app:layout_scrollFlags="scroll|enterAlways|snap">
            <ImageView
                android:id="@+id/live"
                android:layout_width="24dp"
                android:layout_height="24dp"
                android:layout_alignParentRight="true"
                android:layout_centerVertical="true"
                android:layout_marginRight="5dp"
                android:src="@drawable/live_button" />
            <RelativeLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_margin="10dp"
                android:layout_toLeftOf="@id/live"
                android:background="@color/searchmenu">
                <ImageView
                    android:id="@+id/search"
                    android:layout_width="24dp"
                    android:layout_height="24dp"
                    android:layout_centerVertical="true"
                    android:layout_marginLeft="10dp"
                    android:src="@drawable/ic_search" />
                <TextView
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_centerVertical="true"
                    android:layout_marginLeft="10dp"
                    android:layout_toRightOf="@id/search"
                    android:text="搜索話題、問題或人"
                    android:textSize="16sp" />
            </RelativeLayout>
        </RelativeLayout>
    </android.support.design.widget.AppBarLayout>
        .......
</android.support.design.widget.CoordinatorLayout>
 
  這里我們在AppBarLayout內部嵌套了一個RelativeLayout,在這個RelativeLayout中我們模仿了頂部的搜索欄的布局效果,這個很簡單。這里最核心的東西就是
 
  
app:layout_scrollFlags="scroll|enterAlways"
 
  這行代碼。什么意思呢?app:layout_scrollFlags有下面幾個值:
 
   
   -  scroll: 所有想滾動出屏幕的view都需要設置這個flag, 沒有設置這個flag的view將被固定在屏幕頂部。 
-  enterAlways: 設置這個flag時,向下的滾動都會導致該view變為可見,啟用快速“返回模式”。 
-  enterAlwaysCollapsed: 當你的視圖已經設置minHeight屬性又使用此標志時,你的視圖只能已最小高度進入,只有當滾動視圖到達頂部時才擴大到完整高度。 
-  exitUntilCollapsed: 滾動退出屏幕,最后折疊在頂端。 
-  snap: 視圖在滾動時會有一種“就近原則”,怎么說呢,就是當視圖展開時,如果滑動中展 開的內容超過視圖的75%,那么視圖依舊會保持展開;當視圖處于關閉時,如果滑動中展開的部分小于視圖的25%,那么視圖會保持關閉。總的來說,就是會讓動畫有一種彈性的視覺效果。 
這里我們使用了scroll 和 enterAlways ,就很容易的實現了向下滑動時頂部隱藏,向下滑動時頂部出現的效果。
 
  結合TabLayout使用
 
  注意,這里所說的TabLayout是android.support.design.widget.TabLayout,不是很久以前的那個TabLayout。
 
  這里我們模仿的時候,用于種種原因沒能使用TabLayout的動態效果,只是簡單的結合ViewPager使用了一下,實際開發中這個效果還是很不錯的,有興趣的同學可以自己搜一下。
 
  結合CollapsingToolbarLayout使用
 
  個人感覺,這是整個CoordinateLayout中最拉風的動畫特效,主要是實現一種“折疊”的動畫效果。我們在模仿個人中心的時候就是用到了這個功能:
 
  
<?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/appbar"
        android:layout_width="match_parent"
        android:layout_height="256dp"
        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|snap">
            <RelativeLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:background="@drawable/user_bg"
                app:layout_collapseMode="parallax">
                <de.hdodenhof.circleimageview.CircleImageView
                    android:layout_width="68dp"
                    android:layout_height="68dp"
                    android:layout_centerInParent="true"
                    android:src="@drawable/profile" />
            </RelativeLayout>
            <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.v4.widget.NestedScrollView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            android:paddingTop="10dp">
            <ImageView
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:scaleType="fitStart"
                android:src="@drawable/fake" />
        </LinearLayout>
    </android.support.v4.widget.NestedScrollView>
    <android.support.design.widget.FloatingActionButton
        android:id="@+id/btn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="16dp"
        android:clickable="true"
        android:src="@drawable/ic_edit"
        app:layout_anchor="@id/appbar"
        app:layout_anchorGravity="bottom|right|end" />
</android.support.design.widget.CoordinatorLayout>
 
   
   - 首先,我們在AppBarLayout中嵌套一個CollapsingToolbarLayout,并指定其
app:layout_scrollFlags="scroll|exitUntilCollapsed|snap"
 
  這個屬性前面介紹過了,這里三種屬性結合就可實現滾動中“折疊視差”的效果了。
 
   
   - 接下來,我們又在CollapsingToolbarLayout放置了一個RelativeLayout。這個RelativeLayout有一個很重要的設置;
app:layout_collapseMode="parallax"
 
  這個layout_collapseMode就是用來設置整個RelativeLayout的折疊效果的,有兩種取值,“pin”:固定模式,在折疊的時候最后固定在頂端;“parallax”:視差模式,在折疊的時候會有個視差折疊的效果。
 
   
   - 最后是Toolbar,可以看到Toolbar的collapseMode設置為pin,這樣向上滑動時,當RelativeLayout的內容完全折疊后,Toolbar將顯示在頂部;而向下滑動時,Toolbar將消失,而RelativeLayout的內容會動態的折疊展開,而且由于設置了snap,會有一種輕微的彈性效果。
這里需要注意,這個時候,我們需要將AppBarLayout的高度設置為固定值
 
  CoordinatorLayout 還提供了一個 layout_anchor 的屬性,連同 layout_anchorGravity 一起,可以用來放置與其他視圖關聯在一起的懸浮視圖(如 FloatingActionButton)。
 
  這里如果我們將floatingActionButton設置為:
 
  
android:layout_gravity="bottom|right|end"
 
  FloatingActionButton將位于整個屏幕的右下角。
 
  使用細節
 
  這里需要注意的是,使用AppBarLayout時,為了實現其滾動時的效果,在其下面必須有一個可滾動的View,并且需要為其設置app:layout_behavior屬性。
 
  比如我們在結合結合CollapsingToolbarLayout使用時,在AppBarLayout的下面放置了NestedScrollView,并設置app:layout_behavior="@string/appbar_scrolling_view_behavior"。
 
  而在其他頁面,我們AppBarLayout的下面放置了ViewPager或者是FrameLayout都設置了相應的屬性;具體可參考源碼。
 
  Behavior
 
  上面我們提到了layout_behavior,這是個什么意思呢?
 
  這里就不得不說這個Behavior了,可以說Behavior是整個CoordinateLayout最核心的東西。還記得我們最開始的列子嗎?FloatingActionButton會隨著Snackbar的出現,自動的調節自己的位置,這是怎樣的實現的呢?
 
  我們通過追蹤查看 Snackbar 的 show() 這個方法,最終會在Snack的源碼中找到如下實現:
 
  
final void showView() {
        if (mView.getParent() == null) {
            final ViewGroup.LayoutParams lp = mView.getLayoutParams();
            if (lp instanceof CoordinatorLayout.LayoutParams) {
                // If our LayoutParams are from a CoordinatorLayout, we'll setup our Behavior
                final CoordinatorLayout.LayoutParams clp = (CoordinatorLayout.LayoutParams) lp;
                final Behavior behavior = new Behavior();
                behavior.setStartAlphaSwipeDistance(0.1f);
                behavior.setEndAlphaSwipeDistance(0.6f);
                behavior.setSwipeDirection(SwipeDismissBehavior.SWIPE_DIRECTION_START_TO_END);
                behavior.setListener(new SwipeDismissBehavior.OnDismissListener() {
                    @Override
                    public void onDismiss(View view) {
                        view.setVisibility(View.GONE);
                        dispatchDismiss(Callback.DISMISS_EVENT_SWIPE);
                    }
                    @Override
                    public void onDragStateChanged(int state) {
                        switch (state) {
                            case SwipeDismissBehavior.STATE_DRAGGING:
                            case SwipeDismissBehavior.STATE_SETTLING:
                                // If the view is being dragged or settling, cancel the timeout
                                SnackbarManager.getInstance().cancelTimeout(mManagerCallback);
                                break;
                            case SwipeDismissBehavior.STATE_IDLE:
                                // If the view has been released and is idle, restore the timeout
                                SnackbarManager.getInstance().restoreTimeout(mManagerCallback);
                                break;
                        }
                    }
                });
                clp.setBehavior(behavior);
                // Also set the inset edge so that views can dodge the snackbar correctly
                clp.insetEdge = Gravity.BOTTOM;
            }
            mTargetParent.addView(mView);
        }
    ......
    }
 
  我們可以看到,當Snack執行show方法的時候,會生成一個Behavior,然后set給CoordinateLayout,而CoordinateLayout會根據這個Behavior執行動作。這個方法下面省略的大體上就是一個Translation屬性動畫的實現,這里就不展開來說了。
 
  回到我們之前所說,我們需要為帶有滾動屬性的view設置layout_behavior這個屬性,我們為其設置的值
 
  
app:layout_behavior="@string/appbar_scrolling_view_behavior"
 
  
<string name="appbar_scrolling_view_behavior" translatable="false">android.support.design.widget.AppBarLayout$ScrollingViewBehavior</string>
 
  我們可以在AppBarLayout的源碼中找到這個ScrollingViewBehavior,其最終也是繼承自Behavior實現了特定的效果。
 
  現在或許你有疑問,這個神秘的Behavior到底是個什么鬼?
 
  Behavior 核心概念
 
  Behavior 就是行為,他定義了View的行為。
 
  CoordinatorLayout的工作原理是搜索定義了CoordinatorLayout Behavior 的子view,不管是通過在xml中使用app:layout_behavior標簽還是通過在代碼中對view類使用@DefaultBehavior修飾符來添加注解。當滾動發生的時候,CoordinatorLayout會嘗試觸發那些聲明了依賴的子view。
 
  Behavior最核心的兩個方法是:layoutDependsOn() 和onDependentViewChanged();這兩個方法的說明如下:
 
  
public boolean layoutDependsOn(CoordinatorLayout parent, T child, View dependency) {
    boolean rs;
    //根據邏輯判斷rs的取值
    //返回false表示child不依賴dependency,ture表示依賴
    return rs;    
}
 
  
/**
* 當dependency發生改變時(位置、寬高等),執行這個函數
* 返回true表示child的位置或者是寬高要發生改變,否則就返回false
*/
@Override
public boolean onDependentViewChanged(CoordinatorLayout parent, T child, View dependency) {
     //child要執行的具體動作
        return true;
}
 
  FloatingActionButton 的Behavior
 
  我們用Android Studio查看FloatingActionButton的源碼,會發現他包含了一個Behavior的注解:
 
  
@CoordinatorLayout.DefaultBehavior(FloatingActionButton.Behavior.class)
public class FloatingActionButton extends VisibilityAwareImageButton {
.....
}
 
  這里我們看一下FloatingActionButton的注解參數FloatingActionButton.Behavior.class 是怎樣實現的。通過源碼我們發現這個FloatingActionButton的Behavior繼承自CoordinateLayout的Behavior,而且只實現了onDependentViewChanged方法,我們看一下:
 
  
public static class Behavior extends CoordinatorLayout.Behavior<FloatingActionButton> {
        private static final boolean AUTO_HIDE_DEFAULT = true;
        private Rect mTmpRect;
        private OnVisibilityChangedListener mInternalAutoHideListener;
        private boolean mAutoHideEnabled;
        public Behavior() {
            super();
            mAutoHideEnabled = AUTO_HIDE_DEFAULT;
        }
        public Behavior(Context context, AttributeSet attrs) {
            super(context, attrs);
            TypedArray a = context.obtainStyledAttributes(attrs,
                    R.styleable.FloatingActionButton_Behavior_Layout);
            mAutoHideEnabled = a.getBoolean(
                    R.styleable.FloatingActionButton_Behavior_Layout_behavior_autoHide,
                    AUTO_HIDE_DEFAULT);
            a.recycle();
        }
        @Override
        public boolean onDependentViewChanged(CoordinatorLayout parent, FloatingActionButton child,
                View dependency) {
            if (dependency instanceof AppBarLayout) {
                // If we're depending on an AppBarLayout we will show/hide it automatically
                // if the FAB is anchored to the AppBarLayout
                updateFabVisibilityForAppBarLayout(parent, (AppBarLayout) dependency, child);
            } else if (isBottomSheet(dependency)) {
                updateFabVisibilityForBottomSheet(dependency, child);
            }
            return false;
        }
    }
 
  可以看到他在onDependentViewChanged中直接判斷了當前依賴的view。我們在模仿個人中心時,設置的FloatingActionButton的dependency就是AppBarLayout。而在這個方法中,他就會根據此執行特定的操作,也就是updateFabVisibilityForAppBarLayout 這個方法中的內容。
 
  自定義Behavior
 
  好了,說了這么多,下面我們說一下自定義Behavior。我們在模仿知乎底部用于切換Fragment的Tab時,便使用了一個自定義的Behavior。
 
  BottomViewBehavior
 
  
public class BottomViewBehavior extends CoordinatorLayout.Behavior<View> {
    public BottomViewBehavior(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
    @Override
    public boolean layoutDependsOn(CoordinatorLayout parent, View child, View dependency) {
        return dependency instanceof AppBarLayout;
    }
    @Override
    public boolean onDependentViewChanged(CoordinatorLayout parent, View child, View dependency) {
        float translationY = Math.abs(dependency.getTop());
        child.setTranslationY(translationY);
        return true;
    }
}
 
  這里我們的思路很簡單,就是我們的View 要依賴于頂部的AppBarLayout,而用其距離屏幕的距離,作為底部(tab)相對于屏幕的距離,這樣當頂部的AppBarLayout 滑動出屏幕時,底部也將做相應的位移,當然這里底部tab 的高度是需要做限制的。
 
  
<LinearLayout
        android:id="@+id/bottom"
        android:layout_width="match_parent"
        android:layout_height="48dp"
        android:layout_gravity="bottom"
        android:background="@color/white"
        android:orientation="horizontal"  
      app:layout_behavior="home.smart.fly.zhihuindex.behavior.BottomViewBehavior">
        <RadioGroup
            android:id="@+id/tabs_rg"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="horizontal"
            android:paddingLeft="5dp"
            android:paddingRight="5dp">
            <RadioButton
                android:id="@+id/home_tab"
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:background="#00000000"
                android:button="@null"
                android:checked="true"
                android:drawableTop="@drawable/home_sel"
                android:gravity="center|bottom"
                android:paddingTop="5dp" />
            <RadioButton
                android:id="@+id/explore_tab"
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:background="#00000000"
                android:button="@null"
                android:drawableTop="@drawable/explore_sel"
                android:gravity="center|bottom"
                android:paddingTop="5dp" />
            <RadioButton
                android:id="@+id/notify_tab"
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:background="#00000000"
                android:button="@null"
                android:drawableTop="@drawable/notify_sel"
                android:gravity="center|bottom"
                android:paddingTop="5dp" />
            <RadioButton
                android:id="@+id/user_tab"
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="1"
                android:background="#00000000"
                android:button="@null"
                android:drawableTop="@drawable/user_sel"
                android:gravity="center|bottom"
                android:paddingTop="5dp" />
        </RadioGroup>
    </LinearLayout>
 
  我們將自定義的Behavior設置為這個bottom的app:layout_behavior就可以實現類似于知乎首頁的那種效果了。
 
  FabBehavior
 
  這里我們用到的FloatingActionButton也可以自定義Behavior。
 
  
public class FabBehavior extends CoordinatorLayout.Behavior<View> {
    private static final Interpolator INTERPOLATOR = new FastOutSlowInInterpolator();
    /**
     * 控件距離coordinatorLayout底部距離
     */
    private float viewDistance;
    private boolean aninmating;
    public FabBehavior(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
    @Override
    public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, View child, View directTargetChild, View target, int nestedScrollAxes) {
        if(child.getVisibility() == View.VISIBLE&& viewDistance ==0){
            //獲取控件距離父布局(coordinatorLayout)底部距離
            viewDistance =coordinatorLayout.getHeight()-child.getY();
        }
        return (nestedScrollAxes & ViewCompat.SCROLL_AXIS_VERTICAL) != 0;//判斷是否豎直滾動
    }
    @Override
    public void onNestedPreScroll(CoordinatorLayout coordinatorLayout, View child, View target, int dx, int dy, int[] consumed) {
        //dy大于0是向上滾動 小于0是向下滾動
        if (dy >=0&&!aninmating &&child.getVisibility()==View.VISIBLE) {
            hide(child);
        } else if (dy <0&&!aninmating &&child.getVisibility()==View.GONE) {
            show(child);
        }
    }
    private void hide(final View view) {
        ViewPropertyAnimator animator = view.animate().translationY(viewDistance).setInterpolator(INTERPOLATOR).setDuration(200);
        animator.setListener(new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animator) {
                aninmating =true;
            }
            @Override
            public void onAnimationEnd(Animator animator) {
                view.setVisibility(View.GONE);
                aninmating =false;
            }
            @Override
            public void onAnimationCancel(Animator animator) {
                show(view);
            }
            @Override
            public void onAnimationRepeat(Animator animator) {
            }
        });
        animator.start();
    }
    private void show(final View view) {
        ViewPropertyAnimator animator = view.animate().translationY(0).setInterpolator(INTERPOLATOR).setDuration(200);
        animator.setListener(new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animator) {
                view.setVisibility(View.VISIBLE);
                aninmating =true;
            }
            @Override
            public void onAnimationEnd(Animator animator) {
                aninmating =false;
            }
            @Override
            public void onAnimationCancel(Animator animator) {
                hide(view);
            }
            @Override
            public void onAnimationRepeat(Animator animator) {
            }
        });
        animator.start();
    }
}
 
  這里我們并沒有去實現layoutDependsOn() 和onDependentViewChanged()這兩個方法,因為FloatingActionButton已經實現了這兩個方法,我們這里我們從自身需求出發,就其滑動時的特性,做了一個滑動屏幕時FloatingActionButton快速從底部彈出或隱藏的Behavior。結合注釋,代碼很容易理解。
 
  好了,這就是所有關于CoordinateLayout的東西了,可以看到Behavior是這個控件的核心,也是最難理解的東西。自定義Behavior可以讓我們的滑動動畫有無限的可能。
 
  總結
 
  關于這個模仿知乎首頁的實現,最初真的只是想研究一下“首頁”是怎么實現的。結果隨著Demo的展開,加上輕微強迫癥的作祟,便成了現在這個樣子。
 
  到這里,不得不說一下,個人感覺,真正的知乎首頁應該是沒有使用CoordinateLayout;因為按現在這種Activity+n*Fragment 的套路,使用CoordinateLayout完全是給自己添亂,因為CoordinateLayout是滑動特性是無法嵌套使用的(或者說很復雜,我沒發現),當我在最外層的Activity中使用了CoordinateLayout后,內部的Fragment中再次使用CoordinateLayout時,就會發生意想不到的各種bug,所以你會發現我們模擬的個人中心是有問題的,這里就是嵌套CoordinateLayout后外部的CoordinateLayout失效了,導致底部的Behavior也失效。
 
  不過在整個模仿的過程,也算是對CoordinateLayout的一次深入了解吧,順便也對SwipeRefreshLayout的內容和Tween Animation的使用做了一次鞏固。首頁RecycleView item中仿照Toolbar的彈出菜單,真的是耗費了不少時間。
 
   
 
   
 
  來自:http://www.jianshu.com/p/a8f0a1bbc1e6