Replace custom FAM with FABsMenu

This commit is contained in:
Jakob Nixdorf 2018-03-22 10:05:36 +01:00
parent f251fbcfd8
commit b2d25a3ee8
No known key found for this signature in database
GPG key ID: BE99BF86574A7DBC
11 changed files with 89 additions and 329 deletions

View file

@ -148,6 +148,7 @@ So make sure you have a **current backup** before switching!
* [Apache Commons Codec](https://commons.apache.org/proper/commons-codec/) * [Apache Commons Codec](https://commons.apache.org/proper/commons-codec/)
* [Expandable Layout](https://github.com/AAkira/ExpandableLayout) * [Expandable Layout](https://github.com/AAkira/ExpandableLayout)
* [FABsMenu](https://github.com/jahirfiquitiva/FABsMenu)
* [LicensesDialog](https://github.com/PSDev/LicensesDialog) * [LicensesDialog](https://github.com/PSDev/LicensesDialog)
* [material-intro](https://github.com/heinrichreimer/material-intro) * [material-intro](https://github.com/heinrichreimer/material-intro)
* [MaterialProgressBar](https://github.com/DreaminginCodeZH/MaterialProgressBar) * [MaterialProgressBar](https://github.com/DreaminginCodeZH/MaterialProgressBar)
@ -159,10 +160,13 @@ So make sure you have a **current backup** before switching!
* [Android-ItemTouchHelper-Demo](https://github.com/iPaulPro/Android-ItemTouchHelper-Demo/tree/master/app/src/main/java/co/paulburke/android/itemtouchhelperdemo/helper) * [Android-ItemTouchHelper-Demo](https://github.com/iPaulPro/Android-ItemTouchHelper-Demo/tree/master/app/src/main/java/co/paulburke/android/itemtouchhelperdemo/helper)
* [Code Parts from Google's Android Samples](https://android.googlesource.com/platform/development/+/master/samples/Vault/src/com/example/android/vault) * [Code Parts from Google's Android Samples](https://android.googlesource.com/platform/development/+/master/samples/Vault/src/com/example/android/vault)
* [FloatingActionMenuAndroid](https://github.com/pmahsky/FloatingActionMenuAndroid)
* [LetterBitmap](http://stackoverflow.com/questions/23122088/colored-boxed-with-letters-a-la-gmail) * [LetterBitmap](http://stackoverflow.com/questions/23122088/colored-boxed-with-letters-a-la-gmail)
* [DimensionConverter](https://stackoverflow.com/questions/8343971/how-to-parse-a-dimension-string-and-convert-it-to-a-dimension-value) * [DimensionConverter](https://stackoverflow.com/questions/8343971/how-to-parse-a-dimension-string-and-convert-it-to-a-dimension-value)
#### Previously used code examples:
* [FloatingActionMenuAndroid](https://github.com/pmahsky/FloatingActionMenuAndroid)
## License: ## License:
``` ```
Copyright (C) 2017-2018 Jakob Nixdorf <flocke@shadowice.org> Copyright (C) 2017-2018 Jakob Nixdorf <flocke@shadowice.org>

View file

@ -10,6 +10,7 @@ android {
targetSdkVersion 27 targetSdkVersion 27
versionCode 16 versionCode 16
versionName "0.5.0.1" versionName "0.5.0.1"
vectorDrawables.useSupportLibrary = true
} }
buildTypes { buildTypes {
release { release {
@ -35,19 +36,18 @@ ext {
} }
dependencies { dependencies {
compile fileTree(dir: 'libs', include: ['*.jar']) implementation "commons-codec:commons-codec:1.11"
implementation "com.android.support:appcompat-v7:$supportLibVersion"
compile "commons-codec:commons-codec:1.11" implementation "com.android.support:cardview-v7:$supportLibVersion"
compile "com.android.support:appcompat-v7:$supportLibVersion" implementation "com.android.support:design:$supportLibVersion"
compile "com.android.support:cardview-v7:$supportLibVersion" implementation "com.android.support:recyclerview-v7:$supportLibVersion"
compile "com.android.support:design:$supportLibVersion" implementation "com.android.support.constraint:constraint-layout:1.0.2"
compile "com.android.support:recyclerview-v7:$supportLibVersion" implementation "com.github.aakira:expandable-layout:1.6.0"
compile "com.android.support.constraint:constraint-layout:1.0.2" implementation "com.heinrichreimersoftware:material-intro:1.6.2"
compile "com.github.aakira:expandable-layout:1.6.0" implementation "com.journeyapps:zxing-android-embedded:3.6.0"
compile "com.heinrichreimersoftware:material-intro:1.6.2" implementation "com.vanniktech:vntnumberpickerpreference:1.0.0"
compile "com.journeyapps:zxing-android-embedded:3.6.0" implementation "de.psdev.licensesdialog:licensesdialog:1.8.3"
compile "com.vanniktech:vntnumberpickerpreference:1.0.0" implementation "me.zhanghai.android.materialprogressbar:library:1.4.2"
compile "de.psdev.licensesdialog:licensesdialog:1.8.3" implementation "org.sufficientlysecure:openpgp-api:12.0"
compile "me.zhanghai.android.materialprogressbar:library:1.4.2" implementation "me.jahirfiquitiva:FABsMenu:1.1.2"
compile "org.sufficientlysecure:openpgp-api:12.0"
} }

View file

@ -33,7 +33,6 @@ import android.content.res.Configuration;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler; import android.os.Handler;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import android.support.constraint.ConstraintLayout;
import android.support.v4.widget.DrawerLayout; import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarDrawerToggle; import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.LinearLayoutManager;
@ -63,7 +62,6 @@ import org.shadowice.flocke.andotp.Utilities.KeyStoreHelper;
import org.shadowice.flocke.andotp.Utilities.NotificationHelper; import org.shadowice.flocke.andotp.Utilities.NotificationHelper;
import org.shadowice.flocke.andotp.Utilities.TokenCalculator; import org.shadowice.flocke.andotp.Utilities.TokenCalculator;
import org.shadowice.flocke.andotp.View.EntriesCardAdapter; import org.shadowice.flocke.andotp.View.EntriesCardAdapter;
import org.shadowice.flocke.andotp.View.FloatingActionMenu;
import org.shadowice.flocke.andotp.View.ItemTouchHelper.SimpleItemTouchHelperCallback; import org.shadowice.flocke.andotp.View.ItemTouchHelper.SimpleItemTouchHelperCallback;
import org.shadowice.flocke.andotp.View.ManualEntryDialog; import org.shadowice.flocke.andotp.View.ManualEntryDialog;
import org.shadowice.flocke.andotp.View.TagsAdapter; import org.shadowice.flocke.andotp.View.TagsAdapter;
@ -73,6 +71,9 @@ import java.util.HashMap;
import javax.crypto.SecretKey; import javax.crypto.SecretKey;
import jahirfiquitiva.libs.fabsmenu.FABsMenu;
import jahirfiquitiva.libs.fabsmenu.TitleFAB;
import static org.shadowice.flocke.andotp.Utilities.Constants.AuthMethod; import static org.shadowice.flocke.andotp.Utilities.Constants.AuthMethod;
import static org.shadowice.flocke.andotp.Utilities.Constants.EncryptionType; import static org.shadowice.flocke.andotp.Utilities.Constants.EncryptionType;
import static org.shadowice.flocke.andotp.Utilities.Constants.SortMode; import static org.shadowice.flocke.andotp.Utilities.Constants.SortMode;
@ -81,7 +82,7 @@ public class MainActivity extends BaseActivity
implements SharedPreferences.OnSharedPreferenceChangeListener { implements SharedPreferences.OnSharedPreferenceChangeListener {
private EntriesCardAdapter adapter; private EntriesCardAdapter adapter;
private FloatingActionMenu floatingActionMenu; private FABsMenu fabsMenu;
private MenuItem sortMenu; private MenuItem sortMenu;
private SimpleItemTouchHelperCallback touchHelperCallback; private SimpleItemTouchHelperCallback touchHelperCallback;
@ -193,15 +194,22 @@ public class MainActivity extends BaseActivity
showFirstTimeWarning(); showFirstTimeWarning();
} }
floatingActionMenu = new FloatingActionMenu(this, (ConstraintLayout) findViewById(R.id.fab_main_layout)); fabsMenu = findViewById(R.id.fabs_menu);
floatingActionMenu.setFABHandler(new FloatingActionMenu.FABHandler() {
TitleFAB qrFAB = findViewById(R.id.fab_qr_scan);
qrFAB.setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onQRFabClick() { public void onClick(View view) {
fabsMenu.collapse();
scanQRCode(); scanQRCode();
} }
});
TitleFAB manualFAB = findViewById(R.id.fab_manual_entry);
manualFAB.setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onManualFabClick() { public void onClick(View view) {
fabsMenu.collapse();
ManualEntryDialog.show(MainActivity.this, settings, adapter); ManualEntryDialog.show(MainActivity.this, settings, adapter);
} }
}); });
@ -446,7 +454,7 @@ public class MainActivity extends BaseActivity
searchItem.setOnActionExpandListener(new MenuItem.OnActionExpandListener() { searchItem.setOnActionExpandListener(new MenuItem.OnActionExpandListener() {
@Override @Override
public boolean onMenuItemActionExpand(MenuItem menuItem) { public boolean onMenuItemActionExpand(MenuItem menuItem) {
floatingActionMenu.hide(); fabsMenu.setVisibility(View.GONE);
touchHelperCallback.setDragEnabled(false); touchHelperCallback.setDragEnabled(false);
if (sortMenu != null) if (sortMenu != null)
sortMenu.setVisible(false); sortMenu.setVisible(false);
@ -455,7 +463,7 @@ public class MainActivity extends BaseActivity
@Override @Override
public boolean onMenuItemActionCollapse(MenuItem menuItem) { public boolean onMenuItemActionCollapse(MenuItem menuItem) {
floatingActionMenu.show(); fabsMenu.setVisibility(View.VISIBLE);
if (adapter == null || adapter.getSortMode() == SortMode.UNSORTED) if (adapter == null || adapter.getSortMode() == SortMode.UNSORTED)
touchHelperCallback.setDragEnabled(true); touchHelperCallback.setDragEnabled(true);

View file

@ -1,154 +0,0 @@
/*
* Copyright (C) 2017-2018 Jakob Nixdorf
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package org.shadowice.flocke.andotp.View;
import android.content.Context;
import android.support.constraint.ConstraintLayout;
import android.support.design.widget.FloatingActionButton;
import android.support.v4.view.ViewCompat;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.view.animation.LinearInterpolator;
import android.widget.LinearLayout;
import org.shadowice.flocke.andotp.R;
public class FloatingActionMenu {
private boolean isFabMenuOpen = false;
private ConstraintLayout mainLayout;
private Animation fabOpenAnimation;
private Animation fabCloseAnimation;
private FloatingActionButton baseFloatingActionButton;
private FloatingActionButton qrFAB;
private FloatingActionButton manualFAB;
private LinearLayout qrLayout;
private LinearLayout manualLayout;
private FABHandler fabHandler;
public FloatingActionMenu(Context context, ConstraintLayout mainLayout) {
this.mainLayout = mainLayout;
fabOpenAnimation = AnimationUtils.loadAnimation(context, R.anim.fab_open);
fabCloseAnimation = AnimationUtils.loadAnimation(context, R.anim.fab_close);
baseFloatingActionButton = mainLayout.findViewById(R.id.baseFloatingActionButton);
qrFAB = mainLayout.findViewById(R.id.qrFAB);
manualFAB = mainLayout.findViewById(R.id.manualFAB);
qrLayout = mainLayout.findViewById(R.id.qrLayout);
manualLayout = mainLayout.findViewById(R.id.manualLayout);
baseFloatingActionButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (isFabMenuOpen)
collapse();
else
expand();
}
});
qrFAB.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (fabHandler != null)
fabHandler.onQRFabClick();
collapse();
}
});
manualFAB.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (fabHandler != null)
fabHandler.onManualFabClick();
collapse();
}
});
}
public void setFABHandler(FABHandler fabHandler) {
this.fabHandler = fabHandler;
}
public void show() {
mainLayout.setVisibility(View.VISIBLE);
}
public void hide() {
mainLayout.setVisibility(View.GONE);
}
public void expand() {
ViewCompat.animate(baseFloatingActionButton)
.rotation(45F)
.withLayer()
.setDuration(150)
.setInterpolator(new LinearInterpolator())
.start();
qrLayout.setVisibility(View.VISIBLE);
manualLayout.setVisibility(View.VISIBLE);
qrLayout.startAnimation(fabOpenAnimation);
manualLayout.startAnimation(fabOpenAnimation);
qrFAB.setClickable(true);
manualFAB.setClickable(true);
isFabMenuOpen = true;
}
public void collapse() {
ViewCompat.animate(baseFloatingActionButton)
.rotation(0F)
.withLayer()
.setDuration(150)
.setInterpolator(new LinearInterpolator())
.start();
qrLayout.startAnimation(fabCloseAnimation);
manualLayout.startAnimation(fabCloseAnimation);
qrLayout.setVisibility(View.GONE);
manualLayout.setVisibility(View.GONE);
qrFAB.setClickable(false);
manualFAB.setClickable(false);
isFabMenuOpen = false;
}
public interface FABHandler {
void onQRFabClick();
void onManualFabClick();
}
}

View file

@ -1,18 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:fillAfter="true">
<scale
android:duration="150"
android:fromXScale="1"
android:fromYScale="1"
android:interpolator="@android:anim/linear_interpolator"
android:pivotX="50%"
android:pivotY="50%"
android:toXScale="0.0"
android:toYScale="0.0" />
<alpha
android:duration="150"
android:fromAlpha="1.0"
android:interpolator="@android:anim/accelerate_interpolator"
android:toAlpha="0.0" />
</set>

View file

@ -1,18 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:fillAfter="true">
<scale
android:duration="150"
android:fromXScale="0"
android:fromYScale="0"
android:interpolator="@android:anim/linear_interpolator"
android:pivotX="50%"
android:pivotY="50%"
android:toXScale="1"
android:toYScale="1" />
<alpha
android:duration="150"
android:fromAlpha="0.0"
android:interpolator="@android:anim/accelerate_interpolator"
android:toAlpha="1.0" />
</set>

View file

@ -1,7 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:radius="@dimen/fab_small_label_corners" />
<solid android:color="@color/fab_small_label_background"/>
</shape>

View file

@ -1,95 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/fab_main_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.FloatingActionButton
android:id="@+id/baseFloatingActionButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/fab_base_vertical_offset"
android:layout_marginEnd="@dimen/fab_base_horizontal_offset"
android:clickable="true"
android:tint="@android:color/white"
android:src="@drawable/ic_add_white"
app:fabSize="normal"
app:layout_constraintBottom_toBottomOf="@+id/fab_main_layout"
app:layout_constraintRight_toRightOf="@+id/fab_main_layout" />
<LinearLayout
android:id="@+id/qrLayout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/fab_small_vertical_offset"
android:layout_marginEnd="@dimen/fab_small_horizontal_offset"
android:gravity="center_vertical"
android:orientation="horizontal"
android:visibility="gone"
app:layout_constraintBottom_toTopOf="@+id/manualLayout"
app:layout_constraintRight_toRightOf="@+id/fab_main_layout">
<TextView
android:id="@+id/qrLabelTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="@dimen/fab_small_label_offset"
android:background="@drawable/shape_fab_label"
android:padding="@dimen/fab_small_label_padding"
android:text="@string/button_scan_qr"
android:textColor="@android:color/white"
android:typeface="normal" />
<android.support.design.widget.FloatingActionButton
android:id="@+id/qrFAB"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="@dimen/fab_small_margin"
android:clickable="true"
android:tint="@android:color/white"
android:src="@drawable/ic_camera_white"
app:elevation="@dimen/fab_small_elevation"
app:fabSize="mini" />
</LinearLayout>
<LinearLayout
android:id="@+id/manualLayout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/fab_small_vertical_offset_base"
android:layout_marginEnd="@dimen/fab_small_horizontal_offset"
android:gravity="center_vertical"
android:orientation="horizontal"
android:visibility="gone"
app:layout_constraintBottom_toTopOf="@+id/baseFloatingActionButton"
app:layout_constraintRight_toRightOf="@+id/fab_main_layout" >
<TextView
android:id="@+id/manualLabelTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="@dimen/fab_small_label_offset"
android:background="@drawable/shape_fab_label"
android:padding="@dimen/fab_small_label_padding"
android:text="@string/button_enter_details"
android:textColor="@android:color/white"
android:typeface="normal" />
<android.support.design.widget.FloatingActionButton
android:id="@+id/manualFAB"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="@dimen/fab_small_margin"
android:clickable="true"
android:tint="@android:color/white"
android:src="@drawable/ic_edit_white"
app:elevation="@dimen/fab_small_elevation"
app:fabSize="mini" />
</LinearLayout>
</android.support.constraint.ConstraintLayout>

View file

@ -22,7 +22,52 @@
android:paddingBottom="@dimen/fab_recyclerview_padding" android:paddingBottom="@dimen/fab_recyclerview_padding"
android:clipToPadding="false" /> android:clipToPadding="false" />
<include layout="@layout/component_fam" /> <jahirfiquitiva.libs.fabsmenu.FABsMenuLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
app:fabs_menu_overlayColor="#4d000000"
app:fabs_menu_clickableOverlay="true"
tools:layout_behavior="@string/fabs_menu_layout_behavior">
<jahirfiquitiva.libs.fabsmenu.FABsMenu
android:id="@+id/fabs_menu"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:clipChildren="false"
app:fab_moreButtonPlusIcon="@drawable/ic_add_white"
app:fab_moreButtonBackgroundColor="@color/colorAccent"
app:fab_moreButtonRippleColor="@color/colorAccent"
app:fab_moreButtonSize="normal"
app:fab_labelsPosition="left"
app:fab_expandDirection="up">
<jahirfiquitiva.libs.fabsmenu.TitleFAB
android:id="@+id/fab_qr_scan"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:srcCompat="@drawable/ic_camera_white"
app:fabSize="mini"
app:backgroundTint="@color/colorAccent"
app:rippleColor="@color/colorAccent"
app:fab_title="@string/button_scan_qr"
app:fab_title_textColor="@color/colorAccent" />
<jahirfiquitiva.libs.fabsmenu.TitleFAB
android:id="@+id/fab_manual_entry"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:srcCompat="@drawable/ic_edit_white"
app:fabSize="mini"
app:backgroundTint="@color/colorAccent"
app:rippleColor="@color/colorAccent"
app:fab_title="@string/button_enter_details"
app:fab_enableTitleClick="true"
app:fab_title_textColor="@color/colorAccent" />
</jahirfiquitiva.libs.fabsmenu.FABsMenu>
</jahirfiquitiva.libs.fabsmenu.FABsMenuLayout>
<include layout="@layout/component_tags" /> <include layout="@layout/component_tags" />

View file

@ -12,6 +12,12 @@
<copyright>Copyright (C) 2015 A.Akira</copyright> <copyright>Copyright (C) 2015 A.Akira</copyright>
<license>Apache Software License 2.0</license> <license>Apache Software License 2.0</license>
</notice> </notice>
<notice>
<name>FABsMenu</name>
<url>https://github.com/jahirfiquitiva/FABsMenu</url>
<copyright>Copyright (c) 2018 Jahir Fiquitiva</copyright>
<license>Apache Software License 2.0</license>
</notice>
<notice> <notice>
<name>material-intro</name> <name>material-intro</name>
<url>https://github.com/heinrichreimer/material-intro</url> <url>https://github.com/heinrichreimer/material-intro</url>

View file

@ -19,16 +19,5 @@
<dimen name="divider_size">1dp</dimen> <dimen name="divider_size">1dp</dimen>
<!-- FAB Menu --> <!-- FAB Menu -->
<dimen name="fab_small_elevation">2dp</dimen>
<dimen name="fab_small_margin">8dp</dimen>
<dimen name="fab_small_horizontal_offset">16dp</dimen>
<dimen name="fab_small_vertical_offset">8dp</dimen>
<dimen name="fab_small_vertical_offset_base">16dp</dimen>
<dimen name="fab_small_label_corners">4dp</dimen>
<dimen name="fab_small_label_padding">4dp</dimen>
<dimen name="fab_small_label_offset">8dp</dimen>
<dimen name="fab_base_horizontal_offset">16dp</dimen>
<dimen name="fab_base_vertical_offset">16dp</dimen>
<dimen name="fab_recyclerview_padding">84dp</dimen> <!-- 52dp (FAB size) + 2x fab_base_vertical_offset) --> <dimen name="fab_recyclerview_padding">84dp</dimen> <!-- 52dp (FAB size) + 2x fab_base_vertical_offset) -->
</resources> </resources>