12/08/2018, 16:06

CoordinatorLayout in Android

Tại sự kiện Google I/O 2015 thì Google đã ra mắt support library mới được tích hợp sẵn các tính năng liên quan đến Material Design. Trong những thành phần đó thì bạn có thể nhìn thấy các ViewGroup mới như là CoordinatorLayout, AppbarLayout và CollapsingToolbarLayout. Giống như tên gọi của nó, ...

Tại sự kiện Google I/O 2015 thì Google đã ra mắt support library mới được tích hợp sẵn các tính năng liên quan đến Material Design. Trong những thành phần đó thì bạn có thể nhìn thấy các ViewGroup mới như là CoordinatorLayout, AppbarLayout và CollapsingToolbarLayout.

Giống như tên gọi của nó, CoordinatorLayout là một ViewGroup dùng để dịch chuyển vị trí của các view chứ bên tỏng nó.

Chúng ta cùng xem xét bức ảnh sau:

Trong ví dụ này thì bạn có thể thấy các mà các view dịch chuyển tưương đối với nhau. Chúng ta có thể thấy được cách mà các view phụ thuộc nhau như thế nào.

Dười đây là cấu trúc đơn giản nhất sử dụng CoordinatorLayout:

<?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_awidth="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/background_light"
    android:fitsSystemWindows="true"
    >

    <android.support.design.widget.AppBarLayout
        android:id="@+id/main.appbar"
        android:layout_awidth="match_parent"
        android:layout_height="300dp"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
        android:fitsSystemWindows="true"
        >

        <android.support.design.widget.CollapsingToolbarLayout
            android:id="@+id/main.collapsing"
            android:layout_awidth="match_parent"
            android:layout_height="match_parent"
            app:layout_scrollFlags="scroll|exitUntilCollapsed"
            android:fitsSystemWindows="true"
            app:contentScrim="?attr/colorPrimary"
            app:expandedTitleMarginStart="48dp"
            app:expandedTitleMarginEnd="64dp"
            >

            <ImageView
                android:id="@+id/main.backdrop"
                android:layout_awidth="match_parent"
                android:layout_height="match_parent"
                android:scaleType="centerCrop"
                android:fitsSystemWindows="true"
                android:src="@drawable/material_flat"
                app:layout_collapseMode="parallax"
                />

            <android.support.v7.widget.Toolbar
                android:id="@+id/main.toolbar"
                android:layout_awidth="match_parent"
                android:layout_height="?attr/actionBarSize"
                app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
                app:layout_collapseMode="pin"
                />
        </android.support.design.widget.CollapsingToolbarLayout>
    </android.support.design.widget.AppBarLayout>

    <android.support.v4.widget.NestedScrollView
        android:layout_awidth="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior"
        >

        <TextView
            android:layout_awidth="match_parent"
            android:layout_height="wrap_content"
            android:textSize="20sp"
            android:lineSpacingExtra="8dp"
            android:text="@string/lorem"
            android:padding="@dimen/activity_horizontal_margin"
            />
    </android.support.v4.widget.NestedScrollView>

    <android.support.design.widget.FloatingActionButton
        android:layout_height="wrap_content"
        android:layout_awidth="wrap_content"
        android:layout_margin="@dimen/activity_horizontal_margin"
        android:src="@drawable/ic_comment_24dp"
        app:layout_anchor="@id/main.appbar"
        app:layout_anchorGravity="bottom|right|end"
        />
</android.support.design.widget.CoordinatorLayout>

Chúng ta cùng xem xét những thành phần chính của layout này. Trường hợp này thì CoordinatorLayout có duy nhất ba View con là một AppbarLayout, một Scrolleable view và một FloatingActionButton.

<CoordinatorLayout>
    <AppbarLayout>
        <CollapsingToolbarLayout
            app:layout_scrollFlags="scroll|exitUntilCollapsed"
        />
    </AppbarLayout>
    <NestedScrollView
        app:layout_behavior="@string/appbar_scrolling_view_behavior"
    />
    <FloatingActionButton/>
</CoordinatorLayout>

Các bạn hãy chú ý đến hai param app:layout_scrollFlags và app:layout_behavior. Trong đó thì:

  • app:layout_scrollFlags: định nghĩa các flag mà AppBarLayout sẽ scroll. Các giá trị của param này mình sẽ nói ở phần AppBarLayout.
  • app:layout_behavior: là param của thành phần còn lại trong CoordinatorLayout. Thường được khai báo với giá trị app:layout_behavior="@string/appbar_scrolling_view_behavior"

Về cơ bản thì AppBarLayout là một vertical LinearLayout có cài đặt sẵn một số tính năng của app bar trong material design khi nó được scroll.

<AppBarLayout>
    <CollapsingToolbarLayout
        app:layout_scrollFlags="scroll|snap"
        />

    <Toolbar
        app:layout_scrollFlags="scroll|snap"
        />

    <LinearLayout
        android:id="+id/title_container"
        app:layout_scrollFlags="scroll|enterAlways"
        />

    <TabLayout />  
</AppBarLayout>

AppBarLayout trong trường hợp này là view màu xanh lam, được đặt ngay dưới collapsing image. Nó có chứa một Toolbar một LinearLayout với một title và subtitle và một TabLayout với vài tab.

Chúng ta có thể quản lý hành vì của con trực tiếp của AppBarLayout với param layout_scroolFlags. Giá trị scroll có mặt ở hầu hết các view. Nếu nó không được định nghĩa ở view con nào thì các view con đó của AppBarLayout sẽ giữ nguyên vị trí và cho phép nội dung scrollable scroll phía sau nó.

Với giá trị snap, chúng ta tránh rơi vào mid-animation-states, nó có nghĩa là các chuyển động sẽ luôn ẩn hoặc hiện toàn bộ chiều cao của view thay chỉ ẩn hiện một phần.

LinearLayout có chứa title và subTitle sẽ hiện ngay khi mà user cuộn lên nhờ giá trị enterAlways, và TabLayout thì luôn hiện vì chúng ta không gắn flag nào cho nó.

Như bạn có thể thấy thì công dụng của AppBarLayout là nhờ sắp xếp các flag scroll khác nhau với các view.

Sau đây là các các flag của AppBarLayout theo Google Docs Tuy nhiên để chắc chắn thì bạn cần đảm bảo có chạy thử demo để hiểu rõ về các flag nhất có thể.

  • SCROLL_FLAG_ENTER_ALWAYS: View sẽ xuất hiện ngay khi bạn bắt đầu scroll lên.

  • SCROLL_FLAG_ENTER_ALWAYS_COLLAPSED: Một flag bổ xung cho enterAlways và view sẽ chỉ xuất hiện cho đến khi bạn scroll lên hết mức có thể..

  • SCROLL_FLAG_EXIT_UNTIL_COLLAPSED: Khi scroll xuống thì view sẽ scroll đến khi nó đã thu gọn.

  • SCROLL_FLAG_SCROLL: View sẽ scroll cùng chiều với cả hướng bạn scroll.

  • SCROLL_FLAG_SNAP: Khi bạn scroll và kích thước của view bị thay đổi. Nếu scroll dừng và kích thước mới của view nhỏ hơn (<) 50% so với kích thước gốc thì view sẽ bị ẩn đi. Mặt khác nếu kích thước mới của view lớn hơn (>) 50% so với kích thước gốc thì view sẽ hiển thị hoàn toàn. Áp dụng cho cả scroll lên và xuống.

CollapsingToolbarLayout là bao ngoài cho Toolbar mà đã cài đặt sẵn collapsing app bar, dùng để làm con trực tiếp của AppBarLayout.

CollapsingToolbarLayoutcó hai chức năng chính như sau:

  • Parallax scrolling children: Các view con có thể scroll theo AppBarLayout. Khai báo với param app:layout_collapseMode="parallax".

  • Pinned position children: Các view con đứng im khi mà AppBarLayout scroll. Khai báo với param app:layout_collapseMode="pin".

Dựa trên ba ViewGroup mà mình vừa giới thiệu thì các bạn hoàn toàn có thể tạo ra các View mang phong cách material design linh động và đẹp nhất.

http://saulmm.github.io/mastering-coordinator https://guides.codepath.com/android/Handling-Scrolls-with-CoordinatorLayout https://stackoverflow.com/questions/35286582/material-design-layout-scrollflags-meanings

0