1. 程式人生 > >FloatingActionButton實現 展開/摺疊 的多級懸浮選單

FloatingActionButton實現 展開/摺疊 的多級懸浮選單

雖然類似這樣效果的庫網上現在已經有一大堆了,甚至寫的比較完美那我為什麼還是要去實現呢?理由也很簡單:只有自己嘗試著去實現才能體會其中的奧妙 ,才能學習到新的知識這樣當你在遇到自己陌生的東西就能從容的解決了。

一:萬年必放效果圖(沒效果圖鬼知道你寫的是啥…)

這裡寫圖片描述

二:使用詳情

三:總體的實現思路

繼承RelativeLayout 並往裡面新增要展示的選單按鈕,預設不展示的時候將其設定為隱藏狀態。剩下的重點就是將隱藏的選單展示出來,這裡我通過ObjectAnimator(屬性動畫)實現位移動畫(如果還沒了解過的童鞋可以網上搜一搜資料ObjectAnimator)、摺疊時同樣使用位移動畫只需將座標反轉一下即可。

四:為了支援更高的擴充套件性,供使用者自定義每個選單按鈕的動畫在這裡添加了一個動畫管理者(AnimationManager)只需要繼承並實現所有的抽象方即可

public abstract class AnimationManager {

    public SuspensionFab fabView;

    public AnimationManager(SuspensionFab fabView) {
        this.fabView = fabView;
    }

    /**
     * 給按鈕新增自定義動畫
     * 展開動畫
     *
     * @param
fab 按鈕 * @param orientation 展開的方向 */
public abstract void openAnimation(FloatingActionButton fab, ExpandOrientation orientation); /** * 給按鈕新增自定義動畫 * 摺疊動畫 * * @param fab 按鈕 * @param orientation 展開的方向 */ public abstract void closeAnimation
(FloatingActionButton fab, ExpandOrientation orientation); /** * 給預設按鈕新增自定義動畫 * * @param fab 按鈕 * @param orientation 展開的方向 * @param currentState true 為展開狀態|false為摺疊狀態 */ public abstract void defaultFabAnimation(FloatingActionButton fab, ExpandOrientation orientation, boolean currentState); }

只需要在動畫執行的時候呼叫manager中的方法,如下程式碼:

 private void openAnimate() {
   if (animationManager != null) {
            animationManager.defaultFabAnimation(getFabFromTag(defaultTag), ExpandOrientation.getEnum(orientation), currentState);
        }

    //....
    //去除第一個預設的按鈕
    for (int i = getChildCount() - 1; i > 0; i--) {
      FloatingActionButton view = (FloatingActionButton) getChildAt(i - 1);
      if (animationManager != null)
          animationManager.openAnimation(view, ExpandOrientation.getEnum(orientation));//每一個view的動畫,提供給使用者自定義
 }

五:這裡對選單展開的方向使用了列舉來來定義 ExpandOrientation,之前對列舉也是一臉矇蔽現在用著用著也就會了、在實際運用中也是非常的爽 ^_^。

public enum ExpandOrientation {
    /**
     * 按鈕的上邊
     */
    FAB_TOP(1),
    /**
     * 按鈕的下邊
     */
    FAB_BOTTOM(2),
    /**
     * 按鈕的左邊
     */
    FAB_LEFT(3),
    /**
     * 按鈕的右邊
     */
    FAB_RIGHT(4);
    ExpandOrientation(int value) {
        this.value = value;
    }
    private int value = 0;
    /**
     * 根據狀態值獲取列舉值
     *
     * @param value 值
     * @return ExpandOrientation
     */
    public static ExpandOrientation getEnum(int value) {
        if (value == FAB_TOP.getValue()) {
            return ExpandOrientation.FAB_TOP;
        } else if (value == FAB_BOTTOM.getValue()) {
            return ExpandOrientation.FAB_BOTTOM;
        } else if (value == FAB_LEFT.getValue()) {
            return ExpandOrientation.FAB_LEFT;
        } else if (value == FAB_RIGHT.getValue()) {
            return ExpandOrientation.FAB_RIGHT;
        } else {
            return ExpandOrientation.FAB_TOP;
        }
    }
    /**
     * @return 列舉變數實際返回值
     */
    public int getValue() {
        return value;
    }
}

六:因為SuspensionFab view的預設大小正好是預設按鈕的大小,而按鈕還有陰影效果所以會導致陰影顯示不全如下左圖;要解決這個問題也是很簡單第一種就是加大view的高寬(這也是最常用的)、第二種就是在他的父佈局容器中新增android:clipChildren=”false”這個屬性就是允許子view可以超出父容器的大小,這樣陰影也就全部顯示瞭如下右圖:

這裡寫圖片描述   這裡寫圖片描述

這裡需要注意的是:雖然view可以超出父容器,但是如果你需要點選事件的話就比較坑了,因為只有點選原來的容器範圍內才能響應點選事件(不知道為什麼,有大神知道可以告知一二)….

如果覺得不錯就留下你的star吧……專案地址 ^_^