Created
March 6, 2018 12:38
Revisions
-
Subtle-fox created this gist
Mar 6, 2018 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,208 @@ /** * Created by Andrey Kolpakov on 19.01.2018 */ public class FabMenu { private final ViewGroup parent; private final Context context; private final FloatingActionButton fab; private boolean isFabMenuOpened; private View maskedView; private ArrayList<FabMenuItem> menuItems = new ArrayList<>(); private ArrayList<FabMenuView> menuItemViews = new ArrayList<>(); public FabMenu(ViewGroup parent, FloatingActionButton mainFab) { this.parent = parent; this.context = parent.getContext(); this.fab = mainFab; } private View createMaskedView() { View view = new View(context); view.setBackgroundColor(ContextCompat.getColor(context, R.color.fab_menu_background)); view.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { closeFabMenu(); } }); view.setScaleX(0f); view.setScaleY(0f); view.setAlpha(0f); return view; } public void addMenuItem(int imageResId, int label, View.OnClickListener action) { menuItems.add(new FabMenuItem(imageResId, label, action)); } public void create() { if (menuItems.isEmpty()) { fab.setVisibility(View.GONE); return; } maskedView = createMaskedView(); if (menuItems.size() == 1) { fab.setImageResource(menuItems.get(0).imageResId); fab.setOnClickListener(menuItems.get(0).action); } else { createFabMenu(); } fab.show(); } public boolean hasItems() { return menuItems.size() > 0; } private void createFabMenu() { fab.setImageResource(R.drawable.ic_menu_hamburger); fab.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (!isFabMenuOpened) { showFabMenu(); } else { closeFabMenu(); } } }); int firstDy = (int) context.getResources().getDimension(R.dimen.fab_menu_firt_dy); int dy = (int) context.getResources().getDimension(R.dimen.fab_menu_dy); for (int i = 0; i < menuItems.size(); i++) { FabMenuItem menuItem = menuItems.get(i); View menuView = View.inflate(context, R.layout.layout_fab_menu_item, null); FloatingActionButton menuFab = menuView.findViewById(R.id.fab); menuFab.setImageResource(menuItem.imageResId); TextView menuFabLabel = menuView.findViewById(R.id.label); menuFabLabel.setText(menuItem.labelResId); menuFabLabel.setAlpha(0f); menuFab.setOnClickListener(new OnClickListenerDelegate(menuItem.action)); int offset = (i + 1) * dy + firstDy; menuItemViews.add(new FabMenuView(offset, menuView, menuFabLabel)); } } private void showFabMenu() { isFabMenuOpened = true; fab.setImageResource(R.drawable.ic_close_primary_vector); maskedView.setPivotX(fab.getX() + fab.getWidth() / 2); maskedView.setPivotY(fab.getY() - fab.getHeight() / 2); parent.addView(maskedView, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); CoordinatorLayout.LayoutParams layoutParams = new CoordinatorLayout.LayoutParams(CoordinatorLayout.LayoutParams.MATCH_PARENT, CoordinatorLayout.LayoutParams.WRAP_CONTENT); for (FabMenuView menuItemView : menuItemViews) { parent.addView(menuItemView.menuView, layoutParams); menuItemView.menuView.setTranslationY(fab.getY() - fab.getHeight() / 2); menuItemView.menuView.animate().translationY(menuItemView.menuView.getTranslationY() - menuItemView.offsetPx); menuItemView.labelView.animate().setStartDelay(200).setDuration(150).alpha(1f); } maskedView.animate().scaleX(1f).scaleY(1f).alpha(0.85f).setDuration(200); } public void closeFabMenu() { isFabMenuOpened = false; fab.setImageResource(R.drawable.ic_menu_hamburger); for (FabMenuView menuItemView : menuItemViews) { menuItemView.menuView.animate().translationY(fab.getY()); menuItemView.labelView.setAlpha(0f); } maskedView.animate().scaleX(0f).scaleY(0f).setDuration(200).alpha(0f).setListener(animatorListener); } public boolean isOpened() { return isFabMenuOpened; } public void clear() { removeViews(); menuItemViews.clear(); menuItems.clear(); maskedView = null; } private void removeViews() { if (maskedView != null) { parent.removeViewInLayout(maskedView); } for (FabMenuView menuItemView : menuItemViews) { parent.removeViewInLayout(menuItemView.menuView); } } private Animator.AnimatorListener animatorListener = new Animator.AnimatorListener() { @Override public void onAnimationStart(Animator animation) { } @Override public void onAnimationEnd(Animator animation) { if (!isFabMenuOpened) { removeViews(); } } @Override public void onAnimationCancel(Animator animation) { } @Override public void onAnimationRepeat(Animator animation) { } }; class OnClickListenerDelegate implements View.OnClickListener { private final View.OnClickListener clickListener; OnClickListenerDelegate(View.OnClickListener clickListener) { this.clickListener = clickListener; } @Override public void onClick(final View v) { closeFabMenu(); if (clickListener != null) { new Handler().postDelayed(new Runnable() { @Override public void run() { clickListener.onClick(v); } }, 400); } } } public static class FabMenuItem { int imageResId; int labelResId; View.OnClickListener action; FabMenuItem(int imageResId, int labelResId, View.OnClickListener action) { this.imageResId = imageResId; this.labelResId = labelResId; this.action = action; } } public static class FabMenuView { int offsetPx; View menuView; TextView labelView; FabMenuView(int offsetPx, View menuView, TextView labelView) { this.offsetPx = offsetPx; this.menuView = menuView; this.labelView = labelView; } } }