Material Design 控件知識梳理(4) FloatingActionButton

1、概述

今天,咱們介紹一個比較簡單的控件:FloatingActionButton,相信你們必定都聽過也在網上見過相似的例子,咱們就分爲三個部分介紹一下FloatingActionButton的相關知識:android

  • Fab的基礎使用
  • Fab和其它MD控件的組合
  • 經過自定義FloatingActionButton.Behavior,讓Fab根據列表的狀態顯示和隱藏

2、Fab的基礎使用

Fab本質上實際上是一個ImageButton,只是它在ImageButton的基礎上增長了一些屬性,這裏介紹幾個經常使用的屬性:bash

展示屬性

  • android:srcFab的圖片,這實際上是ImageView的屬性。
  • app:backgroundTintFab的背景色,若是沒有設置,那麼會取theme中的colorAccent做爲背景色。
  • app:fabSizeFab的大小,可選的值包括:
  • mini
  • normal
  • automininormal都預設了固定的大小,而auto屬性則會根據屏幕的寬度來設置,在小屏幕上使用mini,而在大屏幕上使用normal,固然咱們也能夠直接經過layout_width/layout_height來指定。
  • app:elevationFabZ軸方向的距離,也就是深度。
  • app:borderWidthFab邊界的寬度,邊界的顏色會比背景色稍淡,以下圖所示

點擊屬性

  • app:pressedTranslationZ:點擊時FabZ軸的變化值。
  • app:rippleColor:點擊時水波紋擴散的顏色。

3、與其它MD控件結合使用

3.1 和AppBarLayout聯動

經過給Fab設置app:layout_anchorlayout_anchorGravity兩個屬性,可讓Fab跟隨AppBarLayout移動,並在合適的時候隱藏,下面是咱們的佈局:app

<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"
    tools:context="com.demo.lizejun.repotransition.FABActivity">
    <android.support.design.widget.AppBarLayout
        android:id="@+id/al_title"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <ImageView
            android:id="@+id/iv_title"
            android:src="@drawable/ic_bg"
            android:layout_width="match_parent"
            android:scaleType="centerCrop"
            android:layout_height="150dp"
            app:layout_scrollFlags="scroll"/>
    </android.support.design.widget.AppBarLayout>
    <android.support.v7.widget.RecyclerView
        android:id="@+id/rv_content"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior"/>
    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@android:drawable/ic_btn_speak_now"
        android:layout_margin="10dp"
        app:backgroundTint="@color/colorPrimary"
        app:layout_anchor="@id/al_title" 
        app:layout_anchorGravity="bottom|end"/>
</android.support.design.widget.CoordinatorLayout>
複製代碼

當咱們滾動佈局的時候,Fab會跟着AppBarLayout先上移,而後消失: ide

3.2 和BottomSheet聯動

AppBarLayout相似,咱們也能夠經過設置layout_anchor的方法讓FabBottomSheet聯動:函數

<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"
    tools:context="com.demo.lizejun.repotransition.FABActivity">
    <android.support.design.widget.AppBarLayout
        android:id="@+id/al_title"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <ImageView
            android:id="@+id/iv_title"
            android:src="@drawable/ic_bg"
            android:layout_width="match_parent"
            android:scaleType="centerCrop"
            android:layout_height="150dp"
            app:layout_scrollFlags="scroll"/>
    </android.support.design.widget.AppBarLayout>
    <android.support.v7.widget.RecyclerView
        android:id="@+id/rv_content"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior"/>
    <include android:id="@+id/bottom_sheet" layout="@layout/layout_bottom_sheet_linear"/>
    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@android:drawable/ic_btn_speak_now"
        android:layout_margin="10dp"
        app:backgroundTint="@color/colorPrimary"
        app:layout_anchor="@id/bottom_sheet"
        app:layout_anchorGravity="end"/>
</android.support.design.widget.CoordinatorLayout>
複製代碼

這裏,咱們把layout_anchor設爲bottom_sheet佈局

