From 09833a1ba51ca01680b9929410bc70218d985eb4 Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Tue, 29 May 2018 18:37:14 +0200 Subject: [PATCH] FloatingActionButton: import cleaned up getbase code Signed-off-by: Jason A. Donenfeld --- app/build.gradle | 7 +- .../widget/fab/AddFloatingActionButton.java | 96 +++ .../widget/fab/FloatingActionButton.java | 409 +++++++++++ .../widget/fab/FloatingActionsMenu.java | 643 ++++++++++++++++++ .../widget/fab/TouchDelegateGroup.java | 78 +++ .../main/res/drawable-hdpi/fab_bg_mini.png | Bin 0 -> 3519 bytes .../main/res/drawable-hdpi/fab_bg_normal.png | Bin 0 -> 4925 bytes .../main/res/drawable-mdpi/fab_bg_mini.png | Bin 0 -> 1547 bytes .../main/res/drawable-mdpi/fab_bg_normal.png | Bin 0 -> 2956 bytes .../main/res/drawable-xhdpi/fab_bg_mini.png | Bin 0 -> 4963 bytes .../main/res/drawable-xhdpi/fab_bg_normal.png | Bin 0 -> 7139 bytes .../main/res/drawable-xxhdpi/fab_bg_mini.png | Bin 0 -> 4803 bytes .../res/drawable-xxhdpi/fab_bg_normal.png | Bin 0 -> 6114 bytes .../main/res/drawable-xxxhdpi/fab_bg_mini.png | Bin 0 -> 5987 bytes .../res/drawable-xxxhdpi/fab_bg_normal.png | Bin 0 -> 8005 bytes .../main/res/layout/tunnel_list_fragment.xml | 8 +- app/src/main/res/values/fab.xml | 58 ++ 17 files changed, 1293 insertions(+), 6 deletions(-) create mode 100644 app/src/main/java/com/wireguard/android/widget/fab/AddFloatingActionButton.java create mode 100644 app/src/main/java/com/wireguard/android/widget/fab/FloatingActionButton.java create mode 100644 app/src/main/java/com/wireguard/android/widget/fab/FloatingActionsMenu.java create mode 100644 app/src/main/java/com/wireguard/android/widget/fab/TouchDelegateGroup.java create mode 100644 app/src/main/res/drawable-hdpi/fab_bg_mini.png create mode 100644 app/src/main/res/drawable-hdpi/fab_bg_normal.png create mode 100644 app/src/main/res/drawable-mdpi/fab_bg_mini.png create mode 100644 app/src/main/res/drawable-mdpi/fab_bg_normal.png create mode 100644 app/src/main/res/drawable-xhdpi/fab_bg_mini.png create mode 100644 app/src/main/res/drawable-xhdpi/fab_bg_normal.png create mode 100644 app/src/main/res/drawable-xxhdpi/fab_bg_mini.png create mode 100644 app/src/main/res/drawable-xxhdpi/fab_bg_normal.png create mode 100644 app/src/main/res/drawable-xxxhdpi/fab_bg_mini.png create mode 100644 app/src/main/res/drawable-xxxhdpi/fab_bg_normal.png create mode 100644 app/src/main/res/values/fab.xml diff --git a/app/build.gradle b/app/build.gradle index e0e1979d..7c653757 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -33,7 +33,6 @@ ext { databindingVersion = '3.1.2' supportLibsVersion = '27.1.1' daggerVersion = '2.14.1' - fabLibVersion = '1.10.1' streamsupportVersion = '1.6.0' } @@ -45,8 +44,12 @@ dependencies { implementation "com.android.support:design:$supportLibsVersion" implementation "com.android.support:preference-v14:$supportLibsVersion" implementation "com.android.support:support-annotations:$supportLibsVersion" - implementation "com.getbase:floatingactionbutton:$fabLibVersion" implementation "com.google.dagger:dagger:$daggerVersion" implementation "net.sourceforge.streamsupport:android-retrofuture:$streamsupportVersion" implementation "net.sourceforge.streamsupport:android-retrostreams:$streamsupportVersion" } + +tasks.withType(JavaCompile) { + options.compilerArgs << '-Xlint:unchecked' + options.deprecation = true +} \ No newline at end of file diff --git a/app/src/main/java/com/wireguard/android/widget/fab/AddFloatingActionButton.java b/app/src/main/java/com/wireguard/android/widget/fab/AddFloatingActionButton.java new file mode 100644 index 00000000..4a4dd3b5 --- /dev/null +++ b/app/src/main/java/com/wireguard/android/widget/fab/AddFloatingActionButton.java @@ -0,0 +1,96 @@ +/* + * Copyright © 2014 Jerzy Chalupski + * Copyright © 2018 Jason A. Donenfeld . All Rights Reserved. + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +package com.wireguard.android.widget.fab; + +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Paint.Style; +import android.graphics.drawable.Drawable; +import android.graphics.drawable.ShapeDrawable; +import android.graphics.drawable.shapes.Shape; +import android.support.annotation.ColorRes; +import android.support.annotation.DrawableRes; +import android.util.AttributeSet; + +import com.wireguard.android.R; + +public class AddFloatingActionButton extends FloatingActionButton { + int mPlusColor; + + public AddFloatingActionButton(final Context context) { + this(context, null); + } + + public AddFloatingActionButton(final Context context, final AttributeSet attrs) { + super(context, attrs); + } + + public AddFloatingActionButton(final Context context, final AttributeSet attrs, final int defStyle) { + super(context, attrs, defStyle); + } + + @Override + void init(final Context context, final AttributeSet attributeSet) { + final TypedArray attr = context.obtainStyledAttributes(attributeSet, R.styleable.AddFloatingActionButton, 0, 0); + mPlusColor = attr.getColor(R.styleable.AddFloatingActionButton_fab_plusIconColor, getColor(android.R.color.white)); + attr.recycle(); + + super.init(context, attributeSet); + } + + /** + * @return the current Color of plus icon. + */ + public int getPlusColor() { + return mPlusColor; + } + + public void setPlusColor(final int color) { + if (mPlusColor != color) { + mPlusColor = color; + updateBackground(); + } + } + + public void setPlusColorResId(@ColorRes int plusColor) { + setPlusColor(getColor(plusColor)); + } + + @Override + public void setIcon(@DrawableRes final int icon) { + throw new UnsupportedOperationException("Use FloatingActionButton if you want to use custom icon"); + } + + @Override + Drawable getIconDrawable() { + final float iconSize = getDimension(R.dimen.fab_icon_size); + final float iconHalfSize = iconSize / 2f; + + final float plusSize = getDimension(R.dimen.fab_plus_icon_size); + final float plusHalfStroke = getDimension(R.dimen.fab_plus_icon_stroke) / 2f; + final float plusOffset = (iconSize - plusSize) / 2f; + + final Shape shape = new Shape() { + @Override + public void draw(final Canvas canvas, final Paint paint) { + canvas.drawRect(plusOffset, iconHalfSize - plusHalfStroke, iconSize - plusOffset, iconHalfSize + plusHalfStroke, paint); + canvas.drawRect(iconHalfSize - plusHalfStroke, plusOffset, iconHalfSize + plusHalfStroke, iconSize - plusOffset, paint); + } + }; + + final ShapeDrawable drawable = new ShapeDrawable(shape); + + final Paint paint = drawable.getPaint(); + paint.setColor(mPlusColor); + paint.setStyle(Style.FILL); + paint.setAntiAlias(true); + + return drawable; + } +} diff --git a/app/src/main/java/com/wireguard/android/widget/fab/FloatingActionButton.java b/app/src/main/java/com/wireguard/android/widget/fab/FloatingActionButton.java new file mode 100644 index 00000000..f636aff0 --- /dev/null +++ b/app/src/main/java/com/wireguard/android/widget/fab/FloatingActionButton.java @@ -0,0 +1,409 @@ +/* + * Copyright © 2014 Jerzy Chalupski + * Copyright © 2018 Jason A. Donenfeld . All Rights Reserved. + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +package com.wireguard.android.widget.fab; + +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.*; +import android.graphics.Paint.Style; +import android.graphics.Shader.TileMode; +import android.graphics.drawable.*; +import android.graphics.drawable.ShapeDrawable.ShaderFactory; +import android.graphics.drawable.shapes.OvalShape; +import android.support.annotation.*; +import android.support.v7.widget.AppCompatImageButton; +import android.util.AttributeSet; +import android.widget.TextView; + +import com.wireguard.android.R; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +public class FloatingActionButton extends AppCompatImageButton { + + public static final int SIZE_NORMAL = 0; + public static final int SIZE_MINI = 1; + int mColorNormal; + int mColorPressed; + int mColorDisabled; + String mTitle; + boolean mStrokeVisible; + @DrawableRes + private int mIcon; + private Drawable mIconDrawable; + private int mSize; + + private float mCircleSize; + private float mShadowRadius; + private float mShadowOffset; + private int mDrawableSize; + public FloatingActionButton(final Context context) { + this(context, null); + } + + public FloatingActionButton(final Context context, final AttributeSet attrs) { + super(context, attrs); + init(context, attrs); + } + + public FloatingActionButton(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + init(context, attrs); + } + + void init(final Context context, final AttributeSet attributeSet) { + final TypedArray attr = context.obtainStyledAttributes(attributeSet, R.styleable.FloatingActionButton, 0, 0); + mColorNormal = attr.getColor(R.styleable.FloatingActionButton_fab_colorNormal, getColor(android.R.color.holo_blue_dark)); + mColorPressed = attr.getColor(R.styleable.FloatingActionButton_fab_colorPressed, getColor(android.R.color.holo_blue_light)); + mColorDisabled = attr.getColor(R.styleable.FloatingActionButton_fab_colorDisabled, getColor(android.R.color.darker_gray)); + mSize = attr.getInt(R.styleable.FloatingActionButton_fab_size, SIZE_NORMAL); + mIcon = attr.getResourceId(R.styleable.FloatingActionButton_fab_icon, 0); + mTitle = attr.getString(R.styleable.FloatingActionButton_fab_title); + mStrokeVisible = attr.getBoolean(R.styleable.FloatingActionButton_fab_stroke_visible, true); + attr.recycle(); + + updateCircleSize(); + mShadowRadius = getDimension(R.dimen.fab_shadow_radius); + mShadowOffset = getDimension(R.dimen.fab_shadow_offset); + updateDrawableSize(); + + updateBackground(); + } + + private void updateDrawableSize() { + mDrawableSize = (int) (mCircleSize + 2 * mShadowRadius); + } + + private void updateCircleSize() { + mCircleSize = getDimension(mSize == SIZE_NORMAL ? R.dimen.fab_size_normal : R.dimen.fab_size_mini); + } + + @FAB_SIZE + public int getSize() { + return mSize; + } + + public void setSize(@FAB_SIZE final int size) { + if (size != SIZE_MINI && size != SIZE_NORMAL) { + throw new IllegalArgumentException("Use @FAB_SIZE constants only!"); + } + + if (mSize != size) { + mSize = size; + updateCircleSize(); + updateDrawableSize(); + updateBackground(); + } + } + + public void setIcon(@DrawableRes final int icon) { + if (mIcon != icon) { + mIcon = icon; + mIconDrawable = null; + updateBackground(); + } + } + + /** + * @return the current Color for normal state. + */ + public int getColorNormal() { + return mColorNormal; + } + + public void setColorNormal(final int color) { + if (mColorNormal != color) { + mColorNormal = color; + updateBackground(); + } + } + + public void setColorNormalResId(@ColorRes final int colorNormal) { + setColorNormal(getColor(colorNormal)); + } + + /** + * @return the current color for pressed state. + */ + public int getColorPressed() { + return mColorPressed; + } + + public void setColorPressed(final int color) { + if (mColorPressed != color) { + mColorPressed = color; + updateBackground(); + } + } + + public void setColorPressedResId(@ColorRes final int colorPressed) { + setColorPressed(getColor(colorPressed)); + } + + /** + * @return the current color for disabled state. + */ + public int getColorDisabled() { + return mColorDisabled; + } + + public void setColorDisabled(final int color) { + if (mColorDisabled != color) { + mColorDisabled = color; + updateBackground(); + } + } + + public void setColorDisabledResId(@ColorRes final int colorDisabled) { + setColorDisabled(getColor(colorDisabled)); + } + + public boolean isStrokeVisible() { + return mStrokeVisible; + } + + public void setStrokeVisible(final boolean visible) { + if (mStrokeVisible != visible) { + mStrokeVisible = visible; + updateBackground(); + } + } + + int getColor(@ColorRes final int id) { + return getResources().getColor(id); + } + + float getDimension(@DimenRes final int id) { + return getResources().getDimension(id); + } + + TextView getLabelView() { + return (TextView) getTag(R.id.fab_label); + } + + public String getTitle() { + return mTitle; + } + + public void setTitle(final String title) { + mTitle = title; + final TextView label = getLabelView(); + if (label != null) { + label.setText(title); + } + } + + @Override + protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + setMeasuredDimension(mDrawableSize, mDrawableSize); + } + + void updateBackground() { + final float strokeWidth = getDimension(R.dimen.fab_stroke_width); + final float halfStrokeWidth = strokeWidth / 2f; + + final LayerDrawable layerDrawable = new LayerDrawable( + new Drawable[]{ + getResources().getDrawable(mSize == SIZE_NORMAL ? R.drawable.fab_bg_normal : R.drawable.fab_bg_mini, null), + createFillDrawable(strokeWidth), + createOuterStrokeDrawable(strokeWidth), + getIconDrawable() + }); + + final int iconOffset = (int) (mCircleSize - getDimension(R.dimen.fab_icon_size)) / 2; + + final int circleInsetHorizontal = (int) (mShadowRadius); + final int circleInsetTop = (int) (mShadowRadius - mShadowOffset); + final int circleInsetBottom = (int) (mShadowRadius + mShadowOffset); + + layerDrawable.setLayerInset(1, + circleInsetHorizontal, + circleInsetTop, + circleInsetHorizontal, + circleInsetBottom); + + layerDrawable.setLayerInset(2, + (int) (circleInsetHorizontal - halfStrokeWidth), + (int) (circleInsetTop - halfStrokeWidth), + (int) (circleInsetHorizontal - halfStrokeWidth), + (int) (circleInsetBottom - halfStrokeWidth)); + + layerDrawable.setLayerInset(3, + circleInsetHorizontal + iconOffset, + circleInsetTop + iconOffset, + circleInsetHorizontal + iconOffset, + circleInsetBottom + iconOffset); + + setBackground(layerDrawable); + } + + Drawable getIconDrawable() { + if (mIconDrawable != null) { + return mIconDrawable; + } else if (mIcon != 0) { + return getResources().getDrawable(mIcon, null); + } else { + return new ColorDrawable(Color.TRANSPARENT); + } + } + + public void setIconDrawable(@NonNull final Drawable iconDrawable) { + if (mIconDrawable != iconDrawable) { + mIcon = 0; + mIconDrawable = iconDrawable; + updateBackground(); + } + } + + private StateListDrawable createFillDrawable(final float strokeWidth) { + final StateListDrawable drawable = new StateListDrawable(); + drawable.addState(new int[]{-android.R.attr.state_enabled}, createCircleDrawable(mColorDisabled, strokeWidth)); + drawable.addState(new int[]{android.R.attr.state_pressed}, createCircleDrawable(mColorPressed, strokeWidth)); + drawable.addState(new int[]{}, createCircleDrawable(mColorNormal, strokeWidth)); + return drawable; + } + + private Drawable createCircleDrawable(final int color, final float strokeWidth) { + final int alpha = Color.alpha(color); + final int opaqueColor = opaque(color); + + final ShapeDrawable fillDrawable = new ShapeDrawable(new OvalShape()); + + final Paint paint = fillDrawable.getPaint(); + paint.setAntiAlias(true); + paint.setColor(opaqueColor); + + final Drawable[] layers = { + fillDrawable, + createInnerStrokesDrawable(opaqueColor, strokeWidth) + }; + + final LayerDrawable drawable = alpha == 255 || !mStrokeVisible + ? new LayerDrawable(layers) + : new TranslucentLayerDrawable(alpha, layers); + + final int halfStrokeWidth = (int) (strokeWidth / 2f); + drawable.setLayerInset(1, halfStrokeWidth, halfStrokeWidth, halfStrokeWidth, halfStrokeWidth); + + return drawable; + } + + private Drawable createOuterStrokeDrawable(final float strokeWidth) { + final ShapeDrawable shapeDrawable = new ShapeDrawable(new OvalShape()); + + final Paint paint = shapeDrawable.getPaint(); + paint.setAntiAlias(true); + paint.setStrokeWidth(strokeWidth); + paint.setStyle(Style.STROKE); + paint.setColor(Color.BLACK); + paint.setAlpha(opacityToAlpha(0.02f)); + + return shapeDrawable; + } + + private int opacityToAlpha(final float opacity) { + return (int) (255f * opacity); + } + + private int darkenColor(final int argb) { + return adjustColorBrightness(argb, 0.9f); + } + + private int lightenColor(final int argb) { + return adjustColorBrightness(argb, 1.1f); + } + + private int adjustColorBrightness(final int argb, final float factor) { + final float[] hsv = new float[3]; + Color.colorToHSV(argb, hsv); + + hsv[2] = Math.min(hsv[2] * factor, 1f); + + return Color.HSVToColor(Color.alpha(argb), hsv); + } + + private int halfTransparent(final int argb) { + return Color.argb( + Color.alpha(argb) / 2, + Color.red(argb), + Color.green(argb), + Color.blue(argb) + ); + } + + private int opaque(final int argb) { + return Color.rgb( + Color.red(argb), + Color.green(argb), + Color.blue(argb) + ); + } + + private Drawable createInnerStrokesDrawable(final int color, final float strokeWidth) { + if (!mStrokeVisible) { + return new ColorDrawable(Color.TRANSPARENT); + } + + final ShapeDrawable shapeDrawable = new ShapeDrawable(new OvalShape()); + + final int bottomStrokeColor = darkenColor(color); + final int bottomStrokeColorHalfTransparent = halfTransparent(bottomStrokeColor); + final int topStrokeColor = lightenColor(color); + final int topStrokeColorHalfTransparent = halfTransparent(topStrokeColor); + + final Paint paint = shapeDrawable.getPaint(); + paint.setAntiAlias(true); + paint.setStrokeWidth(strokeWidth); + paint.setStyle(Style.STROKE); + shapeDrawable.setShaderFactory(new ShaderFactory() { + @Override + public Shader resize(int width, int height) { + return new LinearGradient(width / 2, 0, width / 2, height, + new int[]{topStrokeColor, topStrokeColorHalfTransparent, color, bottomStrokeColorHalfTransparent, bottomStrokeColor}, + new float[]{0f, 0.2f, 0.5f, 0.8f, 1f}, + TileMode.CLAMP + ); + } + }); + + return shapeDrawable; + } + + @Override + public void setVisibility(final int visibility) { + final TextView label = getLabelView(); + if (label != null) { + label.setVisibility(visibility); + } + + super.setVisibility(visibility); + } + + @Retention(RetentionPolicy.SOURCE) + @IntDef({SIZE_NORMAL, SIZE_MINI}) + public @interface FAB_SIZE { + } + + private static class TranslucentLayerDrawable extends LayerDrawable { + private final int mAlpha; + + public TranslucentLayerDrawable(final int alpha, final Drawable... layers) { + super(layers); + mAlpha = alpha; + } + + @Override + public void draw(final Canvas canvas) { + final Rect bounds = getBounds(); + canvas.saveLayerAlpha(bounds.left, bounds.top, bounds.right, bounds.bottom, mAlpha); + super.draw(canvas); + canvas.restore(); + } + } +} diff --git a/app/src/main/java/com/wireguard/android/widget/fab/FloatingActionsMenu.java b/app/src/main/java/com/wireguard/android/widget/fab/FloatingActionsMenu.java new file mode 100644 index 00000000..8c270266 --- /dev/null +++ b/app/src/main/java/com/wireguard/android/widget/fab/FloatingActionsMenu.java @@ -0,0 +1,643 @@ +/* + * Copyright © 2014 Jerzy Chalupski + * Copyright © 2018 Jason A. Donenfeld . All Rights Reserved. + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +package com.wireguard.android.widget.fab; + +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.animation.AnimatorSet; +import android.animation.ObjectAnimator; +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Canvas; +import android.graphics.Rect; +import android.graphics.drawable.Drawable; +import android.graphics.drawable.LayerDrawable; +import android.os.Parcel; +import android.os.Parcelable; +import android.support.annotation.ColorRes; +import android.support.annotation.NonNull; +import android.util.AttributeSet; +import android.view.ContextThemeWrapper; +import android.view.TouchDelegate; +import android.view.View; +import android.view.ViewGroup; +import android.view.animation.DecelerateInterpolator; +import android.view.animation.Interpolator; +import android.view.animation.OvershootInterpolator; +import android.widget.TextView; + +import com.wireguard.android.R; + +public class FloatingActionsMenu extends ViewGroup { + public static final int EXPAND_UP = 0; + public static final int EXPAND_DOWN = 1; + public static final int EXPAND_LEFT = 2; + public static final int EXPAND_RIGHT = 3; + + public static final int LABELS_ON_LEFT_SIDE = 0; + public static final int LABELS_ON_RIGHT_SIDE = 1; + + private static final int ANIMATION_DURATION = 300; + private static final float COLLAPSED_PLUS_ROTATION = 0f; + private static final float EXPANDED_PLUS_ROTATION = 90f + 45f; + private static final Interpolator sExpandInterpolator = new OvershootInterpolator(); + private static final Interpolator sCollapseInterpolator = new DecelerateInterpolator(3f); + private static final Interpolator sAlphaExpandInterpolator = new DecelerateInterpolator(); + private int mAddButtonPlusColor; + private int mAddButtonColorNormal; + private int mAddButtonColorPressed; + private int mAddButtonSize; + private boolean mAddButtonStrokeVisible; + private int mExpandDirection; + private int mButtonSpacing; + private int mLabelsMargin; + private int mLabelsVerticalOffset; + private boolean mExpanded; + private final AnimatorSet mExpandAnimation = new AnimatorSet().setDuration(ANIMATION_DURATION); + private final AnimatorSet mCollapseAnimation = new AnimatorSet().setDuration(ANIMATION_DURATION); + private AddFloatingActionButton mAddButton; + private RotatingDrawable mRotatingDrawable; + private int mMaxButtonWidth; + private int mMaxButtonHeight; + private int mLabelsStyle; + private int mLabelsPosition; + private int mButtonsCount; + private TouchDelegateGroup mTouchDelegateGroup; + private OnFloatingActionsMenuUpdateListener mListener; + private final Rect touchArea = new Rect(0, 0, 0, 0); + + public FloatingActionsMenu(final Context context) { + this(context, null); + } + + public FloatingActionsMenu(final Context context, AttributeSet attrs) { + super(context, attrs); + init(context, attrs); + } + + public FloatingActionsMenu(final Context context, final AttributeSet attrs, final int defStyle) { + super(context, attrs, defStyle); + init(context, attrs); + } + + private void init(final Context context, final AttributeSet attributeSet) { + mButtonSpacing = (int) (getResources().getDimension(R.dimen.fab_actions_spacing) - getResources().getDimension(R.dimen.fab_shadow_radius) - getResources().getDimension(R.dimen.fab_shadow_offset)); + mLabelsMargin = getResources().getDimensionPixelSize(R.dimen.fab_labels_margin); + mLabelsVerticalOffset = getResources().getDimensionPixelSize(R.dimen.fab_shadow_offset); + + mTouchDelegateGroup = new TouchDelegateGroup(this); + setTouchDelegate(mTouchDelegateGroup); + + final TypedArray attr = context.obtainStyledAttributes(attributeSet, R.styleable.FloatingActionsMenu, 0, 0); + mAddButtonPlusColor = attr.getColor(R.styleable.FloatingActionsMenu_fab_addButtonPlusIconColor, getColor(android.R.color.white)); + mAddButtonColorNormal = attr.getColor(R.styleable.FloatingActionsMenu_fab_addButtonColorNormal, getColor(android.R.color.holo_blue_dark)); + mAddButtonColorPressed = attr.getColor(R.styleable.FloatingActionsMenu_fab_addButtonColorPressed, getColor(android.R.color.holo_blue_light)); + mAddButtonSize = attr.getInt(R.styleable.FloatingActionsMenu_fab_addButtonSize, FloatingActionButton.SIZE_NORMAL); + mAddButtonStrokeVisible = attr.getBoolean(R.styleable.FloatingActionsMenu_fab_addButtonStrokeVisible, true); + mExpandDirection = attr.getInt(R.styleable.FloatingActionsMenu_fab_expandDirection, EXPAND_UP); + mLabelsStyle = attr.getResourceId(R.styleable.FloatingActionsMenu_fab_labelStyle, 0); + mLabelsPosition = attr.getInt(R.styleable.FloatingActionsMenu_fab_labelsPosition, LABELS_ON_LEFT_SIDE); + attr.recycle(); + + if (mLabelsStyle != 0 && expandsHorizontally()) { + throw new IllegalStateException("Action labels in horizontal expand orientation is not supported."); + } + + createAddButton(context); + } + + public void setOnFloatingActionsMenuUpdateListener(final OnFloatingActionsMenuUpdateListener listener) { + mListener = listener; + } + + private boolean expandsHorizontally() { + return mExpandDirection == EXPAND_LEFT || mExpandDirection == EXPAND_RIGHT; + } + + private void createAddButton(final Context context) { + mAddButton = new AddFloatingActionButton(context) { + @Override + void updateBackground() { + mPlusColor = mAddButtonPlusColor; + mColorNormal = mAddButtonColorNormal; + mColorPressed = mAddButtonColorPressed; + mStrokeVisible = mAddButtonStrokeVisible; + super.updateBackground(); + } + + @Override + Drawable getIconDrawable() { + final RotatingDrawable rotatingDrawable = new RotatingDrawable(super.getIconDrawable()); + mRotatingDrawable = rotatingDrawable; + + final OvershootInterpolator interpolator = new OvershootInterpolator(); + + final ObjectAnimator collapseAnimator = ObjectAnimator.ofFloat(rotatingDrawable, "rotation", EXPANDED_PLUS_ROTATION, COLLAPSED_PLUS_ROTATION); + final ObjectAnimator expandAnimator = ObjectAnimator.ofFloat(rotatingDrawable, "rotation", COLLAPSED_PLUS_ROTATION, EXPANDED_PLUS_ROTATION); + + collapseAnimator.setInterpolator(interpolator); + expandAnimator.setInterpolator(interpolator); + + mExpandAnimation.play(expandAnimator); + mCollapseAnimation.play(collapseAnimator); + + return rotatingDrawable; + } + }; + + mAddButton.setId(R.id.fab_expand_menu_button); + mAddButton.setSize(mAddButtonSize); + mAddButton.setOnClickListener(new OnClickListener() { + @Override + public void onClick(View v) { + toggle(); + } + }); + + addView(mAddButton, super.generateDefaultLayoutParams()); + mButtonsCount++; + } + + public void addButton(final FloatingActionButton button) { + addView(button, mButtonsCount - 1); + mButtonsCount++; + + if (mLabelsStyle != 0) { + createLabels(); + } + } + + public void removeButton(final FloatingActionButton button) { + removeView(button.getLabelView()); + removeView(button); + button.setTag(R.id.fab_label, null); + mButtonsCount--; + } + + private int getColor(@ColorRes final int id) { + return getResources().getColor(id); + } + + @Override + protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) { + measureChildren(widthMeasureSpec, heightMeasureSpec); + + int width = 0; + int height = 0; + + mMaxButtonWidth = 0; + mMaxButtonHeight = 0; + int maxLabelWidth = 0; + + for (int i = 0; i < mButtonsCount; i++) { + View child = getChildAt(i); + + if (child.getVisibility() == GONE) { + continue; + } + + switch (mExpandDirection) { + case EXPAND_UP: + case EXPAND_DOWN: + mMaxButtonWidth = Math.max(mMaxButtonWidth, child.getMeasuredWidth()); + height += child.getMeasuredHeight(); + break; + case EXPAND_LEFT: + case EXPAND_RIGHT: + width += child.getMeasuredWidth(); + mMaxButtonHeight = Math.max(mMaxButtonHeight, child.getMeasuredHeight()); + break; + } + + if (!expandsHorizontally()) { + TextView label = (TextView) child.getTag(R.id.fab_label); + if (label != null) { + maxLabelWidth = Math.max(maxLabelWidth, label.getMeasuredWidth()); + } + } + } + + if (!expandsHorizontally()) { + width = mMaxButtonWidth + (maxLabelWidth > 0 ? maxLabelWidth + mLabelsMargin : 0); + } else { + height = mMaxButtonHeight; + } + + switch (mExpandDirection) { + case EXPAND_UP: + case EXPAND_DOWN: + height += mButtonSpacing * (mButtonsCount - 1); + height = adjustForOvershoot(height); + break; + case EXPAND_LEFT: + case EXPAND_RIGHT: + width += mButtonSpacing * (mButtonsCount - 1); + width = adjustForOvershoot(width); + break; + } + + setMeasuredDimension(width, height); + } + + private int adjustForOvershoot(final int dimension) { + return dimension * 12 / 10; + } + + @Override + protected void onLayout(final boolean changed, final int l, final int t, final int r, final int b) { + switch (mExpandDirection) { + case EXPAND_UP: + case EXPAND_DOWN: + final boolean expandUp = mExpandDirection == EXPAND_UP; + + if (changed) { + mTouchDelegateGroup.clearTouchDelegates(); + } + + final int addButtonY = expandUp ? b - t - mAddButton.getMeasuredHeight() : 0; + // Ensure mAddButton is centered on the line where the buttons should be + final int buttonsHorizontalCenter = mLabelsPosition == LABELS_ON_LEFT_SIDE + ? r - l - mMaxButtonWidth / 2 + : mMaxButtonWidth / 2; + final int addButtonLeft = buttonsHorizontalCenter - mAddButton.getMeasuredWidth() / 2; + mAddButton.layout(addButtonLeft, addButtonY, addButtonLeft + mAddButton.getMeasuredWidth(), addButtonY + mAddButton.getMeasuredHeight()); + + final int labelsOffset = mMaxButtonWidth / 2 + mLabelsMargin; + final int labelsXNearButton = mLabelsPosition == LABELS_ON_LEFT_SIDE + ? buttonsHorizontalCenter - labelsOffset + : buttonsHorizontalCenter + labelsOffset; + + int nextY = expandUp ? + addButtonY - mButtonSpacing : + addButtonY + mAddButton.getMeasuredHeight() + mButtonSpacing; + + for (int i = mButtonsCount - 1; i >= 0; i--) { + final View child = getChildAt(i); + + if (child == mAddButton || child.getVisibility() == GONE) continue; + + final int childX = buttonsHorizontalCenter - child.getMeasuredWidth() / 2; + final int childY = expandUp ? nextY - child.getMeasuredHeight() : nextY; + child.layout(childX, childY, childX + child.getMeasuredWidth(), childY + child.getMeasuredHeight()); + + final float collapsedTranslation = addButtonY - childY; + final float expandedTranslation = 0f; + + child.setTranslationY(mExpanded ? expandedTranslation : collapsedTranslation); + child.setAlpha(mExpanded ? 1f : 0f); + + LayoutParams params = (LayoutParams) child.getLayoutParams(); + params.mCollapseDir.setFloatValues(expandedTranslation, collapsedTranslation); + params.mExpandDir.setFloatValues(collapsedTranslation, expandedTranslation); + params.setAnimationsTarget(child); + + final View label = (View) child.getTag(R.id.fab_label); + if (label != null) { + final int labelXAwayFromButton = mLabelsPosition == LABELS_ON_LEFT_SIDE + ? labelsXNearButton - label.getMeasuredWidth() + : labelsXNearButton + label.getMeasuredWidth(); + + final int labelLeft = mLabelsPosition == LABELS_ON_LEFT_SIDE + ? labelXAwayFromButton + : labelsXNearButton; + + final int labelRight = mLabelsPosition == LABELS_ON_LEFT_SIDE + ? labelsXNearButton + : labelXAwayFromButton; + + final int labelTop = childY - mLabelsVerticalOffset + (child.getMeasuredHeight() - label.getMeasuredHeight()) / 2; + + label.layout(labelLeft, labelTop, labelRight, labelTop + label.getMeasuredHeight()); + + touchArea.set(Math.min(childX, labelLeft), + childY - mButtonSpacing / 2, + Math.max(childX + child.getMeasuredWidth(), labelRight), + childY + child.getMeasuredHeight() + mButtonSpacing / 2); + mTouchDelegateGroup.addTouchDelegate(new TouchDelegate(touchArea, child)); + + label.setTranslationY(mExpanded ? expandedTranslation : collapsedTranslation); + label.setAlpha(mExpanded ? 1f : 0f); + + LayoutParams labelParams = (LayoutParams) label.getLayoutParams(); + labelParams.mCollapseDir.setFloatValues(expandedTranslation, collapsedTranslation); + labelParams.mExpandDir.setFloatValues(collapsedTranslation, expandedTranslation); + labelParams.setAnimationsTarget(label); + } + + nextY = expandUp ? + childY - mButtonSpacing : + childY + child.getMeasuredHeight() + mButtonSpacing; + } + break; + + case EXPAND_LEFT: + case EXPAND_RIGHT: + final boolean expandLeft = mExpandDirection == EXPAND_LEFT; + + final int addButtonX = expandLeft ? r - l - mAddButton.getMeasuredWidth() : 0; + // Ensure mAddButton is centered on the line where the buttons should be + final int addButtonTop = b - t - mMaxButtonHeight + (mMaxButtonHeight - mAddButton.getMeasuredHeight()) / 2; + mAddButton.layout(addButtonX, addButtonTop, addButtonX + mAddButton.getMeasuredWidth(), addButtonTop + mAddButton.getMeasuredHeight()); + + int nextX = expandLeft ? + addButtonX - mButtonSpacing : + addButtonX + mAddButton.getMeasuredWidth() + mButtonSpacing; + + for (int i = mButtonsCount - 1; i >= 0; i--) { + final View child = getChildAt(i); + + if (child == mAddButton || child.getVisibility() == GONE) continue; + + final int childX = expandLeft ? nextX - child.getMeasuredWidth() : nextX; + final int childY = addButtonTop + (mAddButton.getMeasuredHeight() - child.getMeasuredHeight()) / 2; + child.layout(childX, childY, childX + child.getMeasuredWidth(), childY + child.getMeasuredHeight()); + + final float collapsedTranslation = addButtonX - childX; + final float expandedTranslation = 0f; + + child.setTranslationX(mExpanded ? expandedTranslation : collapsedTranslation); + child.setAlpha(mExpanded ? 1f : 0f); + + final LayoutParams params = (LayoutParams) child.getLayoutParams(); + params.mCollapseDir.setFloatValues(expandedTranslation, collapsedTranslation); + params.mExpandDir.setFloatValues(collapsedTranslation, expandedTranslation); + params.setAnimationsTarget(child); + + nextX = expandLeft ? + childX - mButtonSpacing : + childX + child.getMeasuredWidth() + mButtonSpacing; + } + + break; + } + } + + @Override + protected ViewGroup.LayoutParams generateDefaultLayoutParams() { + return new LayoutParams(super.generateDefaultLayoutParams()); + } + + @Override + public ViewGroup.LayoutParams generateLayoutParams(final AttributeSet attrs) { + return new LayoutParams(super.generateLayoutParams(attrs)); + } + + @Override + protected ViewGroup.LayoutParams generateLayoutParams(final ViewGroup.LayoutParams p) { + return new LayoutParams(super.generateLayoutParams(p)); + } + + @Override + protected boolean checkLayoutParams(final ViewGroup.LayoutParams p) { + return super.checkLayoutParams(p); + } + + @Override + protected void onFinishInflate() { + super.onFinishInflate(); + + bringChildToFront(mAddButton); + mButtonsCount = getChildCount(); + + if (mLabelsStyle != 0) { + createLabels(); + } + } + + private void createLabels() { + final Context context = new ContextThemeWrapper(getContext(), mLabelsStyle); + + for (int i = 0; i < mButtonsCount; i++) { + final FloatingActionButton button = (FloatingActionButton) getChildAt(i); + final String title = button.getTitle(); + + if (button == mAddButton || title == null || + button.getTag(R.id.fab_label) != null) continue; + + final TextView label = new TextView(context); + label.setTextAppearance(context, mLabelsStyle); + label.setText(button.getTitle()); + addView(label); + + button.setTag(R.id.fab_label, label); + } + } + + public void collapse() { + collapse(false); + } + + public void collapseImmediately() { + collapse(true); + } + + private void collapse(final boolean immediately) { + if (mExpanded) { + mExpanded = false; + mTouchDelegateGroup.setEnabled(false); + mCollapseAnimation.setDuration(immediately ? 0 : ANIMATION_DURATION); + mCollapseAnimation.start(); + mExpandAnimation.cancel(); + + if (mListener != null) { + mListener.onMenuCollapsed(); + } + } + } + + public void toggle() { + if (mExpanded) { + collapse(); + } else { + expand(); + } + } + + public void expand() { + if (!mExpanded) { + mExpanded = true; + mTouchDelegateGroup.setEnabled(true); + mCollapseAnimation.cancel(); + mExpandAnimation.start(); + + if (mListener != null) { + mListener.onMenuExpanded(); + } + } + } + + public boolean isExpanded() { + return mExpanded; + } + + @Override + public void setEnabled(boolean enabled) { + super.setEnabled(enabled); + + mAddButton.setEnabled(enabled); + } + + @Override + public Parcelable onSaveInstanceState() { + final Parcelable superState = super.onSaveInstanceState(); + final SavedState savedState = new SavedState(superState); + savedState.mExpanded = mExpanded; + + return savedState; + } + + @Override + public void onRestoreInstanceState(final Parcelable state) { + if (state instanceof SavedState) { + final SavedState savedState = (SavedState) state; + mExpanded = savedState.mExpanded; + mTouchDelegateGroup.setEnabled(mExpanded); + + if (mRotatingDrawable != null) { + mRotatingDrawable.setRotation(mExpanded ? EXPANDED_PLUS_ROTATION : COLLAPSED_PLUS_ROTATION); + } + + super.onRestoreInstanceState(savedState.getSuperState()); + } else { + super.onRestoreInstanceState(state); + } + } + + public interface OnFloatingActionsMenuUpdateListener { + void onMenuExpanded(); + + void onMenuCollapsed(); + } + + private static class RotatingDrawable extends LayerDrawable { + private float mRotation; + + RotatingDrawable(final Drawable drawable) { + super(new Drawable[]{drawable}); + } + + @SuppressWarnings("UnusedDeclaration") + public float getRotation() { + return mRotation; + } + + @SuppressWarnings("UnusedDeclaration") + public void setRotation(final float rotation) { + mRotation = rotation; + invalidateSelf(); + } + + @Override + public void draw(final Canvas canvas) { + canvas.save(); + canvas.rotate(mRotation, getBounds().centerX(), getBounds().centerY()); + super.draw(canvas); + canvas.restore(); + } + } + + public static class SavedState extends BaseSavedState { + public static final Creator CREATOR = new Creator() { + + @Override + public SavedState createFromParcel(Parcel in) { + return new SavedState(in); + } + + @Override + public SavedState[] newArray(int size) { + return new SavedState[size]; + } + }; + public boolean mExpanded; + + public SavedState(final Parcelable parcel) { + super(parcel); + } + + private SavedState(final Parcel in) { + super(in); + mExpanded = in.readInt() == 1; + } + + @Override + public void writeToParcel(@NonNull final Parcel out, final int flags) { + super.writeToParcel(out, flags); + out.writeInt(mExpanded ? 1 : 0); + } + } + + private class LayoutParams extends ViewGroup.LayoutParams { + + private final ObjectAnimator mExpandDir = new ObjectAnimator(); + private final ObjectAnimator mExpandAlpha = new ObjectAnimator(); + private final ObjectAnimator mCollapseDir = new ObjectAnimator(); + private final ObjectAnimator mCollapseAlpha = new ObjectAnimator(); + private boolean animationsSetToPlay; + + LayoutParams(final ViewGroup.LayoutParams source) { + super(source); + + mExpandDir.setInterpolator(sExpandInterpolator); + mExpandAlpha.setInterpolator(sAlphaExpandInterpolator); + mCollapseDir.setInterpolator(sCollapseInterpolator); + mCollapseAlpha.setInterpolator(sCollapseInterpolator); + + mCollapseAlpha.setProperty(View.ALPHA); + mCollapseAlpha.setFloatValues(1f, 0f); + + mExpandAlpha.setProperty(View.ALPHA); + mExpandAlpha.setFloatValues(0f, 1f); + + switch (mExpandDirection) { + case EXPAND_UP: + case EXPAND_DOWN: + mCollapseDir.setProperty(View.TRANSLATION_Y); + mExpandDir.setProperty(View.TRANSLATION_Y); + break; + case EXPAND_LEFT: + case EXPAND_RIGHT: + mCollapseDir.setProperty(View.TRANSLATION_X); + mExpandDir.setProperty(View.TRANSLATION_X); + break; + } + } + + public void setAnimationsTarget(final View view) { + mCollapseAlpha.setTarget(view); + mCollapseDir.setTarget(view); + mExpandAlpha.setTarget(view); + mExpandDir.setTarget(view); + + // Now that the animations have targets, set them to be played + if (!animationsSetToPlay) { + addLayerTypeListener(mExpandDir, view); + addLayerTypeListener(mCollapseDir, view); + + mCollapseAnimation.play(mCollapseAlpha); + mCollapseAnimation.play(mCollapseDir); + mExpandAnimation.play(mExpandAlpha); + mExpandAnimation.play(mExpandDir); + animationsSetToPlay = true; + } + } + + private void addLayerTypeListener(final Animator animator, final View view) { + animator.addListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(final Animator animation) { + view.setLayerType(LAYER_TYPE_NONE, null); + } + + @Override + public void onAnimationStart(final Animator animation) { + view.setLayerType(LAYER_TYPE_HARDWARE, null); + } + }); + } + } +} diff --git a/app/src/main/java/com/wireguard/android/widget/fab/TouchDelegateGroup.java b/app/src/main/java/com/wireguard/android/widget/fab/TouchDelegateGroup.java new file mode 100644 index 00000000..9aa221ed --- /dev/null +++ b/app/src/main/java/com/wireguard/android/widget/fab/TouchDelegateGroup.java @@ -0,0 +1,78 @@ +/* + * Copyright © 2014 Jerzy Chalupski + * Copyright © 2018 Jason A. Donenfeld . All Rights Reserved. + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +package com.wireguard.android.widget.fab; + +import android.graphics.Rect; +import android.support.annotation.NonNull; +import android.view.MotionEvent; +import android.view.TouchDelegate; +import android.view.View; + +import java.util.ArrayList; +import java.util.List; + +public class TouchDelegateGroup extends TouchDelegate { + private static final Rect USELESS_HACKY_RECT = new Rect(); + private final List mTouchDelegates = new ArrayList<>(); + private TouchDelegate mCurrentTouchDelegate; + private boolean mEnabled; + + public TouchDelegateGroup(final View uselessHackyView) { + super(USELESS_HACKY_RECT, uselessHackyView); + } + + public void addTouchDelegate(@NonNull final TouchDelegate touchDelegate) { + mTouchDelegates.add(touchDelegate); + } + + public void removeTouchDelegate(final TouchDelegate touchDelegate) { + mTouchDelegates.remove(touchDelegate); + if (mCurrentTouchDelegate == touchDelegate) { + mCurrentTouchDelegate = null; + } + } + + public void clearTouchDelegates() { + mTouchDelegates.clear(); + mCurrentTouchDelegate = null; + } + + @Override + public boolean onTouchEvent(@NonNull final MotionEvent event) { + if (!mEnabled) return false; + + TouchDelegate delegate = null; + + switch (event.getAction()) { + case MotionEvent.ACTION_DOWN: + for (int i = 0; i < mTouchDelegates.size(); i++) { + final TouchDelegate touchDelegate = mTouchDelegates.get(i); + if (touchDelegate.onTouchEvent(event)) { + mCurrentTouchDelegate = touchDelegate; + return true; + } + } + break; + + case MotionEvent.ACTION_MOVE: + delegate = mCurrentTouchDelegate; + break; + + case MotionEvent.ACTION_CANCEL: + case MotionEvent.ACTION_UP: + delegate = mCurrentTouchDelegate; + mCurrentTouchDelegate = null; + break; + } + + return delegate != null && delegate.onTouchEvent(event); + } + + public void setEnabled(final boolean enabled) { + mEnabled = enabled; + } +} diff --git a/app/src/main/res/drawable-hdpi/fab_bg_mini.png b/app/src/main/res/drawable-hdpi/fab_bg_mini.png new file mode 100644 index 0000000000000000000000000000000000000000..4b48351c279f621f1f50858093b0f4dbee5cdf16 GIT binary patch literal 3519 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-mdpi/fab_bg_mini.png b/app/src/main/res/drawable-mdpi/fab_bg_mini.png new file mode 100644 index 0000000000000000000000000000000000000000..218cf044c1da028e537e83c8460654791c366cbc GIT binary patch literal 1547 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 literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xxhdpi/fab_bg_normal.png b/app/src/main/res/drawable-xxhdpi/fab_bg_normal.png new file mode 100644 index 0000000000000000000000000000000000000000..14608fff5052376d4cce68da91a3a208429640cb GIT binary patch literal 6114 zcma)AWmJ?=*CnMpq`On3TaX;OL1F;uR%(=X2x*X#7?3V0K}x!%J0+!to}r}VeZJSV z-rwI{YtHPmpZlD%&%XE1Oth}HDgiDHE(!_?fx4QKKJdNve;;ggAlkQRN1&jf&Fg9! zDg){Nf7RC3?(OZJot<4=TwGmU{rU6f_VyMIhfhvU9v&W!jg0{$!2Bz?y1IIKc?qQD z<>d$jVtadgcX#*r_!xNW--e-~q3i4G^YinYo13MjB_IMkQ0M6AC@(LsprBxWetuzL z0q6+u2L}g01PTImrl+ST2KwhlhuOOI1}>^-sK}rY7(xBO~LV z=kMOV`}yAmknQd5D=RC&2H;S##kp+&3hAS-ZGeJ`hK_-Wg^h!YhfhFA#BFYGYc5Un zO5XN`0V6SquDJlOy}7xA3>m4Snk|u@0J(z$Kfk`79fc#Mft{hyv!?>N!SPiwE?Kos)?OZwS?X9@D zW!QOm`S|q(1g)$b9NgWVom7;CWIWtWOoSPq8+mw`iV9eX*olF~-P|-aC5+r9Wn{d( zq`jovWz}V@h@2ed1e~2-fUV@;7zyaRD0shBd~2j+>}ssyZKvw&u51rd^Oo^u^fp$1 z1@f@AcJT4m@O3u#KANzcK|vw=sjj482thrX5~V>`z<;@EA9(yHt=Ft32>(^Oj4hvhoESk^#=ux5HQA^5($yKCC zo<>GP-SrkbPNRp7x@eP%ciD z$?Qg7TY zkk~@eMjuQ}$mu?KXHGbBX_;#Li_HBw%ne;G)7Uv&E%kKT@ zS7_I=Ozdi<_+qB_8G??+QTt`-*^tZQ)33G*#WDIX?ZY}5Hq3;41ugx5-1Rs4nQJG7 zI^x~uCA^1MUq`J69@nlnFLbQ$WQ^p0Hl;6+eh#KrbH`Bd8p_1d)lcKiH zIY5GoDm{;&%Y;_@thwb%#od2>!-Y3=FI8;$a4@hrV!c+H&>Qm9PPjT0Hc2!sdBj2R zgZcp1;WN0Da1w`tiY)9#PRCO5FVsZ5theTP8L?yrm%E)6{gc;5Cl%a)eybquATAcE zi6eJ6tNbSqnp2MLrrXhZvDY6n$JZjH0;rXt50!bE*oKG3Aiv?^D#91Pre$OnU^ zVK{z>P(qOX0jdKiecjaj0WRfDmyhNr`=W(>5yd?_*lldV@aIJg{U3_Oykj_4BZoBE zQOv9`xn;-)FgTzADjYCMc#me%Y5Y6IzeJ0o*CXtG3}zJL!pp;aNz!Y2efz1>+#aw} zNAuq!PdFyp550OLTR#oCORB%mPl)c~e%D|23cE9;8b-WNh}pVVlI_Z^svn{9vnLG| z9G$pVr4!_*%Y7hen;zzg?#lWgKWJWo#c4dixjE{ar_{9`8cdfb(OFU@`J86q-8^sE z7%q;2eK9#Cv-~r7=BmLpqAC+_c9=4{`wGw zuC~f>TpUGv1B!#IZ9k{^EQ2Kr1vo!x1bqq7ApdUTxjTzOXvsGI|(S%;=_zLmN1noPiu{vD^%~f1TR0Gnc zW8Lezjrc7!&cHjT z(o$Lh_5PQIj8&hkztU%V4DNNEXtJz*B$>cVB@`4;e-2Y1d!4wuo7JymuV0Lt zx1{{Sx!Dehncv^}+`Z^Q5N95aXmftq6QKM$wvUJo{|y)GS&wqr>&#CU*Mm#71#uuC zb*meOU{=qBzf5~Ftt(;$Tt{oi;Eki1`dI`=yLfe3VHz!^=`%g3ZDlAqW|mq`f=Gq< zK)e_o)`>FaN&9`_Xuqz`hY{9o^6{Jv#z4olwt)5i(XY@|@`|Jz&7ii4co*O5N+Z~t zL8R5|))wWUw)9;!S}{FeBxF`x`L$3}d1BMpFI@Mss-x|a1<%E}WlhId8BS;4jVry; z&0*n9tyzi1jbcsk(1mmb?`TCFB?meNcUh|Ey>1JrHLIH99Z_mY>w)JapXey3$Bd&0 zA@n6-<$n36c4yms;Z=^W1P?;53oz|HO(iH0-?<%`d+%+dDf8IH*LMjHhm7U@KE+Qc zMt;{IYO^c}8@tADy0M)>BmGtq_uZVRZ51(wCFAhwh2s+P70>FgrD80rrn#Jwe4=ck zp1*8*87X{H8jgt!5ZUxh?e=*lgxXE>IFd#xb~PW%D$3p?ehYFR6HLl5_C9%2$?@mz zMc0V$RY6nIvE7;7?^GE3V*vw1a5=peHiYiF$qcjVRCkkwq~DWj$*l~F=&>Ne^HE!w z1|xW^9P! zU3WD5wtkZTY`|OISlTs?Zb~?lSb_>%I9xl0I~qoK9v{4dumvbvo?R`rs~pG@M zObBdwvpY@pN)>&xDq$0DTb_qoGcjk+1PX0BdW^a*W`KZY?cbctp`RX>_T8xvwRuX) zs8Dsxpq~a1CMI7pUUc1&K)m?BpADs|Pr%^_y#CiRoQ~z~c|Kit&dCrF;&-na#@nrs zVc0WL@%3vHQX3CjQdExXaf$Wc5x8qLK)!p$kIiaa1)^hbDGt7b-(p#ShCg#fpCx$@ zGfnanR3wT^=*FGdjkh%V#r<#=81Ti4oE@a4glNW%grD_?kz68zFLBMBUr~miX)r=f zzVrXN<_pOuZ<`XDgAahLx*PFtBR<_@QJoDK4blp})81mVo|RgMK9^YQD>{IrpnHHF zi|~pL)I;R1TZ+GJO;5@nw7jdV!231fC`Bz4;==@{qk6DJEYn@anB~NMq^CD+O_g<~ zgCRU4J@wk9I5j-FPvZ5*9pSpvA#PFcV=d1>cd6Cme}m9_-ejq~K7K8Y5Vqgvhb4&X zuGKtW3q!up^P_yXA4BJO%<65f6&F~DWi%iya$sZl6jrRjkjX0ZSH=&L-YCi7vK0x&zTYdW*+pJr-Kof$ zQnuQ?R8Xqo)t?g~9u}yWk*{W1d(#=W%r^3&%7o0*#^Q;6R8=(wuGmCjm=m9JIovS& z{z3LrWQ!8ZjB9MZ=X!L?!6uAcdIGwhYO=tM&L&eLwJm2|81n$=SOOFRjII(KrzVcD(98Y-uM$miUMM8tL*SW@R5oy$ldD;LFss9g#RWv zT`Vg;wdIkO*3%zkYe(tJNrJdwdQGiLCGj8-U+&(Qy1we2nJpm*ThL-qL!dCv=Gc?J zWl26OsU~Fo?T%Ry=^XD!(G5rjBDvm%A@EDcc_z*cIC&JO>tSOTY)>}XgWa$?Xr?`` zZEnWHXNFT9s0^Rss{dFb4w$q{o|v+}`DWTdX7H2(p1UWYb#up&)IPH{)>+iFKNudj zrcHGS^16wkftZwh!1ZIeH$@JHtI-ZY^v{*-I9fFzMwqRY8R*WYe5@eP*M8pc0!F0E za91n-mmlE^2Ri=zIY{2=TB`e(R`)Z7kSD<&E)y)I7toP~!;Xh>%S6yj|CXo?f=Yfs zB%|U=Idj^08^JO~vGcBQJaEq=+_8^|ZA<tBLASu4c}{gmdYIer(BZ#W$(x<7f=o)3VY%HV zBG>%9{Lz=UPhMQ1ZU3c;n_!=##vM#_rC`PUge>c#g~l_89;Vwb`K0rH`Z35HVH?;8 z%aoU%=Xzl-y*)Zy7t~lal%--4FA7E0?S5Z0jKF3lFt72aXPsgeSH%SB&?)pVaWU-bP{O71FbkCBJJylOCsk$Vas_?$M=(6TEqB`_Z?tkap~S&48)VYdeRKfWOG zL4TlE8(eJZfR68uN0c;G8%AgJmAdDp3vR8%2Jh61Q+IXeZ!UWEzFd92`;eW6+$8lW z!X0n0G&rJLbHO_Ww6XT?$ z$oqAZ(ZDRnz)o4&GUoZU;=r{r3{3@3jCQ}Hcc=bs8EQhj$=ytRB6ZFU(yKhWaV19R zd$hgJgt83nyQmB{+ATeFvX2LE%U-y-&?k@9E_Wyqo#bI?d5JoTU)=Pp}OD`|k;f)(a=FQ9>?8!)e#;&MPEr|wO z)xsN7Ht57 z{0qjtUnQ!TKB*dZzNX7ZgIM0m^AX`*>s!-a;Ss#b*w`=K^Jv*Ps)^FzU_82@P#;{1 zyzvEr+p$2M7jy@xC&D<&Tp1uGDopO-a^*+(`Qp^j3vV~aH^o^erR^^0v8hkMQY^w9 zejUM9T@t8ooY0yLT+0+yxLFmQKYrvcOKJs-P@wor;T(;t((E~{UC;nC zuMQuZGIG*q9WPx`Qa|{ju;gp<5U|_M2tLCl9o?CiyHe%@+&YeC8MuwMSHrDbhw5O*6TG9w8Vcb-7a94mrJ? zSnqtqj{fG5Zt?h+=?>Ji_wB|oq1k)mo?Tu{-Xica98Ko+7qDKq2lkW->zIg7&flR+ z@1*DwH`uv<;V+pmtR^&)X)jr&IOAdNeTfIkk!N=KRT=Kx z%~hE1?9?Q%7nqi@k;7@(e)Aqy-Nok;)ALVO$`OVxQHRs~LmA>Cc{r##)E{*{oj)?U zcJT?j&xmamNPp9%?;@W?kz!UPp_tm6rM7X|6Mm$``)p?iRcWRhQC?|f>Y^m15aKBU zdC&{kWjA~ab6tIo!Aexm-ORw1JwO$=qg3j-6;O6S!|M4wwU{JgYzRQ>@F>~ VhfOUU_)8N-U0GYHTG9H$e*onV`Jw;- literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xxxhdpi/fab_bg_mini.png b/app/src/main/res/drawable-xxxhdpi/fab_bg_mini.png new file mode 100644 index 0000000000000000000000000000000000000000..6fea6746d9da50098fd4f4b4ce8ba4eec428dd21 GIT binary patch literal 5987 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

3SM>%eV@5ht?I) z|HkcG@+M6Ln1EBb%XX$^8(^aX*nX;4_7)RSWMF50u-wHq*7bWu z)LVvrx7NXK*d0)%cTx{m;TVpR2`bwX5mqfM!dJ!2zeBm${?aUShQ)PhINso-1OQQe zUMC)DZ_d8G@A1&>cr*Y|_FuzIIA}}^XaC`JbPnfST`o;LJ - - - - + diff --git a/app/src/main/res/values/fab.xml b/app/src/main/res/values/fab.xml new file mode 100644 index 00000000..e2931595 --- /dev/null +++ b/app/src/main/res/values/fab.xml @@ -0,0 +1,58 @@ + + + + + + 56dp + 40dp + + 24dp + + 14dp + 2dp + + 3dp + 9dp + + 1dp + + 16dp + 8dp + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +