Instantly share code, notes, and snippets.
Last active
January 12, 2018 12:43
-
Star
1
(1)
You must be signed in to star a gist -
Fork
1
(1)
You must be signed in to fork a gist
-
Save chantellosejo/5bbc0d357ac81718f90a to your computer and use it in GitHub Desktop.
Android Material Floating Action Button (Supports API 14+ with shadows and 21+ with Lollipop elevation)
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 characters
package com.bigoven.android.widgets; | |
import android.animation.AnimatorSet; | |
import android.animation.ObjectAnimator; | |
import android.annotation.SuppressLint; | |
import android.content.Context; | |
import android.content.res.TypedArray; | |
import android.graphics.Canvas; | |
import android.graphics.Color; | |
import android.graphics.Paint; | |
import android.graphics.drawable.Drawable; | |
import android.graphics.drawable.ShapeDrawable; | |
import android.graphics.drawable.shapes.OvalShape; | |
import android.os.Build; | |
import android.util.AttributeSet; | |
import android.view.MotionEvent; | |
import android.view.View; | |
import android.view.animation.AccelerateInterpolator; | |
import android.widget.ImageButton; | |
import com.bigoven.android.R; | |
import com.bigoven.android.utilities.UiHelper; | |
@SuppressLint("ClickableViewAccessibility") | |
/** | |
* This class is a custom view that encompasses the functionality of Google's Material Design "Floating Action Button" | |
* It supports API 14+ devices. | |
* | |
* Copyright (C) 2015 Chantell Osejo | |
* | |
* This program is free software: you can redistribute it and/or modify | |
* it under the terms of the GNU General Public License as published by | |
* the Free Software Foundation, either version 3 of the License, or | |
* (at your option) any later version. | |
* | |
* This program is distributed in the hope that it will be useful, | |
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
* GNU General Public License for more details. | |
* | |
* You should have received a copy of the GNU General Public License | |
* along with this program. If not, see <http://www.gnu.org/licenses/> | |
*/ | |
public class FloatingActionButton extends ImageButton { | |
public static final int GOOGLE_DESIGN_GUIDELINE_RECOMMENDED_DIAMETER_PX = UiHelper.convertDpToPixel(56); | |
public static final int GOOGLE_DESIGN_GUIDELINE_RECOMMENDED_MINI_DIAMETER_PX = UiHelper.convertDpToPixel(40); | |
final static AccelerateInterpolator accelerateInterpolator = new AccelerateInterpolator(); | |
private Paint mBackgroundPaint; | |
private int mColor = Color.WHITE; | |
private int visibility = View.VISIBLE; | |
private ShapeDrawable mCircleBackground; | |
public FloatingActionButton(Context context) { | |
super(context); | |
init(); | |
} | |
public FloatingActionButton(Context context, AttributeSet attrs) { | |
super(context, attrs); | |
TypedArray a = context.getTheme().obtainStyledAttributes( | |
attrs, | |
R.styleable.FloatingActionButton, | |
0, 0); | |
try { | |
mColor = a.getColor(R.styleable.FloatingActionButton_buttonColor, Color.WHITE); | |
} finally { | |
a.recycle(); | |
} | |
init(); | |
} | |
private void init() { | |
setColor(mColor); | |
setScaleType(ScaleType.CENTER_INSIDE); | |
visibility = getVisibility(); | |
} | |
public void setColor(int color) { | |
this.mColor = color; | |
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { | |
setLayerType(LAYER_TYPE_SOFTWARE, mBackgroundPaint); | |
mBackgroundPaint = new Paint(Paint.ANTI_ALIAS_FLAG); | |
mBackgroundPaint.setColor(mColor); | |
mBackgroundPaint.setShadowLayer(10.0f, 0.0f, 3.5f, Color.argb(100, 0, 0, 0)); | |
setBackgroundDrawable(null); | |
} else { | |
if (null == mCircleBackground) { | |
mCircleBackground = new ShapeDrawable(new OvalShape()); | |
setBackground(mCircleBackground); | |
setElevation(UiHelper.convertDpToPixel(8)); | |
} | |
mCircleBackground.getPaint().setColor(color); | |
} | |
invalidate(); | |
} | |
@Override | |
protected void onDraw(Canvas canvas) { | |
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { | |
canvas.drawCircle(getWidth() / 2, getHeight() / 2, (float) (getWidth() / 2.6), mBackgroundPaint); | |
} | |
super.onDraw(canvas); | |
} | |
@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 setVisibilityAfterDelay(final int visibility, long delay) { | |
if (this.visibility == visibility) { | |
return; | |
} | |
this.visibility = visibility; | |
boolean hide = this.visibility != View.VISIBLE; | |
ObjectAnimator scaleX = ObjectAnimator.ofFloat(this, SCALE_X, hide ? 1 : 0, hide ? 0 : 1); | |
ObjectAnimator scaleY = ObjectAnimator.ofFloat(this, SCALE_Y, hide ? 1 : 0, hide ? 0 : 1); | |
ObjectAnimator alpha = ObjectAnimator.ofFloat(this, ALPHA, hide ? 1 : 0, hide ? 0 : 1); | |
ObjectAnimator rotate = ObjectAnimator.ofFloat(this, ROTATION, 0f, 360f); | |
final AnimatorSet animSetXY = new AnimatorSet(); | |
animSetXY.playTogether(scaleX, scaleY, rotate, alpha); | |
animSetXY.setInterpolator(accelerateInterpolator); | |
animSetXY.setDuration(hide ? 200 : 300); | |
animSetXY.setStartDelay(delay); | |
animSetXY.start(); | |
} | |
@Override | |
/** | |
* Hijacking the visibility parameter to animate hiding/showing the button | |
*/ | |
public void setVisibility(final int visibility) { | |
setVisibilityAfterDelay(visibility, 0); | |
} | |
static public class Builder { | |
private final Context context; | |
int color = Color.WHITE; | |
private Drawable drawable; | |
/** | |
* Builder of the fab button | |
* | |
* @param context should be an Activity context, used to create the view | |
*/ | |
public Builder(Context context) { | |
this.context = context; | |
} | |
/** | |
* Sets the FAB drawable | |
*/ | |
public Builder setDrawable(final Drawable drawable) { | |
this.drawable = drawable; | |
return this; | |
} | |
/** | |
* Sets the FAB color | |
*/ | |
public Builder setColor(final int color) { | |
this.color = color; | |
return this; | |
} | |
public FloatingActionButton create() { | |
final FloatingActionButton button = new FloatingActionButton(context); | |
button.setColor(this.color); | |
button.setImageDrawable(this.drawable); | |
return button; | |
} | |
} | |
} |
Author
chantellosejo
commented
Apr 20, 2015
Also, don't forget...in your attrs.xml :
<declare-styleable name="FloatingActionButton">
<attr name="buttonColor" format="color"/>
</declare-styleable>
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment