summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorEric Kuck <eric@bluelinelabs.com>2018-07-11 12:48:18 -0500
committerJason A. Donenfeld <Jason@zx2c4.com>2018-07-11 21:03:22 +0200
commit5463086e7533f647e4a29a964d4b54a4e79ddca1 (patch)
tree9bd0a78e4940d15f371e0cca9d7a827e2ba9bf6c
parent1f7bdd4f5f9fadb51f6c61c453f51533e4886dfa (diff)
fab: use support library's rendering
Signed-off-by: Eric Kuck <eric@bluelinelabs.com>
-rw-r--r--app/src/main/java/com/wireguard/android/fragment/TunnelListFragment.java1
-rw-r--r--app/src/main/java/com/wireguard/android/widget/fab/AddFloatingActionButton.java97
-rw-r--r--app/src/main/java/com/wireguard/android/widget/fab/FloatingActionButton.java446
-rw-r--r--app/src/main/java/com/wireguard/android/widget/fab/FloatingActionsMenu.java82
-rw-r--r--app/src/main/java/com/wireguard/android/widget/fab/LabeledFloatingActionButton.java55
-rw-r--r--app/src/main/java/com/wireguard/android/widget/fab/TouchDelegateGroup.java5
-rw-r--r--app/src/main/res/drawable-hdpi/fab_bg_mini.pngbin3519 -> 0 bytes
-rw-r--r--app/src/main/res/drawable-hdpi/fab_bg_normal.pngbin4925 -> 0 bytes
-rw-r--r--app/src/main/res/drawable-mdpi/fab_bg_mini.pngbin1547 -> 0 bytes
-rw-r--r--app/src/main/res/drawable-mdpi/fab_bg_normal.pngbin2956 -> 0 bytes
-rw-r--r--app/src/main/res/drawable-xhdpi/fab_bg_mini.pngbin4963 -> 0 bytes
-rw-r--r--app/src/main/res/drawable-xhdpi/fab_bg_normal.pngbin7139 -> 0 bytes
-rw-r--r--app/src/main/res/drawable-xxhdpi/fab_bg_mini.pngbin4803 -> 0 bytes
-rw-r--r--app/src/main/res/drawable-xxhdpi/fab_bg_normal.pngbin6114 -> 0 bytes
-rw-r--r--app/src/main/res/drawable-xxxhdpi/fab_bg_mini.pngbin5987 -> 0 bytes
-rw-r--r--app/src/main/res/drawable-xxxhdpi/fab_bg_normal.pngbin8005 -> 0 bytes
-rw-r--r--app/src/main/res/drawable/ic_action_add_inverse.xml9
-rw-r--r--app/src/main/res/layout/tunnel_list_fragment.xml21
-rw-r--r--app/src/main/res/values/fab.xml32
19 files changed, 108 insertions, 640 deletions
diff --git a/app/src/main/java/com/wireguard/android/fragment/TunnelListFragment.java b/app/src/main/java/com/wireguard/android/fragment/TunnelListFragment.java
index 88d9c0b7..5969aa9a 100644
--- a/app/src/main/java/com/wireguard/android/fragment/TunnelListFragment.java
+++ b/app/src/main/java/com/wireguard/android/fragment/TunnelListFragment.java
@@ -35,7 +35,6 @@ import com.wireguard.android.databinding.TunnelListFragmentBinding;
import com.wireguard.android.databinding.TunnelListItemBinding;
import com.wireguard.android.model.Tunnel;
import com.wireguard.android.util.ExceptionLoggers;
-import com.wireguard.android.widget.ToggleSwitch;
import com.wireguard.config.Config;
import java.io.BufferedReader;
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
deleted file mode 100644
index 7dcdd649..00000000
--- a/app/src/main/java/com/wireguard/android/widget/fab/AddFloatingActionButton.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright © 2014 Jerzy Chalupski
- * Copyright © 2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
- * SPDX-License-Identifier: Apache-2.0
- */
-
-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.support.v4.content.ContextCompat;
-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, FloatingActionButton.getColorFromTheme(context, android.R.attr.colorBackground, 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 final int plusColor) {
- setPlusColor(ContextCompat.getColor(getContext(), 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
deleted file mode 100644
index 417ae52d..00000000
--- a/app/src/main/java/com/wireguard/android/widget/fab/FloatingActionButton.java
+++ /dev/null
@@ -1,446 +0,0 @@
-/*
- * Copyright © 2014 Jerzy Chalupski
- * Copyright © 2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
- * SPDX-License-Identifier: Apache-2.0
- */
-
-package com.wireguard.android.widget.fab;
-
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.LinearGradient;
-import android.graphics.Paint;
-import android.graphics.Paint.Style;
-import android.graphics.Rect;
-import android.graphics.Shader;
-import android.graphics.Shader.TileMode;
-import android.graphics.drawable.ColorDrawable;
-import android.graphics.drawable.Drawable;
-import android.graphics.drawable.LayerDrawable;
-import android.graphics.drawable.ShapeDrawable;
-import android.graphics.drawable.ShapeDrawable.ShaderFactory;
-import android.graphics.drawable.StateListDrawable;
-import android.graphics.drawable.shapes.OvalShape;
-import android.support.annotation.ColorRes;
-import android.support.annotation.DimenRes;
-import android.support.annotation.DrawableRes;
-import android.support.annotation.IntDef;
-import android.support.annotation.NonNull;
-import android.support.v4.content.ContextCompat;
-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(final Context context, final AttributeSet attrs, final int defStyle) {
- super(context, attrs, defStyle);
- init(context, attrs);
- }
-
- public static int getColorFromTheme(final Context context, final int themeResource, @ColorRes final int fallback) {
- final TypedArray a = context.obtainStyledAttributes(new int[]{themeResource});
- try {
- return a.getColor(0, ContextCompat.getColor(context, fallback));
- } finally {
- a.recycle();
- }
- }
-
- 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,
- getColorFromTheme(context, android.R.attr.colorAccent, android.R.color.holo_blue_bright));
- mColorPressed = attr.getColor(R.styleable.FloatingActionButton_fab_colorPressed,
- darkenOrLightenColor(mColorNormal)); //TODO(msf): use getColorForState on the accent color from theme instead to get darker states
- mColorDisabled = attr.getColor(R.styleable.FloatingActionButton_fab_colorDisabled,
- ContextCompat.getColor(context, android.R.color.darker_gray)); //TODO(msf): load from theme
- 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(ContextCompat.getColor(getContext(), 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(ContextCompat.getColor(getContext(), 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(ContextCompat.getColor(getContext(), colorDisabled));
- }
-
- public boolean isStrokeVisible() {
- return mStrokeVisible;
- }
-
- public void setStrokeVisible(final boolean visible) {
- if (mStrokeVisible != visible) {
- mStrokeVisible = visible;
- updateBackground();
- }
- }
-
- 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[]{
- //TODO(msf); replace these pngs with programatic elevation
- 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 ContextCompat.getDrawable(getContext(), mIcon);
- } 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 static 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 static int opacityToAlpha(final float opacity) {
- return (int) (255f * opacity);
- }
-
- private static int darkenColor(final int argb) {
- return adjustColorBrightness(argb, 0.9f);
- }
-
- private static int lightenColor(final int argb) {
- return adjustColorBrightness(argb, 1.1f);
- }
-
- public static int darkenOrLightenColor(final int argb) {
- final float[] hsv = new float[3];
- Color.colorToHSV(argb, hsv);
- final float factor;
- if (hsv[2] < 0.2)
- factor = 1.2f;
- else
- factor = 0.8f;
-
- hsv[2] = Math.min(hsv[2] * factor, 1f);
- return Color.HSVToColor(Color.alpha(argb), hsv);
- }
-
- private static 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 static int halfTransparent(final int argb) {
- return Color.argb(
- Color.alpha(argb) / 2,
- Color.red(argb),
- Color.green(argb),
- Color.blue(argb)
- );
- }
-
- private static 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 final class TranslucentLayerDrawable extends LayerDrawable {
- private final int mAlpha;
-
- private 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
index c56fbe29..cdf30a26 100644
--- a/app/src/main/java/com/wireguard/android/widget/fab/FloatingActionsMenu.java
+++ b/app/src/main/java/com/wireguard/android/widget/fab/FloatingActionsMenu.java
@@ -22,6 +22,8 @@ import android.os.Parcel;
import android.os.Parcelable;
import android.support.annotation.Keep;
import android.support.annotation.NonNull;
+import android.support.design.widget.FloatingActionButton;
+import android.support.v4.content.res.ResourcesCompat;
import android.support.v7.widget.AppCompatTextView;
import android.util.AttributeSet;
import android.view.ContextThemeWrapper;
@@ -50,11 +52,6 @@ public class FloatingActionsMenu extends ViewGroup {
private static final TimeInterpolator EXPAND_INTERPOLATOR = new OvershootInterpolator();
private static final TimeInterpolator COLLAPSE_INTERPOLATOR = new DecelerateInterpolator(3f);
private static final TimeInterpolator ALPHA_EXPAND_INTERPOLATOR = 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;
@@ -62,7 +59,7 @@ public class FloatingActionsMenu extends ViewGroup {
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 FloatingActionButton mAddButton;
private RotatingDrawable mRotatingDrawable;
private int mMaxButtonWidth;
private int mMaxButtonHeight;
@@ -88,7 +85,7 @@ public class FloatingActionsMenu extends ViewGroup {
}
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));
+ mButtonSpacing = (int) (getResources().getDimension(R.dimen.fab_actions_spacing));
mLabelsMargin = getResources().getDimensionPixelSize(R.dimen.fab_labels_margin);
mLabelsVerticalOffset = getResources().getDimensionPixelSize(R.dimen.fab_shadow_offset);
@@ -96,14 +93,6 @@ public class FloatingActionsMenu extends ViewGroup {
setTouchDelegate(mTouchDelegateGroup);
final TypedArray attr = context.obtainStyledAttributes(attributeSet, R.styleable.FloatingActionsMenu, 0, 0);
- mAddButtonPlusColor = attr.getColor(R.styleable.FloatingActionsMenu_fab_addButtonPlusIconColor,
- FloatingActionButton.getColorFromTheme(context, android.R.attr.colorBackground, android.R.color.white));
- mAddButtonColorNormal = attr.getColor(R.styleable.FloatingActionsMenu_fab_addButtonColorNormal,
- FloatingActionButton.getColorFromTheme(context, android.R.attr.colorAccent, android.R.color.holo_blue_bright));
- mAddButtonColorPressed = attr.getColor(R.styleable.FloatingActionsMenu_fab_addButtonColorPressed,
- FloatingActionButton.darkenOrLightenColor(mAddButtonColorNormal)); //TODO(msf): use getColorForState on the accent color from theme instead to get darker states
- 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);
@@ -125,45 +114,30 @@ public class FloatingActionsMenu extends ViewGroup {
}
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 RotatingDrawable rotatingDrawable = new RotatingDrawable(ResourcesCompat.getDrawable(context.getResources(), R.drawable.ic_action_add_inverse, context.getTheme()));
+ mRotatingDrawable = rotatingDrawable;
- final TimeInterpolator interpolator = new OvershootInterpolator();
+ final TimeInterpolator 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);
+ 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);
+ collapseAnimator.setInterpolator(interpolator);
+ expandAnimator.setInterpolator(interpolator);
- mExpandAnimation.play(expandAnimator);
- mCollapseAnimation.play(collapseAnimator);
-
- return rotatingDrawable;
- }
- };
+ mExpandAnimation.play(expandAnimator);
+ mCollapseAnimation.play(collapseAnimator);
+ mAddButton = new FloatingActionButton(context);
+ mAddButton.setImageDrawable(rotatingDrawable);
mAddButton.setId(R.id.fab_expand_menu_button);
- mAddButton.setSize(mAddButtonSize);
mAddButton.setOnClickListener(v -> toggle());
addView(mAddButton, super.generateDefaultLayoutParams());
mButtonsCount++;
}
- public void addButton(final FloatingActionButton button) {
+ public void addButton(final LabeledFloatingActionButton button) {
addView(button, mButtonsCount - 1);
mButtonsCount++;
@@ -172,7 +146,7 @@ public class FloatingActionsMenu extends ViewGroup {
}
}
- public void removeButton(final FloatingActionButton button) {
+ public void removeButton(final LabeledFloatingActionButton button) {
removeView(button.getLabelView());
removeView(button);
button.setTag(R.id.fab_label, null);
@@ -257,9 +231,9 @@ public class FloatingActionsMenu extends ViewGroup {
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
+ final int buttonsHorizontalCenter = (mLabelsPosition == LABELS_ON_LEFT_SIDE
? r - l - mMaxButtonWidth / 2
- : mMaxButtonWidth / 2;
+ : mMaxButtonWidth / 2);
final int addButtonLeft = buttonsHorizontalCenter - mAddButton.getMeasuredWidth() / 2;
mAddButton.layout(addButtonLeft, addButtonY, addButtonLeft + mAddButton.getMeasuredWidth(), addButtonY + mAddButton.getMeasuredHeight());
@@ -314,7 +288,7 @@ public class FloatingActionsMenu extends ViewGroup {
childY - mButtonSpacing / 2,
Math.max(childX + child.getMeasuredWidth(), labelRight),
childY + child.getMeasuredHeight() + mButtonSpacing / 2);
- mTouchDelegateGroup.addTouchDelegate(new TouchDelegate(touchArea, child));
+ mTouchDelegateGroup.addTouchDelegate(new TouchDelegate(new Rect(touchArea), child));
label.setTranslationY(mExpanded ? expandedTranslation : collapsedTranslation);
label.setAlpha(mExpanded ? 1f : 0f);
@@ -407,17 +381,17 @@ public class FloatingActionsMenu extends ViewGroup {
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;
+ if (button instanceof LabeledFloatingActionButton) {
+ final String title = ((LabeledFloatingActionButton) button).getTitle();
- final AppCompatTextView label = new AppCompatTextView(context);
- label.setTextAppearance(context, mLabelsStyle);
- label.setText(button.getTitle());
- addView(label);
+ final AppCompatTextView label = new AppCompatTextView(context);
+ label.setTextAppearance(context, mLabelsStyle);
+ label.setText(title);
+ addView(label);
- button.setTag(R.id.fab_label, label);
+ button.setTag(R.id.fab_label, label);
+ }
}
}
diff --git a/app/src/main/java/com/wireguard/android/widget/fab/LabeledFloatingActionButton.java b/app/src/main/java/com/wireguard/android/widget/fab/LabeledFloatingActionButton.java
new file mode 100644
index 00000000..a203282e
--- /dev/null
+++ b/app/src/main/java/com/wireguard/android/widget/fab/LabeledFloatingActionButton.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright © 2014 Jerzy Chalupski
+ * Copyright © 2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+package com.wireguard.android.widget.fab;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.support.design.widget.FloatingActionButton;
+import android.util.AttributeSet;
+import android.widget.TextView;
+
+import com.wireguard.android.R;
+
+public class LabeledFloatingActionButton extends FloatingActionButton {
+
+ private final String title;
+
+ public LabeledFloatingActionButton(final Context context) {
+ this(context, null);
+ }
+
+ public LabeledFloatingActionButton(final Context context, final AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public LabeledFloatingActionButton(final Context context, final AttributeSet attrs, final int defStyle) {
+ super(context, attrs, defStyle);
+
+ final TypedArray attr = context.obtainStyledAttributes(attrs, R.styleable.LabeledFloatingActionButton, 0, 0);
+ title = attr.getString(R.styleable.LabeledFloatingActionButton_fab_title);
+ attr.recycle();
+ }
+
+ TextView getLabelView() {
+ return (TextView) getTag(R.id.fab_label);
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ @Override
+ public void setVisibility(final int visibility) {
+ final TextView label = getLabelView();
+ if (label != null) {
+ label.setVisibility(visibility);
+ }
+
+ super.setVisibility(visibility);
+ }
+
+}
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
index f9ee8429..f6152934 100644
--- a/app/src/main/java/com/wireguard/android/widget/fab/TouchDelegateGroup.java
+++ b/app/src/main/java/com/wireguard/android/widget/fab/TouchDelegateGroup.java
@@ -43,13 +43,14 @@ public class TouchDelegateGroup extends TouchDelegate {
@Override
public boolean onTouchEvent(@NonNull final MotionEvent event) {
- if (!mEnabled) return false;
+ if (!mEnabled)
+ return false;
TouchDelegate delegate = null;
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
- for (final TouchDelegate touchDelegate : mTouchDelegates) {
+ for (final TouchDelegate touchDelegate : mTouchDelegates) {
if (touchDelegate.onTouchEvent(event)) {
mCurrentTouchDelegate = touchDelegate;
return true;
diff --git a/app/src/main/res/drawable-hdpi/fab_bg_mini.png b/app/src/main/res/drawable-hdpi/fab_bg_mini.png
deleted file mode 100644
index 4b48351c..00000000
--- a/app/src/main/res/drawable-hdpi/fab_bg_mini.png
+++ /dev/null
Binary files differ
diff --git a/app/src/main/res/drawable-hdpi/fab_bg_normal.png b/app/src/main/res/drawable-hdpi/fab_bg_normal.png
deleted file mode 100644
index 4daec66d..00000000
--- a/app/src/main/res/drawable-hdpi/fab_bg_normal.png
+++ /dev/null
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/fab_bg_mini.png b/app/src/main/res/drawable-mdpi/fab_bg_mini.png
deleted file mode 100644
index 218cf044..00000000
--- a/app/src/main/res/drawable-mdpi/fab_bg_mini.png
+++ /dev/null
Binary files differ
diff --git a/app/src/main/res/drawable-mdpi/fab_bg_normal.png b/app/src/main/res/drawable-mdpi/fab_bg_normal.png
deleted file mode 100644
index c157df36..00000000
--- a/app/src/main/res/drawable-mdpi/fab_bg_normal.png
+++ /dev/null
Binary files differ
diff --git a/app/src/main/res/drawable-xhdpi/fab_bg_mini.png b/app/src/main/res/drawable-xhdpi/fab_bg_mini.png
deleted file mode 100644
index d56bfe82..00000000
--- a/app/src/main/res/drawable-xhdpi/fab_bg_mini.png
+++ /dev/null
Binary files differ
diff --git a/app/src/main/res/drawable-xhdpi/fab_bg_normal.png b/app/src/main/res/drawable-xhdpi/fab_bg_normal.png
deleted file mode 100644
index 41614b93..00000000
--- a/app/src/main/res/drawable-xhdpi/fab_bg_normal.png
+++ /dev/null
Binary files differ
diff --git a/app/src/main/res/drawable-xxhdpi/fab_bg_mini.png b/app/src/main/res/drawable-xxhdpi/fab_bg_mini.png
deleted file mode 100644
index 1cdd2b1d..00000000
--- a/app/src/main/res/drawable-xxhdpi/fab_bg_mini.png
+++ /dev/null
Binary files differ
diff --git a/app/src/main/res/drawable-xxhdpi/fab_bg_normal.png b/app/src/main/res/drawable-xxhdpi/fab_bg_normal.png
deleted file mode 100644
index 14608fff..00000000
--- a/app/src/main/res/drawable-xxhdpi/fab_bg_normal.png
+++ /dev/null
Binary files differ
diff --git a/app/src/main/res/drawable-xxxhdpi/fab_bg_mini.png b/app/src/main/res/drawable-xxxhdpi/fab_bg_mini.png
deleted file mode 100644
index 6fea6746..00000000
--- a/app/src/main/res/drawable-xxxhdpi/fab_bg_mini.png
+++ /dev/null
Binary files differ
diff --git a/app/src/main/res/drawable-xxxhdpi/fab_bg_normal.png b/app/src/main/res/drawable-xxxhdpi/fab_bg_normal.png
deleted file mode 100644
index 0e78ff60..00000000
--- a/app/src/main/res/drawable-xxxhdpi/fab_bg_normal.png
+++ /dev/null
Binary files differ
diff --git a/app/src/main/res/drawable/ic_action_add_inverse.xml b/app/src/main/res/drawable/ic_action_add_inverse.xml
new file mode 100644
index 00000000..571e70e7
--- /dev/null
+++ b/app/src/main/res/drawable/ic_action_add_inverse.xml
@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportHeight="24.0"
+ android:viewportWidth="24.0">
+ <path
+ android:fillColor="?android:attr/colorBackground"
+ android:pathData="M19,13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z" />
+</vector>
diff --git a/app/src/main/res/layout/tunnel_list_fragment.xml b/app/src/main/res/layout/tunnel_list_fragment.xml
index cad2e094..5aff4739 100644
--- a/app/src/main/res/layout/tunnel_list_fragment.xml
+++ b/app/src/main/res/layout/tunnel_list_fragment.xml
@@ -23,7 +23,8 @@
android:id="@+id/main_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:background="?android:attr/colorBackground">
+ android:background="?android:attr/colorBackground"
+ android:clipChildren="false">
<android.support.v7.widget.RecyclerView
android:id="@+id/tunnel_list"
@@ -39,27 +40,27 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
- android:layout_margin="8dp"
+ android:layout_margin="16dp"
app:fab_labelStyle="@style/fab_label"
- app:fab_labelsPosition="left"
- app:layout_dodgeInsetEdges="bottom">
+ android:clipChildren="false"
+ app:fab_labelsPosition="left" >
- <com.wireguard.android.widget.fab.FloatingActionButton
+ <com.wireguard.android.widget.fab.LabeledFloatingActionButton
android:id="@+id/create_empty"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="@{fragment::onRequestCreateConfig}"
- app:fab_icon="@drawable/ic_action_edit_inverse"
- app:fab_size="mini"
+ app:fabSize="mini"
+ app:srcCompat="@drawable/ic_action_edit_inverse"
app:fab_title="@string/create_empty" />
- <com.wireguard.android.widget.fab.FloatingActionButton
+ <com.wireguard.android.widget.fab.LabeledFloatingActionButton
android:id="@+id/create_from_file"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="@{fragment::onRequestImportConfig}"
- app:fab_icon="@drawable/ic_action_open_inverse"
- app:fab_size="mini"
+ app:srcCompat="@drawable/ic_action_open_inverse"
+ app:fabSize="mini"
app:fab_title="@string/create_from_file" />
</com.wireguard.android.widget.fab.FloatingActionsMenu>
</android.support.design.widget.CoordinatorLayout>
diff --git a/app/src/main/res/values/fab.xml b/app/src/main/res/values/fab.xml
index e2931595..0f373333 100644
--- a/app/src/main/res/values/fab.xml
+++ b/app/src/main/res/values/fab.xml
@@ -3,46 +3,18 @@
<item name="fab_expand_menu_button" type="id"/>
<item name="fab_label" type="id"/>
- <dimen name="fab_size_normal">56dp</dimen>
- <dimen name="fab_size_mini">40dp</dimen>
-
- <dimen name="fab_icon_size">24dp</dimen>
-
- <dimen name="fab_plus_icon_size">14dp</dimen>
- <dimen name="fab_plus_icon_stroke">2dp</dimen>
-
<dimen name="fab_shadow_offset">3dp</dimen>
<dimen name="fab_shadow_radius">9dp</dimen>
<dimen name="fab_stroke_width">1dp</dimen>
- <dimen name="fab_actions_spacing">16dp</dimen>
+ <dimen name="fab_actions_spacing">24dp</dimen>
<dimen name="fab_labels_margin">8dp</dimen>
- <declare-styleable name="FloatingActionButton">
- <attr name="fab_colorPressed" format="color"/>
- <attr name="fab_colorDisabled" format="color"/>
- <attr name="fab_colorNormal" format="color"/>
- <attr name="fab_icon" format="reference"/>
- <attr name="fab_size" format="enum">
- <enum name="normal" value="0"/>
- <enum name="mini" value="1"/>
- </attr>
+ <declare-styleable name="LabeledFloatingActionButton">
<attr name="fab_title" format="string"/>
- <attr name="fab_stroke_visible" format="boolean"/>
- </declare-styleable>
- <declare-styleable name="AddFloatingActionButton">
- <attr name="fab_plusIconColor" format="color"/>
</declare-styleable>
<declare-styleable name="FloatingActionsMenu">
- <attr name="fab_addButtonColorPressed" format="color"/>
- <attr name="fab_addButtonColorNormal" format="color"/>
- <attr name="fab_addButtonSize" format="enum">
- <enum name="normal" value="0"/>
- <enum name="mini" value="1"/>
- </attr>
- <attr name="fab_addButtonPlusIconColor" format="color"/>
- <attr name="fab_addButtonStrokeVisible" format="boolean"/>
<attr name="fab_labelStyle" format="reference"/>
<attr name="fab_labelsPosition" format="enum">
<enum name="left" value="0"/>