Skip to content
This repository was archived by the owner on Oct 23, 2020. It is now read-only.

Commit 42ea3d9

Browse files
committed
Merge pull request #16 from Clans/dev
Added show/hide animations for FAM. Added close on touch outside option.
2 parents 4ed63e9 + 1e636d0 commit 42ea3d9

File tree

6 files changed

+233
-31
lines changed

6 files changed

+233
-31
lines changed

library/build.gradle

+7-1
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,20 @@ android {
55
buildToolsVersion "22.0.1"
66

77
defaultConfig {
8-
minSdkVersion 15
8+
minSdkVersion 14
99
targetSdkVersion 22
1010
versionCode Integer.parseInt(project.VERSION_CODE)
1111
versionName project.VERSION_NAME
1212
}
1313
buildTypes {
1414
release {
1515
minifyEnabled false
16+
debuggable false
17+
}
18+
19+
debug {
20+
minifyEnabled false
21+
debuggable true
1622
}
1723
}
1824
}

library/src/main/java/com/github/clans/fab/FloatingActionMenu.java

+164-4
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,11 @@
1111
import android.util.AttributeSet;
1212
import android.util.TypedValue;
1313
import android.view.ContextThemeWrapper;
14+
import android.view.GestureDetector;
15+
import android.view.MotionEvent;
1416
import android.view.View;
1517
import android.view.ViewGroup;
18+
import android.view.animation.Animation;
1619
import android.view.animation.AnimationUtils;
1720
import android.view.animation.AnticipateInterpolator;
1821
import android.view.animation.Interpolator;
@@ -70,6 +73,10 @@ public class FloatingActionMenu extends ViewGroup {
7073
private int mLabelsStyle;
7174
private boolean mIconAnimated = true;
7275
private ImageView mImageToggle;
76+
private Animation mMenuButtonShowAnimation;
77+
private Animation mMenuButtonHideAnimation;
78+
private boolean mIsMenuButtonAnimationRunning;
79+
private boolean mIsSetClosedOnTouchOutside;
7380

7481
private OnMenuToggleListener mToggleListener;
7582

@@ -135,9 +142,15 @@ private void init(Context context, AttributeSet attrs) {
135142
mOpenInterpolator = new OvershootInterpolator();
136143
mCloseInterpolator = new AnticipateInterpolator();
137144

145+
initMenuButtonAnimations();
138146
createMenuButton();
139147
}
140148

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+
141154
private void initPadding(int padding) {
142155
mLabelsPaddingTop = padding;
143156
mLabelsPaddingRight = padding;
@@ -226,17 +239,26 @@ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
226239
}
227240
}
228241

229-
width = Math.max(mMaxButtonWidth, maxLabelWidth + mLabelsMargin);
242+
width = Math.max(mMaxButtonWidth, maxLabelWidth + mLabelsMargin) + getPaddingLeft() + getPaddingRight();
230243

231-
height += mButtonSpacing * (getChildCount() - 1);
244+
height += mButtonSpacing * (getChildCount() - 1) + getPaddingTop() + getPaddingBottom();
232245
height = adjustForOvershoot(height);
233246

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+
234256
setMeasuredDimension(width, height);
235257
}
236258

237259
@Override
238260
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();
240262
int menuButtonTop = b - t - mMenuButton.getMeasuredHeight() - getPaddingBottom();
241263
int menuButtonLeft = buttonsHorizontalCenter - mMenuButton.getMeasuredWidth() / 2;
242264

@@ -281,7 +303,9 @@ protected void onLayout(boolean changed, int l, int t, int r, int b) {
281303
label.layout(labelXAwayFromButton, labelTop,
282304
labelXNearButton, labelTop + label.getMeasuredHeight());
283305

284-
label.setVisibility(INVISIBLE);
306+
if (!mMenuOpened) {
307+
label.setVisibility(INVISIBLE);
308+
}
285309
}
286310

287311
nextY = childY - mButtonSpacing;
@@ -401,6 +425,51 @@ protected boolean checkLayoutParams(LayoutParams p) {
401425
return p instanceof MarginLayoutParams;
402426
}
403427

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+
404473
/* ===== API methods ===== */
405474

406475
public boolean isOpened() {
@@ -555,4 +624,95 @@ public void setIconToggleAnimatorSet(AnimatorSet toggleAnimatorSet) {
555624
public AnimatorSet getIconToggleAnimatorSet() {
556625
return mIconToggleSet;
557626
}
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+
}
558718
}

sample/build.gradle

+5-3
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,22 @@ android {
66

77
defaultConfig {
88
applicationId "com.github.fab.sample"
9-
minSdkVersion 15
9+
minSdkVersion 14
1010
targetSdkVersion 22
1111
versionCode Integer.parseInt(project.VERSION_CODE)
1212
versionName project.VERSION_NAME
1313
}
1414
buildTypes {
1515
release {
1616
minifyEnabled true
17-
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
17+
debuggable false
18+
proguardFiles 'proguard-rules.pro'
1819
}
1920

2021
debug {
2122
minifyEnabled false
22-
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
23+
debuggable true
24+
proguardFiles 'proguard-rules.pro'
2325
}
2426
}
2527
}

0 commit comments

Comments
 (0)