Android CoordinatorLayout 入門介紹
在 2015
年的 I/O
開發者大會上,Google
介紹了一個新的 Android Design Support Library
,該庫可以幫助開發者在應用上使用 meterial design
。它包含了許多重要的 meterial design
的構建塊,並且它支持 API 7
及以上的版本。如果你錯過了這次大會,那就請打開谷歌開發者站點來查閱它的相關信息吧:傳送門。
CoordinatorLayout
在庫中所有好的東東之間,看起來真正有趣的是 CoordinatorLayout
,它是一個 FrameLayout
。從它的名字中,你或許已經猜到:該布局的強大在於,能夠協調子元素之間的依賴關系。
你需要做的就是把 View
包含在 CoordinatorLayout
中。讓我們直接進入代碼吧。下面的例子非常簡單,它包含了 Floating Action Button
,點擊時會觸發一個 Snackbar
。
首先,在 gradle
文件中引入 meterial design
庫:
compile 'com.android.support:design:22.2.0'
接下來,為 Activity
創建一個簡單的布局文件:
<?xml version="1.0" encoding="utf-8"?> <android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <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>
還需要添加 MainActivity
:
public class MainActivity extends AppCompatActivity { @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, "Hello Snackbar", Snackbar.LENGTH_LONG).show(); } }); } }

非常酷,是嗎?
但是,如果你想使用其它 FAB
的實現又會怎么樣呢?因為 Support Library
中的 FAB
實現沒有菜單選項,於是,我們嘗試一下由開發者 Base
實現的 FAB
開源庫。
compile 'com.getbase:floatingactionbutton:1.9.1'
<?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"> <com.getbase.floatingactionbutton.FloatingActionButton android:id="@+id/fab" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="end|bottom" android:layout_margin="16dp" app:fab_icon="@drawable/ic_done" /> </android.support.design.widget.CoordinatorLayout>

如圖所示,在這種情況下,CoordinatorLayout
不能正常工作。這是因為 View
沒有默認的CoordinatorLayout.Behavior
的實現。現有的解決方案就是等待有人來完善它。
或者呢,我們可以為這個組件寫一個自定義的行為實現。:D
View 知道如何表現
這個框架真的非常強大,要給 view
自定義行為時,你根本不需要獲取這個 view
。你還可以改變任意 view
的默認行為。
首先,需要繼承 Behavior
類:
public class FloatingActionButtonBehavior extends CoordinatorLayout.Behavior<FloatingActionButton>
為了使這個類可以填充 xml
中的內容,我們需要給它設置一個構造方法,方法有兩個參數:Context
和AttributeSet
。
public FloatingActionButtonBehavior(Context context, AttributeSet attrs) {}
接下來的步驟是重寫 layoutDependsOn()
方法,並且,如果我們想監聽改變,就讓方法返回 true
。在例子中,我們只想監聽 Snackbar
對象的改變。
@Override public boolean layoutDependsOn(CoordinatorLayout parent, FloatingActionButton child, View dependency) { return dependency instanceof SnackbarLayout; }
現在,讓我們繼承真正行為的實現。當 CoordinatorLayout
中的 view
每次發生變化時,onDependentViewChanged
方法都會被調用。在這個方法中,我們要讀取當前 Snackbar
的狀態。當Snackbar
顯示的時候,我們想把 FAB
也移上來。要實現這樣的目的,我們需要把 FAB
的 Y
坐標設置為Snackbar
的高度。要得到正確的轉換值,我們需要從轉化的 Y
值中減去 Snackbar
的高度。
@Override public boolean onDependentViewChanged(CoordinatorLayout parent, FloatingActionButton child, View dependency) { float translationY = Math.min(0, dependency.getTranslationY() - dependency.getHeight()); child.setTranslationY(translationY); return true; }
最后一步就是告訴 CoordinatorLayout
使用 FloatingActionButtonBeahvior
:
<?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"> <com.getbase.floatingactionbutton.FloatingActionButton android:id="@+id/fab" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="end|bottom" android:layout_margin="16dp" app:layout_behavior="com.getbase.coordinatorlayoutdemo.FloatingActionButtonBehavior" app:fab_icon="@drawable/ic_done" /> </android.support.design.widget.CoordinatorLayout>
最終,問題被修正了:

如果你想為 view
定義默認行為,只需要在你的 Behavior
類上添加 DefaultBehavior
注解就可以了。
以上代碼的 GitHub
地址為:https://github.com/ggajews/coordinatorlayoutwithfabdemo 。
祝大家編碼愉快!