|
11 | 11 | import android.util.AttributeSet;
|
12 | 12 | import android.util.TypedValue;
|
13 | 13 | import android.view.ContextThemeWrapper;
|
| 14 | +import android.view.GestureDetector; |
| 15 | +import android.view.MotionEvent; |
14 | 16 | import android.view.View;
|
15 | 17 | import android.view.ViewGroup;
|
| 18 | +import android.view.animation.Animation; |
16 | 19 | import android.view.animation.AnimationUtils;
|
17 | 20 | import android.view.animation.AnticipateInterpolator;
|
18 | 21 | import android.view.animation.Interpolator;
|
@@ -70,6 +73,10 @@ public class FloatingActionMenu extends ViewGroup {
|
70 | 73 | private int mLabelsStyle;
|
71 | 74 | private boolean mIconAnimated = true;
|
72 | 75 | private ImageView mImageToggle;
|
| 76 | + private Animation mMenuButtonShowAnimation; |
| 77 | + private Animation mMenuButtonHideAnimation; |
| 78 | + private boolean mIsMenuButtonAnimationRunning; |
| 79 | + private boolean mIsSetClosedOnTouchOutside; |
73 | 80 |
|
74 | 81 | private OnMenuToggleListener mToggleListener;
|
75 | 82 |
|
@@ -135,9 +142,15 @@ private void init(Context context, AttributeSet attrs) {
|
135 | 142 | mOpenInterpolator = new OvershootInterpolator();
|
136 | 143 | mCloseInterpolator = new AnticipateInterpolator();
|
137 | 144 |
|
| 145 | + initMenuButtonAnimations(); |
138 | 146 | createMenuButton();
|
139 | 147 | }
|
140 | 148 |
|
| 149 | + private void initMenuButtonAnimations() { |
| 150 | + mMenuButtonShowAnimation = AnimationUtils.loadAnimation(getContext(), R.anim.fab_scale_up); |
| 151 | + mMenuButtonHideAnimation = AnimationUtils.loadAnimation(getContext(), R.anim.fab_scale_down); |
| 152 | + } |
| 153 | + |
141 | 154 | private void initPadding(int padding) {
|
142 | 155 | mLabelsPaddingTop = padding;
|
143 | 156 | mLabelsPaddingRight = padding;
|
@@ -226,17 +239,26 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
226 | 239 | }
|
227 | 240 | }
|
228 | 241 |
|
229 |
| - width = Math.max(mMaxButtonWidth, maxLabelWidth + mLabelsMargin); |
| 242 | + width = Math.max(mMaxButtonWidth, maxLabelWidth + mLabelsMargin) + getPaddingLeft() + getPaddingRight(); |
230 | 243 |
|
231 |
| - height += mButtonSpacing * (getChildCount() - 1); |
| 244 | + height += mButtonSpacing * (getChildCount() - 1) + getPaddingTop() + getPaddingBottom(); |
232 | 245 | height = adjustForOvershoot(height);
|
233 | 246 |
|
| 247 | + |
| 248 | + if (getLayoutParams().width == LayoutParams.MATCH_PARENT) { |
| 249 | + width = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec); |
| 250 | + } |
| 251 | + |
| 252 | + if (getLayoutParams().height == LayoutParams.MATCH_PARENT) { |
| 253 | + height = getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec); |
| 254 | + } |
| 255 | + |
234 | 256 | setMeasuredDimension(width, height);
|
235 | 257 | }
|
236 | 258 |
|
237 | 259 | @Override
|
238 | 260 | protected void onLayout(boolean changed, int l, int t, int r, int b) {
|
239 |
| - int buttonsHorizontalCenter = r - l - mMaxButtonWidth / 2; |
| 261 | + int buttonsHorizontalCenter = r - l - mMaxButtonWidth / 2 - getPaddingRight(); |
240 | 262 | int menuButtonTop = b - t - mMenuButton.getMeasuredHeight() - getPaddingBottom();
|
241 | 263 | int menuButtonLeft = buttonsHorizontalCenter - mMenuButton.getMeasuredWidth() / 2;
|
242 | 264 |
|
@@ -281,7 +303,9 @@ protected void onLayout(boolean changed, int l, int t, int r, int b) {
|
281 | 303 | label.layout(labelXAwayFromButton, labelTop,
|
282 | 304 | labelXNearButton, labelTop + label.getMeasuredHeight());
|
283 | 305 |
|
284 |
| - label.setVisibility(INVISIBLE); |
| 306 | + if (!mMenuOpened) { |
| 307 | + label.setVisibility(INVISIBLE); |
| 308 | + } |
285 | 309 | }
|
286 | 310 |
|
287 | 311 | nextY = childY - mButtonSpacing;
|
@@ -401,6 +425,51 @@ protected boolean checkLayoutParams(LayoutParams p) {
|
401 | 425 | return p instanceof MarginLayoutParams;
|
402 | 426 | }
|
403 | 427 |
|
| 428 | + private void hideMenuButtonWithImage(boolean animate) { |
| 429 | + if (!isMenuButtonHidden()) { |
| 430 | + mMenuButton.hide(animate); |
| 431 | + if (animate) { |
| 432 | + mImageToggle.startAnimation(mMenuButtonHideAnimation); |
| 433 | + } |
| 434 | + mImageToggle.setVisibility(INVISIBLE); |
| 435 | + mIsMenuButtonAnimationRunning = false; |
| 436 | + } |
| 437 | + } |
| 438 | + |
| 439 | + private void showMenuButtonWithImage(boolean animate) { |
| 440 | + if (isMenuButtonHidden()) { |
| 441 | + mMenuButton.show(animate); |
| 442 | + if (animate) { |
| 443 | + mImageToggle.startAnimation(mMenuButtonShowAnimation); |
| 444 | + } |
| 445 | + mImageToggle.setVisibility(VISIBLE); |
| 446 | + } |
| 447 | + } |
| 448 | + |
| 449 | + @Override |
| 450 | + public boolean onTouchEvent(MotionEvent event) { |
| 451 | + if (mIsSetClosedOnTouchOutside) { |
| 452 | + return mGestureDetector.onTouchEvent(event); |
| 453 | + } else { |
| 454 | + return super.onTouchEvent(event); |
| 455 | + } |
| 456 | + } |
| 457 | + |
| 458 | + GestureDetector mGestureDetector = new GestureDetector(getContext(), |
| 459 | + new GestureDetector.SimpleOnGestureListener() { |
| 460 | + |
| 461 | + @Override |
| 462 | + public boolean onDown(MotionEvent e) { |
| 463 | + return mIsSetClosedOnTouchOutside && isOpened(); |
| 464 | + } |
| 465 | + |
| 466 | + @Override |
| 467 | + public boolean onSingleTapUp(MotionEvent e) { |
| 468 | + close(mIsAnimated); |
| 469 | + return true; |
| 470 | + } |
| 471 | + }); |
| 472 | + |
404 | 473 | /* ===== API methods ===== */
|
405 | 474 |
|
406 | 475 | public boolean isOpened() {
|
@@ -555,4 +624,95 @@ public void setIconToggleAnimatorSet(AnimatorSet toggleAnimatorSet) {
|
555 | 624 | public AnimatorSet getIconToggleAnimatorSet() {
|
556 | 625 | return mIconToggleSet;
|
557 | 626 | }
|
| 627 | + |
| 628 | + public void setMenuButtonShowAnimation(Animation showAnimation) { |
| 629 | + mMenuButtonShowAnimation = showAnimation; |
| 630 | + mMenuButton.setShowAnimation(showAnimation); |
| 631 | + } |
| 632 | + |
| 633 | + public void setMenuButtonHideAnimation(Animation hideAnimation) { |
| 634 | + mMenuButtonHideAnimation = hideAnimation; |
| 635 | + mMenuButton.setHideAnimation(hideAnimation); |
| 636 | + } |
| 637 | + |
| 638 | + public boolean isMenuButtonHidden() { |
| 639 | + return mMenuButton.isHidden(); |
| 640 | + } |
| 641 | + |
| 642 | + public void showMenuButton(boolean animate) { |
| 643 | + if (isMenuButtonHidden()) { |
| 644 | + showMenuButtonWithImage(animate); |
| 645 | + } |
| 646 | + } |
| 647 | + |
| 648 | + public void hideMenuButton(final boolean animate) { |
| 649 | + if (!isMenuButtonHidden() && !mIsMenuButtonAnimationRunning) { |
| 650 | + mIsMenuButtonAnimationRunning = true; |
| 651 | + if (isOpened()) { |
| 652 | + close(animate); |
| 653 | + mUiHandler.postDelayed(new Runnable() { |
| 654 | + @Override |
| 655 | + public void run() { |
| 656 | + hideMenuButtonWithImage(animate); |
| 657 | + } |
| 658 | + }, mAnimationDelayPerItem * mButtonsCount); |
| 659 | + } else { |
| 660 | + hideMenuButtonWithImage(animate); |
| 661 | + } |
| 662 | + } |
| 663 | + } |
| 664 | + |
| 665 | + public void toggleMenuButton(boolean animate) { |
| 666 | + if (isMenuButtonHidden()) { |
| 667 | + showMenuButton(animate); |
| 668 | + } else { |
| 669 | + hideMenuButton(animate); |
| 670 | + } |
| 671 | + } |
| 672 | + |
| 673 | + public void setClosedOnTouchOutside(boolean close) { |
| 674 | + mIsSetClosedOnTouchOutside = close; |
| 675 | + } |
| 676 | + |
| 677 | + public void setMenuButtonColorNormal(int color) { |
| 678 | + mMenuColorNormal = color; |
| 679 | + mMenuButton.setColorNormal(color); |
| 680 | + } |
| 681 | + |
| 682 | + public void setMenuButtonColorNormalResId(int colorResId) { |
| 683 | + mMenuColorNormal = getResources().getColor(colorResId); |
| 684 | + mMenuButton.setColorNormalResId(colorResId); |
| 685 | + } |
| 686 | + |
| 687 | + public int getMenuButtonColorNormal() { |
| 688 | + return mMenuColorNormal; |
| 689 | + } |
| 690 | + |
| 691 | + public void setMenuButtonColorPressed(int color) { |
| 692 | + mMenuColorPressed = color; |
| 693 | + mMenuButton.setColorPressed(color); |
| 694 | + } |
| 695 | + |
| 696 | + public void setMenuButtonColorPressedResId(int colorResId) { |
| 697 | + mMenuColorPressed = getResources().getColor(colorResId); |
| 698 | + mMenuButton.setColorPressedResId(colorResId); |
| 699 | + } |
| 700 | + |
| 701 | + public int getMenuButtonColorPressed() { |
| 702 | + return mMenuColorPressed; |
| 703 | + } |
| 704 | + |
| 705 | + public void setMenuButtonColorRipple(int color) { |
| 706 | + mMenuColorRipple = color; |
| 707 | + mMenuButton.setColorRipple(color); |
| 708 | + } |
| 709 | + |
| 710 | + public void setMenuButtonColorRippleResId(int colorResId) { |
| 711 | + mMenuColorRipple = getResources().getColor(colorResId); |
| 712 | + mMenuButton.setColorRippleResId(colorResId); |
| 713 | + } |
| 714 | + |
| 715 | + public int getMenuButtonColorRipple() { |
| 716 | + return mMenuColorRipple; |
| 717 | + } |
558 | 718 | }
|
0 commit comments