📜 ⬆️ ⬇️

Add Floating Action Button to your Android app.

This year, a new version of Android - L was introduced at the Google I / O presentation. At the same time, many new features for users and developers were presented. But one of the main innovations was undoubtedly the new Google solution for the unification of design - Material Design.

One of the patterns of Material Design is the Floating Action Button .

What is the Floating Action Button?


Google says this is a “special method for facilitating action.” The button itself has the shape of a circle floating above the interface.
')


It is worth noting that the Floating Action Button should reflect only the main action in the application.

Quick and dirty implementation


I wanted to create a quick way to add the simplest FAB for my Android applications with minSdkVersion = 14 (Ice Cream Sandwich). I also implemented the appearance / disappearance animation and small customization options for the button.

All code is available in Github Gist (add this class to your project).

For reliability, I'll duplicate the code here.
package your_package; import android.animation.AnimatorSet; import android.animation.ObjectAnimator; 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; public class FloatingActionButton extends View { Context context; Paint mButtonPaint; Paint mDrawablePaint; Bitmap mBitmap; 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(new 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(new OvershootInterpolator()); animSetXY.setDuration(200); animSetXY.start(); mHidden = false; } } public boolean isHidden() { return mHidden; } static public class Builder { private FrameLayout.LayoutParams params; private final Activity activity; int gravity = Gravity.BOTTOM | Gravity.RIGHT; // default bottom right Drawable drawable; int color = Color.WHITE; int size = 0; float scale = 0; public Builder(Activity context) { scale = context.getResources().getDisplayMetrics().density; // 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) size = (int) (72 * scale + 0.5f); // default size is 72dp by 72dp params = new FrameLayout.LayoutParams(size, size); params.gravity = gravity; this.activity = context; } /** * 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((int) (left * scale + 0.5f), (int) (top * scale + 0.5f), (int) (right * scale + 0.5f), (int) (bottom * scale + 0.5f)); 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 = (int) (size * scale + 0.5f); params = new FrameLayout.LayoutParams(size, size); return this; } 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); root.addView(button, params); return button; } } } 


When creating the button in XML, I found some difficulties in positioning the View with our button over the rest of the View (in particular, above the Navigation Drawer). I decided to implement the button programmatically and work through the Builder pattern, which will allow the FAB to be placed above the other View in the Activity when calling .create () .

Fine! But how do I add this to my app?


Adding a Floating Action Button is very simple:

 FloatingActionButton fabButton = new FloatingActionButton.Builder(this) .withDrawable(yourDrawable) .withButtonColor(Color.WHITE) .withGravity(Gravity.BOTTOM | Gravity.RIGHT) .withMargins(0, 0, 16, 16) .create(); 

The size of the button is easily changed by calling .withButtonSize (int size) . The default is 72dp.



Conclusion


It seems that Google will use this pattern in many of its applications. And there is still no news about whether Google will add a floating action button in the support library, so for now, feel free to use this solution.

Github Gist Code

Source: https://habr.com/ru/post/231429/


All Articles