Showing posts with label CoordinatorLayout. Show all posts
Showing posts with label CoordinatorLayout. Show all posts

Sunday, December 6, 2015

讓你的view跟著CoordinatorLayout舞動

文章攢寫時間︰2015/12/06 18:37
文章更新時間︰2016/01/17 16:53
文章修改次數︰2

本篇參考來源
1. INTRODUCTION TO COORDINATOR LAYOUT ON ANDROID

一、前言

藉由前一篇的教學,
了解到官方已經用很簡單的方式就讓我們做到頁面裡元件間彼此互動。
但是,
如果在前一篇的教學裡,
我們用的不是官方的Floating Action Button(以下簡稱FAB),而是第3方的。
那麼我們又該如何實作呢?

二、文章開始
首先,
我們在引用Library時,
改由Maven從repositories(雲端倉庫)下載

在您的app專案底下、build.gradle檔裡寫下該行︰
compile 'com.getbase:floatingactionbutton:1.9.1'

此時,
就能在專案中引用第3方套件的Floating Action Buton了。 

接著,
我們將剛才的專案裡,
原本使用官方的FAB佈局改成現在第3方的︰
<!--?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">
     
    <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"
        android:src="@drawable/ic_done">
         
    <com.getbase.floatingactionbutton.FloatingActionButton>
</android.support.design.widget.CoordinatorLayout>

然後執行它。

此時,
我們發現CoordinatorLayout完全沒有任何作用。
為什麼呢?
這是由於我們的第3方FAB套件沒有實作預設的Coordinatorlayout.Behavior


●行為!一切都是行為!(Coordinatorlayout.Behavior)
是的。

為什麼Android會知道當Snacker往上彈起時,
FAB也需要跟著向上彈起呢?
因為官方的FAB實作了Behavior(行為)。

籍由CoordinatorLayout這個強大的Framework,
開發者們完全不用自己操刀去控制2個互相牽聯的view元件,
然後一邊算A view(被依賴者,在這篇文章範例裡指的是SnackbarLayout),
一邊再控制B view(依賴者,在這篇文章範例指的是第3方的FAB),
只要實作欲依賴的B view的Behavior,
就能輕鬆達到A、B兩個view的互動。

怎麼實作呢?

首先,我們需要創建一個新的類別,
並且繼承自CoordinatorLayout.Behavior

public class FloatingActionButtonBehavior extends CoordinatorLayout.Behavior<FloatingActionButton>

為了確保我們這個實作能從xml中被inflate(擴充),
需要在這個類別裡加上含有Context與AttributeSet兩個參數的建構子︰
public FloatingActionButtonBehavior(Context context, AttributeSet attrs) {}

下一步,
Override(覆寫) layoutDependsOn()函式並且回傳true,
以確保CoordinatorLayout能幫我們明確的監聽到A view(被依賴者,SnackbarLayout)的任何畫面異動。

由於我們現在的例子中,
被依賴者是A view(範例裡的SnackbarLayout元件),
因此我們將layoutDependsOn()函式覆寫如下︰
@Override
public boolean layoutDependsOn(CoordinatorLayout parent, FloatingActionButton child, View dependency) {
  return dependency instanceof SnackbarLayout;
}

意思是︰
倘若收到的dependency(依賴者)是SnackbarLayout,
那麼我們就告訴CoordinatorLayout說︰
對對對!我就是依賴著它SnackbarLayout。

再來,
我們要告訴CoordinatorLayout︰"倒底要怎麼個互動"的實作了。

因為剛才我們已經告訴CoordinatorLayout說︰
第3方的FAB元件現在要依賴SnackbarLayout。
因此,
每當CoordinatorLayout發現到SnackbarLayout有畫面異動時,
都會藉由一隻Callback(回呼函式)通知我們現在正在實作的FloatingActionButtonBehavior類別。
這個Callback為︰
onDependentViewChanged()

因為onDependentViewChanged()這個函式,
我們可以取到被依賴者︰SnackbarLayout視圖當下的任何狀態
(因為...CoordinatorLayout幫你把整個SnackbarLayout視圖都傳過來了...你還會抓不到嗎@@)

我們現在想要做岀以下這個效果,
這也是前一篇教學原本就有的效果︰

每當Snackbar向上彈起時,
我們第3方FAB元件也能跟著向上彈起。

為了做到這個效果,
我們需要跟著Snackbar現在的Y值去位移第3方FAB元件的Y值,
簡單來說,
就是Snackbar現在彈多高、FAB就彈多高的意思啦!

依照官方文件的說明,
實作onDependentViewChanged()這個函式,
我們一樣要回傳true才能發揮作用。
@Override
public boolean onDependentViewChanged(CoordinatorLayout parent, FloatingActionButton child, View dependency) {
  float translationY = Math.min(0, dependency.getTranslationY() - dependency.getHeight());
  child.setTranslationY(translationY);
  return true;
}

這段Code的意思是︰每當被依賴者SnackBar一旦移動了多少Y值(高度),就將第3方FAB也跟著移動多少Y值。

這樣子我們就實作完了Behavior要的2個基本Callback(回呼函式)
layoutDependsOn()和onDependentViewChanged(),以及一個含有AttributeSet的建構子了。

剩下最後一步...
現在我們已經將Behavior實作完了,
接下來就只剩下︰
告訴CoordinatorLayout我們的第3方FAB有實作你要的Behavior,
請你幫我收下並做岀我要的效果!

因此,
我們將xml裡,第3方的FAB元件加上一行屬性
app:layout_behavior="com.simon.hellocoordinatorlayout.FloatingActionButtonBehavior"

整頁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:layout_width="match_parent"
    android:layout_height="match_parent">
     
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="右下角是第3方套件的FAB按鈕,該專案同時實作了CoordinatorLayout.Behivor"/>

    <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"
        app:layout_behavior="com.simon.hellocoordinatorlayout.FloatingActionButtonBehavior"/>
         
</android.support.design.widget.CoordinatorLayout>

差不多就是這個樣子了,
為了證明這整篇教學沒有在唬爛,
底下這是執行後的畫面︰
如果您想要使用預設的Behavior,
只需要在您的Behavior類別上,
加上DefaultBehavior這個Anntation即可。


三、總結

藉由實作CoordinatorLayout.Behavior,
我們讓 第3方FAB元件 與 SnackBar 達到了 互 動 效果。

那...如果今天有一個專案需求是︰
當列表滾動時,
上方的工具列要隱藏,
又要怎麼做?
誰是依賴者?誰又是被依賴者?

待續...XD

四、其它

附上本篇教學的原始碼

Wednesday, September 16, 2015

CoordinatorLayout初步認識

文章攢寫時間︰2015/09/16 18:37
文章更新時間︰2016/01/17 16:53
文章更新次數︰4

本篇參考來源

1. INTRODUCTION TO COORDINATOR LAYOUT ON ANDROID

一、前言

2015年的Google I/O大會上,
Google介紹了有關於Android Design Support Library,
該套件讓開發者們能更方便的使用Material Design(實感設計,或譯材料設計),
而且也能在API level 7(Android 2.1)或以上的Android版本兼容。
相關資訊可以參考Android Developers Blog


二、文章開始

Android Design Support Library有很多好用的Material Design元件,
其中最有趣的是官方宣稱一個"超強大"的FrameLayout,
名為CoordinatorLayout
就如同這個名字所言,
這個強大的Layout擁有"依據Layout底下一個View的位置變化,
進而讓其它子View也跟著位移"的能力。

使用這個CoordinatorLayout的方式只有一個,
就是將子View放進CoordinatorLayout的子階層(就像您使用FrameLayout那樣,將TextView放進FrameLayout裡)。

接下來要展示的這個範例相當簡單,
一個Floating Action Buton觸發Snackbar展開連動關係。

首先我們要做的是 - 將Support Design Library放入Gradle中︰
compile 'com.android.support:design:22.2.0'

再來,
替activity建立一個簡單的Layout︰
<!--?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.FloatingActionButton>
</android.support.design.widget.CoordinatorLayout>

接著,
攢寫activity。
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();
      }
    });
  }
}

做完的結果如下︰

由上圖可看到︰
當Snackbar(下方突然岀現的黑色bar)岀現時,
Floating Action Buton(綠色勾勾)就會跟著往上移動。

很酷,對吧?

註︰官方總是喜歡用簡單幾行code(就像Hello World一樣)吸引開發者們嚐鮮,然後⋯你懂的。

但如果今天你有客製化的元件想要也跟著位移,
又該怎麼實作?
跟著位移的原理又是什麼?

請各位看倌們接著看下一篇教學︰
讓你的view跟著CoordinatorLayout舞動

如需本篇教學原始碼,
請至Github下載

相關文章

1. Android 嵌套滑动机制(NestedScrolling)
2. CoordinatorLayout与滚动的处理
3. Android NestedScrolling 实战
4. Android Developers Blog