fab: use support library's rendering
Signed-off-by: Eric Kuck <eric@bluelinelabs.com>
@ -35,7 +35,6 @@ import com.wireguard.android.databinding.TunnelListFragmentBinding;
|
|||||||
import com.wireguard.android.databinding.TunnelListItemBinding;
|
import com.wireguard.android.databinding.TunnelListItemBinding;
|
||||||
import com.wireguard.android.model.Tunnel;
|
import com.wireguard.android.model.Tunnel;
|
||||||
import com.wireguard.android.util.ExceptionLoggers;
|
import com.wireguard.android.util.ExceptionLoggers;
|
||||||
import com.wireguard.android.widget.ToggleSwitch;
|
|
||||||
import com.wireguard.config.Config;
|
import com.wireguard.config.Config;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -22,6 +22,8 @@ import android.os.Parcel;
|
|||||||
import android.os.Parcelable;
|
import android.os.Parcelable;
|
||||||
import android.support.annotation.Keep;
|
import android.support.annotation.Keep;
|
||||||
import android.support.annotation.NonNull;
|
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.support.v7.widget.AppCompatTextView;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
import android.view.ContextThemeWrapper;
|
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 EXPAND_INTERPOLATOR = new OvershootInterpolator();
|
||||||
private static final TimeInterpolator COLLAPSE_INTERPOLATOR = new DecelerateInterpolator(3f);
|
private static final TimeInterpolator COLLAPSE_INTERPOLATOR = new DecelerateInterpolator(3f);
|
||||||
private static final TimeInterpolator ALPHA_EXPAND_INTERPOLATOR = new DecelerateInterpolator();
|
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 mExpandDirection;
|
||||||
private int mButtonSpacing;
|
private int mButtonSpacing;
|
||||||
private int mLabelsMargin;
|
private int mLabelsMargin;
|
||||||
@ -62,7 +59,7 @@ public class FloatingActionsMenu extends ViewGroup {
|
|||||||
private boolean mExpanded;
|
private boolean mExpanded;
|
||||||
private final AnimatorSet mExpandAnimation = new AnimatorSet().setDuration(ANIMATION_DURATION);
|
private final AnimatorSet mExpandAnimation = new AnimatorSet().setDuration(ANIMATION_DURATION);
|
||||||
private final AnimatorSet mCollapseAnimation = new AnimatorSet().setDuration(ANIMATION_DURATION);
|
private final AnimatorSet mCollapseAnimation = new AnimatorSet().setDuration(ANIMATION_DURATION);
|
||||||
private AddFloatingActionButton mAddButton;
|
private FloatingActionButton mAddButton;
|
||||||
private RotatingDrawable mRotatingDrawable;
|
private RotatingDrawable mRotatingDrawable;
|
||||||
private int mMaxButtonWidth;
|
private int mMaxButtonWidth;
|
||||||
private int mMaxButtonHeight;
|
private int mMaxButtonHeight;
|
||||||
@ -88,7 +85,7 @@ public class FloatingActionsMenu extends ViewGroup {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void init(final Context context, final AttributeSet attributeSet) {
|
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);
|
mLabelsMargin = getResources().getDimensionPixelSize(R.dimen.fab_labels_margin);
|
||||||
mLabelsVerticalOffset = getResources().getDimensionPixelSize(R.dimen.fab_shadow_offset);
|
mLabelsVerticalOffset = getResources().getDimensionPixelSize(R.dimen.fab_shadow_offset);
|
||||||
|
|
||||||
@ -96,14 +93,6 @@ public class FloatingActionsMenu extends ViewGroup {
|
|||||||
setTouchDelegate(mTouchDelegateGroup);
|
setTouchDelegate(mTouchDelegateGroup);
|
||||||
|
|
||||||
final TypedArray attr = context.obtainStyledAttributes(attributeSet, R.styleable.FloatingActionsMenu, 0, 0);
|
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);
|
mExpandDirection = attr.getInt(R.styleable.FloatingActionsMenu_fab_expandDirection, EXPAND_UP);
|
||||||
mLabelsStyle = attr.getResourceId(R.styleable.FloatingActionsMenu_fab_labelStyle, 0);
|
mLabelsStyle = attr.getResourceId(R.styleable.FloatingActionsMenu_fab_labelStyle, 0);
|
||||||
mLabelsPosition = attr.getInt(R.styleable.FloatingActionsMenu_fab_labelsPosition, LABELS_ON_LEFT_SIDE);
|
mLabelsPosition = attr.getInt(R.styleable.FloatingActionsMenu_fab_labelsPosition, LABELS_ON_LEFT_SIDE);
|
||||||
@ -125,19 +114,7 @@ public class FloatingActionsMenu extends ViewGroup {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void createAddButton(final Context context) {
|
private void createAddButton(final Context context) {
|
||||||
mAddButton = new AddFloatingActionButton(context) {
|
final RotatingDrawable rotatingDrawable = new RotatingDrawable(ResourcesCompat.getDrawable(context.getResources(), R.drawable.ic_action_add_inverse, context.getTheme()));
|
||||||
@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;
|
mRotatingDrawable = rotatingDrawable;
|
||||||
|
|
||||||
final TimeInterpolator interpolator = new OvershootInterpolator();
|
final TimeInterpolator interpolator = new OvershootInterpolator();
|
||||||
@ -151,19 +128,16 @@ public class FloatingActionsMenu extends ViewGroup {
|
|||||||
mExpandAnimation.play(expandAnimator);
|
mExpandAnimation.play(expandAnimator);
|
||||||
mCollapseAnimation.play(collapseAnimator);
|
mCollapseAnimation.play(collapseAnimator);
|
||||||
|
|
||||||
return rotatingDrawable;
|
mAddButton = new FloatingActionButton(context);
|
||||||
}
|
mAddButton.setImageDrawable(rotatingDrawable);
|
||||||
};
|
|
||||||
|
|
||||||
mAddButton.setId(R.id.fab_expand_menu_button);
|
mAddButton.setId(R.id.fab_expand_menu_button);
|
||||||
mAddButton.setSize(mAddButtonSize);
|
|
||||||
mAddButton.setOnClickListener(v -> toggle());
|
mAddButton.setOnClickListener(v -> toggle());
|
||||||
|
|
||||||
addView(mAddButton, super.generateDefaultLayoutParams());
|
addView(mAddButton, super.generateDefaultLayoutParams());
|
||||||
mButtonsCount++;
|
mButtonsCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addButton(final FloatingActionButton button) {
|
public void addButton(final LabeledFloatingActionButton button) {
|
||||||
addView(button, mButtonsCount - 1);
|
addView(button, mButtonsCount - 1);
|
||||||
mButtonsCount++;
|
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.getLabelView());
|
||||||
removeView(button);
|
removeView(button);
|
||||||
button.setTag(R.id.fab_label, null);
|
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;
|
final int addButtonY = expandUp ? b - t - mAddButton.getMeasuredHeight() : 0;
|
||||||
// Ensure mAddButton is centered on the line where the buttons should be
|
// 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
|
? r - l - mMaxButtonWidth / 2
|
||||||
: mMaxButtonWidth / 2;
|
: mMaxButtonWidth / 2);
|
||||||
final int addButtonLeft = buttonsHorizontalCenter - mAddButton.getMeasuredWidth() / 2;
|
final int addButtonLeft = buttonsHorizontalCenter - mAddButton.getMeasuredWidth() / 2;
|
||||||
mAddButton.layout(addButtonLeft, addButtonY, addButtonLeft + mAddButton.getMeasuredWidth(), addButtonY + mAddButton.getMeasuredHeight());
|
mAddButton.layout(addButtonLeft, addButtonY, addButtonLeft + mAddButton.getMeasuredWidth(), addButtonY + mAddButton.getMeasuredHeight());
|
||||||
|
|
||||||
@ -314,7 +288,7 @@ public class FloatingActionsMenu extends ViewGroup {
|
|||||||
childY - mButtonSpacing / 2,
|
childY - mButtonSpacing / 2,
|
||||||
Math.max(childX + child.getMeasuredWidth(), labelRight),
|
Math.max(childX + child.getMeasuredWidth(), labelRight),
|
||||||
childY + child.getMeasuredHeight() + mButtonSpacing / 2);
|
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.setTranslationY(mExpanded ? expandedTranslation : collapsedTranslation);
|
||||||
label.setAlpha(mExpanded ? 1f : 0f);
|
label.setAlpha(mExpanded ? 1f : 0f);
|
||||||
@ -407,19 +381,19 @@ public class FloatingActionsMenu extends ViewGroup {
|
|||||||
|
|
||||||
for (int i = 0; i < mButtonsCount; i++) {
|
for (int i = 0; i < mButtonsCount; i++) {
|
||||||
final FloatingActionButton button = (FloatingActionButton) getChildAt(i);
|
final FloatingActionButton button = (FloatingActionButton) getChildAt(i);
|
||||||
final String title = button.getTitle();
|
|
||||||
|
|
||||||
if (button == mAddButton || title == null ||
|
if (button instanceof LabeledFloatingActionButton) {
|
||||||
button.getTag(R.id.fab_label) != null) continue;
|
final String title = ((LabeledFloatingActionButton) button).getTitle();
|
||||||
|
|
||||||
final AppCompatTextView label = new AppCompatTextView(context);
|
final AppCompatTextView label = new AppCompatTextView(context);
|
||||||
label.setTextAppearance(context, mLabelsStyle);
|
label.setTextAppearance(context, mLabelsStyle);
|
||||||
label.setText(button.getTitle());
|
label.setText(title);
|
||||||
addView(label);
|
addView(label);
|
||||||
|
|
||||||
button.setTag(R.id.fab_label, label);
|
button.setTag(R.id.fab_label, label);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void collapse() {
|
public void collapse() {
|
||||||
collapse(false);
|
collapse(false);
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -43,7 +43,8 @@ public class TouchDelegateGroup extends TouchDelegate {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onTouchEvent(@NonNull final MotionEvent event) {
|
public boolean onTouchEvent(@NonNull final MotionEvent event) {
|
||||||
if (!mEnabled) return false;
|
if (!mEnabled)
|
||||||
|
return false;
|
||||||
|
|
||||||
TouchDelegate delegate = null;
|
TouchDelegate delegate = null;
|
||||||
|
|
||||||
|
Before Width: | Height: | Size: 3.4 KiB |
Before Width: | Height: | Size: 4.8 KiB |
Before Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 2.9 KiB |
Before Width: | Height: | Size: 4.8 KiB |
Before Width: | Height: | Size: 7.0 KiB |
Before Width: | Height: | Size: 4.7 KiB |
Before Width: | Height: | Size: 6.0 KiB |
Before Width: | Height: | Size: 5.8 KiB |
Before Width: | Height: | Size: 7.8 KiB |
9
app/src/main/res/drawable/ic_action_add_inverse.xml
Normal file
@ -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>
|
@ -23,7 +23,8 @@
|
|||||||
android:id="@+id/main_container"
|
android:id="@+id/main_container"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="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.support.v7.widget.RecyclerView
|
||||||
android:id="@+id/tunnel_list"
|
android:id="@+id/tunnel_list"
|
||||||
@ -39,27 +40,27 @@
|
|||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="bottom|end"
|
android:layout_gravity="bottom|end"
|
||||||
android:layout_margin="8dp"
|
android:layout_margin="16dp"
|
||||||
app:fab_labelStyle="@style/fab_label"
|
app:fab_labelStyle="@style/fab_label"
|
||||||
app:fab_labelsPosition="left"
|
android:clipChildren="false"
|
||||||
app:layout_dodgeInsetEdges="bottom">
|
app:fab_labelsPosition="left" >
|
||||||
|
|
||||||
<com.wireguard.android.widget.fab.FloatingActionButton
|
<com.wireguard.android.widget.fab.LabeledFloatingActionButton
|
||||||
android:id="@+id/create_empty"
|
android:id="@+id/create_empty"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:onClick="@{fragment::onRequestCreateConfig}"
|
android:onClick="@{fragment::onRequestCreateConfig}"
|
||||||
app:fab_icon="@drawable/ic_action_edit_inverse"
|
app:fabSize="mini"
|
||||||
app:fab_size="mini"
|
app:srcCompat="@drawable/ic_action_edit_inverse"
|
||||||
app:fab_title="@string/create_empty" />
|
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:id="@+id/create_from_file"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:onClick="@{fragment::onRequestImportConfig}"
|
android:onClick="@{fragment::onRequestImportConfig}"
|
||||||
app:fab_icon="@drawable/ic_action_open_inverse"
|
app:srcCompat="@drawable/ic_action_open_inverse"
|
||||||
app:fab_size="mini"
|
app:fabSize="mini"
|
||||||
app:fab_title="@string/create_from_file" />
|
app:fab_title="@string/create_from_file" />
|
||||||
</com.wireguard.android.widget.fab.FloatingActionsMenu>
|
</com.wireguard.android.widget.fab.FloatingActionsMenu>
|
||||||
</android.support.design.widget.CoordinatorLayout>
|
</android.support.design.widget.CoordinatorLayout>
|
||||||
|
@ -3,46 +3,18 @@
|
|||||||
<item name="fab_expand_menu_button" type="id"/>
|
<item name="fab_expand_menu_button" type="id"/>
|
||||||
<item name="fab_label" 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_offset">3dp</dimen>
|
||||||
<dimen name="fab_shadow_radius">9dp</dimen>
|
<dimen name="fab_shadow_radius">9dp</dimen>
|
||||||
|
|
||||||
<dimen name="fab_stroke_width">1dp</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>
|
<dimen name="fab_labels_margin">8dp</dimen>
|
||||||
|
|
||||||
<declare-styleable name="FloatingActionButton">
|
<declare-styleable name="LabeledFloatingActionButton">
|
||||||
<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>
|
|
||||||
<attr name="fab_title" format="string"/>
|
<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>
|
||||||
<declare-styleable name="FloatingActionsMenu">
|
<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_labelStyle" format="reference"/>
|
||||||
<attr name="fab_labelsPosition" format="enum">
|
<attr name="fab_labelsPosition" format="enum">
|
||||||
<enum name="left" value="0"/>
|
<enum name="left" value="0"/>
|
||||||
|