3.3 和Snackbar聯動

須要和Snackbar聯動時,不須要Fab設置layout_anchor,而是須要在Snackbar展示的時候,第一個參數傳入的是CoordinatorLayoutui

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_fab);
        initView();
        mRootView = (CoordinatorLayout) findViewById(R.id.cl_root);
        mFab = (FloatingActionButton) findViewById(R.id.fab);
        mFab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //這裏須要傳入CoordinatorLayout
                Snackbar.make(mRootView, "點擊Fab", Snackbar.LENGTH_LONG).show();
            }
        });

    }
複製代碼

下面是展示的效果: spa

4、Fab根據列表的狀態顯示或隱藏

Fab的內部,定義了一個Behavior,咱們能夠經過繼承這個Behavior來監聽CoordinatorLayout內佈局的變化,以實現Fab的顯示和隱藏,首先看咱們的佈局:code

<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/cl_root"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.demo.lizejun.repotransition.FABActivity">
    <android.support.v7.widget.RecyclerView
        android:id="@+id/rv_content"
        android:tag="rv_content"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior"/>
    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@android:drawable/ic_btn_speak_now"
        android:layout_margin="10dp"
        android:layout_gravity="bottom|end"
        app:backgroundTint="@color/colorPrimary"
        app:layout_behavior="com.demo.lizejun.repotransition.behavior.FabListBehavior"/>
</android.support.design.widget.CoordinatorLayout>
複製代碼

咱們的根佈局是一個CoordinatorLayoutRecyclerViewFab是它的兩個子ViewFab位於CoordinatorLayout的右下角,注意到,這裏咱們給Fab設置了一個自定義的Behavior,正是經過這個behaviorFab能夠監聽到CoordinatorLayout內佈局的滾動狀況,下面是咱們的Behaviororm

public class FabListBehavior extends FloatingActionButton.Behavior {

    private static final int MIN_CHANGED_DISTANCE = 30;

    public FabListBehavior(Context context, AttributeSet attributeSet) {
        super(context, attributeSet);
    }

    @Override
    public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, FloatingActionButton child, View directTargetChild, View target, int nestedScrollAxes) {
        return true;
    }

    @Override
    public void onNestedScroll(CoordinatorLayout coordinatorLayout, FloatingActionButton child, View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed) {
        super.onNestedScroll(coordinatorLayout, child, target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed);
        if (dyConsumed > MIN_CHANGED_DISTANCE) {
            createValueAnimator(coordinatorLayout, child, false).start();
        } else if (dyConsumed < -MIN_CHANGED_DISTANCE) {
            createValueAnimator(coordinatorLayout, child, true).start();
        }
    }

    private Animator createValueAnimator(CoordinatorLayout coordinatorLayout, final View fab, boolean dismiss) {
        int distanceToDismiss = coordinatorLayout.getBottom() - fab.getBottom() + fab.getHeight();
        int end = dismiss ? 0 : distanceToDismiss;
        float start = fab.getTranslationY();
        ValueAnimator animator = ValueAnimator.ofFloat(start, end);
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                fab.setTranslationY((Float) animation.getAnimatedValue());
            }
        });
        return animator;
    }

}
複製代碼

這裏,咱們繼承於FloatingActionButton.Behavior來實現本身的Behavior,注意,必需要聲明構造函數爲FabListBehavior(Context, AttributeSet),並調用super()方法,不然會沒法實例化:

  • onStartNestedScroll決定了以後是否須要回調onNestedScroll,這裏咱們直接返回true
  • onNestedScroll:咱們根據dyConsumed的正負值來判斷列表滾動的方法,而後經過改變FabtranslationY來讓它移入或者移出屏幕。

5、總結

這篇文章,介紹了Fab的基本用法、其它MD控件的聯動以及如何自定義FloatingActionButtonBehavior


更多文章,歡迎訪問個人 Android 知識梳理系列:

相關文章
相關標籤/搜索