Skip to content

Instantly share code, notes, and snippets.

@roberdcr
Forked from Jogan/FloatingActionButton.java
Last active September 11, 2017 21:27
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save roberdcr/ef33471fb8bd47165540 to your computer and use it in GitHub Desktop.
Save roberdcr/ef33471fb8bd47165540 to your computer and use it in GitHub Desktop.
package your_package;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.OvershootInterpolator;
import android.widget.FrameLayout;
@SuppressLint("ClickableViewAccessibility")
/**
* Class for implement float action button in android apps from API 14
* @author Roberto de Castro Rodríguez
* @version 1.1
* @since 02/12/2014
*/
public class FloatingActionButton extends View {
final static OvershootInterpolator overshootInterpolator = new OvershootInterpolator();
final static AccelerateInterpolator accelerateInterpolator = new AccelerateInterpolator();
@SuppressWarnings("unused")
private Context context;
private Paint mButtonPaint;
private Paint mDrawablePaint;
private Bitmap mBitmap;
private boolean mHidden = false;
public FloatingActionButton(Context context) {
super(context);
this.context = context;
init(Color.WHITE);
}
public void setFloatingActionButtonColor(int FloatingActionButtonColor) {
init(FloatingActionButtonColor);
}
public void setFloatingActionButtonDrawable(Drawable FloatingActionButtonDrawable) {
mBitmap = ((BitmapDrawable) FloatingActionButtonDrawable).getBitmap();
invalidate();
}
public void init(int FloatingActionButtonColor) {
setWillNotDraw(false);
setLayerType(View.LAYER_TYPE_SOFTWARE, null);
mButtonPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mButtonPaint.setColor(FloatingActionButtonColor);
mButtonPaint.setStyle(Paint.Style.FILL);
mButtonPaint.setShadowLayer(10.0f, 0.0f, 3.5f, Color.argb(100, 0, 0, 0));
mDrawablePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
invalidate();
}
@Override
protected void onDraw(Canvas canvas) {
setClickable(true);
canvas.drawCircle(getWidth() / 2, getHeight() / 2, (float) (getWidth() / 2.6), mButtonPaint);
canvas.drawBitmap(mBitmap, (getWidth() - mBitmap.getWidth()) / 2,
(getHeight() - mBitmap.getHeight()) / 2, mDrawablePaint);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_UP) {
setAlpha(1.0f);
} else if (event.getAction() == MotionEvent.ACTION_DOWN) {
setAlpha(0.6f);
}
return super.onTouchEvent(event);
}
public void hideFloatingActionButton() {
if (!mHidden) {
ObjectAnimator scaleX = ObjectAnimator.ofFloat(this, "scaleX", 1, 0);
ObjectAnimator scaleY = ObjectAnimator.ofFloat(this, "scaleY", 1, 0);
AnimatorSet animSetXY = new AnimatorSet();
animSetXY.playTogether(scaleX, scaleY);
animSetXY.setInterpolator(accelerateInterpolator);
animSetXY.setDuration(100);
animSetXY.start();
mHidden = true;
}
}
public void showFloatingActionButton() {
if (mHidden) {
ObjectAnimator scaleX = ObjectAnimator.ofFloat(this, "scaleX", 0, 1);
ObjectAnimator scaleY = ObjectAnimator.ofFloat(this, "scaleY", 0, 1);
AnimatorSet animSetXY = new AnimatorSet();
animSetXY.playTogether(scaleX, scaleY);
animSetXY.setInterpolator(overshootInterpolator);
animSetXY.setDuration(200);
animSetXY.start();
mHidden = false;
}
}
public boolean isHidden() {
return mHidden;
}
/**
* Class for build fab button from code
* @author Roberto de Castro Rodríguez
* @version 1.0
* @since 02/12/2014
*/
static public class Builder {
/**
* Params of layout
*/
private FrameLayout.LayoutParams params;
/**
* Activity of app
*/
private final Activity activity;
/**
* Container where button is added
*/
private final ViewGroup container;
/**
* Default gravity
*/
int gravity = Gravity.BOTTOM | Gravity.RIGHT;
/**
* Button's icon
*/
private Drawable drawable;
/**
* Button's color
*/
int color = Color.WHITE;
/**
* Button's size
*/
int size = 0;
/**
* Button's scale
*/
float scale = 0;
/**
* Builder of the fab button
* @param context activity for add the button
* @param container layout where add the button
*/
public Builder(Activity context, ViewGroup container) {
scale = context.getResources().getDisplayMetrics().density;
size = convertToPixels(72, scale); // default size is 72dp by 72dp
params = new FrameLayout.LayoutParams(size, size);
params.gravity = gravity;
this.activity = context;
this.container = container;
}
/**
* Sets the gravity for the FAB
*/
public Builder withGravity(int gravity) {
this.gravity = gravity;
return this;
}
/**
* Sets the margins for the FAB in dp
*/
public Builder withMargins(int left, int top, int right, int bottom) {
params.setMargins(
convertToPixels(left, scale),
convertToPixels(top, scale),
convertToPixels(right, scale),
convertToPixels(bottom, scale));
return this;
}
/**
* Sets the FAB drawable
*/
public Builder withDrawable(final Drawable drawable) {
this.drawable = drawable;
return this;
}
/**
* Sets the FAB color
*/
public Builder withButtonColor(final int color) {
this.color = color;
return this;
}
/**
* Sets the FAB size in dp
*/
public Builder withButtonSize(int size) {
size = convertToPixels(size, scale);
params = new FrameLayout.LayoutParams(size, size);
return this;
}
/**
* Creation of the button
* @return fab button
*/
public FloatingActionButton create() {
final FloatingActionButton button = new FloatingActionButton(activity);
button.setFloatingActionButtonColor(this.color);
button.setFloatingActionButtonDrawable(this.drawable);
params.gravity = this.gravity;
//ViewGroup root = (ViewGroup) activity.findViewById(android.R.id.content);
this.container.addView(button, params);
return button;
}
// The calculation (value * scale + 0.5f) is a widely used to convert to dps to pixel units
// based on density scale
// see developer.android.com (Supporting Multiple Screen Sizes)
private int convertToPixels(int dp, float scale){
return (int) (dp * scale + 0.5f) ;
}
}
}
FloatingActionButton fab = new FloatingActionButton.Builder(this.getActivity(), (FrameLayout)rootView.findViewById(R.id.your_layout))
.withDrawable(getResources().getDrawable(R.drawable.add_icon_activity))
.withButtonColor(getResources().getColor(R.color.fab_color))
.withGravity(Gravity.BOTTOM | Gravity.RIGHT)
.withMargins(0, 0, 5, 5)
.create();
@hiteshsahu
Copy link

If you want to put it on border of two layouts drawn one above another one can use this class as 👎

final RelativeLayout topLayout = (RelativeLayout) view
.findViewById(R.id.top_view);

        final ViewTreeObserver observer = topLayout.getViewTreeObserver();
        observer.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                topLayout.getHeight();

                fabButton = new FloatingActionButton.Builder(getActivity())
                        .withDrawable(
                                getResources().getDrawable(R.drawable.fab_icon))
                        .withButtonColor(Color.WHITE)
                        .withGravity(Gravity.TOP | Gravity.RIGHT)
                        .withMargins(0, topLayout.getHeight() - 72 + 30, 16, 0)
                        .create();

                fabButton.setOnClickListener(new OnClickListener() {

                    @Override
                    public void onClick(View arg0) {

                        fabButton.hideFloatingActionButton();

                        //DO something
                    }
                });

                topLayout.getViewTreeObserver().removeGlobalOnLayoutListener(
                        this);
            }
        });                                  Where in magic number- 72 + 30 , 72 is default width of fab icon  and 30 is bottomMargin given to top layout.

Out put will be like :-

|--------------------------------- |
|_TOP LAYOUT|
| (Fab) |
| |
|_BOTTOM LAYOUT
|

@CGLaidlaw
Copy link

We are looking to implement this button in our app on top of an expandable list view, but the button is behind the list, any thoughts?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment