From 550ee32baa8e4d714ef5f83f5d79f60f22cc5528 Mon Sep 17 00:00:00 2001 From: Negue Date: Fri, 9 Oct 2015 23:13:28 +0200 Subject: [PATCH] Replace Floating Action Button with a custom control (and on sub item for each task type) --- Habitica/Habitica.iml | 16 ++-- Habitica/build.gradle | 6 +- Habitica/res/layout/activity_main.xml | 95 ++++++++++++++++++- Habitica/res/layout/fragment_recyclerview.xml | 13 --- .../android/habitica/MainActivity.java | 59 +++++++++--- .../fragments/TaskRecyclerViewFragment.java | 36 +------ .../helpers/FloatingActionMenuBehavior.java | 70 ++++++++++++++ 7 files changed, 224 insertions(+), 71 deletions(-) create mode 100644 Habitica/src/com/habitrpg/android/habitica/ui/helpers/FloatingActionMenuBehavior.java diff --git a/Habitica/Habitica.iml b/Habitica/Habitica.iml index 18844ac30..b48ca7789 100644 --- a/Habitica/Habitica.iml +++ b/Habitica/Habitica.iml @@ -79,10 +79,11 @@ + - - + + @@ -113,7 +114,6 @@ - @@ -125,8 +125,8 @@ - + @@ -134,14 +134,16 @@ - + + + - + @@ -152,13 +154,13 @@ + - diff --git a/Habitica/build.gradle b/Habitica/build.gradle index c9577510d..3f72cdb38 100644 --- a/Habitica/build.gradle +++ b/Habitica/build.gradle @@ -72,11 +72,15 @@ dependencies { // Changelog Fragment, minSDK 17 compile 'com.github.porokoro.paperboy:paperboy:2.0.1' - // About View for all dependent Libraries, where are using + // About View for all dependent Libraries, we are using compile('com.mikepenz:aboutlibraries:5.0.5@aar') { transitive = true } + // a better fab alternative + compile 'com.github.clans:fab:1.6.1' + + // ORM provided 'com.raizlabs.android:DBFlow-Compiler:2.2.1' compile "com.raizlabs.android:DBFlow-Core:2.2.1" compile "com.raizlabs.android:DBFlow:2.2.1" diff --git a/Habitica/res/layout/activity_main.xml b/Habitica/res/layout/activity_main.xml index c79c63703..1e8df9afc 100644 --- a/Habitica/res/layout/activity_main.xml +++ b/Habitica/res/layout/activity_main.xml @@ -1,6 +1,7 @@ - + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Habitica/res/layout/fragment_recyclerview.xml b/Habitica/res/layout/fragment_recyclerview.xml index ea37dd3fd..48e9beeb4 100644 --- a/Habitica/res/layout/fragment_recyclerview.xml +++ b/Habitica/res/layout/fragment_recyclerview.xml @@ -2,7 +2,6 @@ @@ -16,16 +15,4 @@ android:scrollbars="vertical" /> - - diff --git a/Habitica/src/com/habitrpg/android/habitica/MainActivity.java b/Habitica/src/com/habitrpg/android/habitica/MainActivity.java index de1a9cda0..f112ad6ba 100644 --- a/Habitica/src/com/habitrpg/android/habitica/MainActivity.java +++ b/Habitica/src/com/habitrpg/android/habitica/MainActivity.java @@ -4,6 +4,7 @@ import android.content.Intent; import android.graphics.Color; import android.os.Bundle; import android.support.design.widget.Snackbar; +import android.support.design.widget.TabLayout; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentPagerAdapter; import android.view.Gravity; @@ -12,12 +13,11 @@ import android.view.MenuItem; import android.view.View; import android.widget.CompoundButton; +import com.github.clans.fab.FloatingActionMenu; import com.habitrpg.android.habitica.callbacks.HabitRPGUserCallback; import com.habitrpg.android.habitica.callbacks.TaskCreationCallback; import com.habitrpg.android.habitica.callbacks.TaskScoringCallback; import com.habitrpg.android.habitica.callbacks.TaskUpdateCallback; -import com.habitrpg.android.habitica.events.TaskCreatedEvent; -import com.habitrpg.android.habitica.events.commands.AddNewTaskCommand; import com.habitrpg.android.habitica.events.BuyRewardTappedEvent; import com.habitrpg.android.habitica.events.HabitScoreEvent; import com.habitrpg.android.habitica.events.TaskCheckedEvent; @@ -25,6 +25,7 @@ import com.habitrpg.android.habitica.events.TaskLongPressedEvent; import com.habitrpg.android.habitica.events.TaskSaveEvent; import com.habitrpg.android.habitica.events.TaskTappedEvent; import com.habitrpg.android.habitica.events.ToggledInnStateEvent; +import com.habitrpg.android.habitica.events.commands.AddNewTaskCommand; import com.habitrpg.android.habitica.events.commands.CreateTagCommand; import com.habitrpg.android.habitica.events.commands.FilterTasksByTagsCommand; import com.habitrpg.android.habitica.prefs.PrefsActivity; @@ -56,6 +57,8 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import butterknife.InjectView; +import butterknife.OnClick; import de.greenrobot.event.EventBus; import retrofit.Callback; import retrofit.RetrofitError; @@ -74,6 +77,9 @@ public class MainActivity extends AvatarActivityBase implements HabitRPGUserCall APIHelper mAPIHelper; + @InjectView(R.id.fab_menu) + FloatingActionMenu floatingMenu; + FlowContentObserver observer; @Override @@ -134,14 +140,48 @@ public class MainActivity extends AvatarActivityBase implements HabitRPGUserCall super.onDestroy(); } + // region onClick for the FAB Menu + + @OnClick(R.id.fab_new_habit) + public void onNewHabit(View view) { + openNewTaskActivity("habit"); + } + + @OnClick(R.id.fab_new_daily) + public void onNewDaily(View view) { + openNewTaskActivity("daily"); + } + + @OnClick(R.id.fab_new_todo) + public void onNewTodo(View view) { + openNewTaskActivity("todo"); + } + + @OnClick(R.id.fab_new_reward) + public void onNewReward(View view) { + openNewTaskActivity("reward"); + } + + + private void openNewTaskActivity(String type) { + Bundle bundle = new Bundle(); + bundle.putString("type", type); + + Intent intent = new Intent(this, TaskFormActivity.class); + intent.putExtras(bundle); + intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); + + startActivityForResult(intent, TASK_CREATED_RESULT); + } + + // endregion + private void showSnackbar(String content) { showSnackbar(content, false); } private void showSnackbar(String content, boolean negative) { - Fragment f = ViewFragmentsDictionary.get(viewPager.getCurrentItem()); - - Snackbar snackbar = Snackbar.make(f.getView().findViewById(R.id.fab), content, Snackbar.LENGTH_LONG); + Snackbar snackbar = Snackbar.make(floatingMenu, content, Snackbar.LENGTH_LONG); if (negative) { View snackbarView = snackbar.getView(); @@ -200,14 +240,7 @@ public class MainActivity extends AvatarActivityBase implements HabitRPGUserCall } public void onEvent(AddNewTaskCommand event) { - Bundle bundle = new Bundle(); - bundle.putString("type", event.ClassType.toLowerCase()); - - Intent intent = new Intent(this, TaskFormActivity.class); - intent.putExtras(bundle); - intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); - - startActivityForResult(intent, TASK_CREATED_RESULT); + openNewTaskActivity(event.ClassType.toLowerCase()); } public void onEvent(final BuyRewardTappedEvent event) { diff --git a/Habitica/src/com/habitrpg/android/habitica/ui/fragments/TaskRecyclerViewFragment.java b/Habitica/src/com/habitrpg/android/habitica/ui/fragments/TaskRecyclerViewFragment.java index d33af2aa4..0705ef6fa 100644 --- a/Habitica/src/com/habitrpg/android/habitica/ui/fragments/TaskRecyclerViewFragment.java +++ b/Habitica/src/com/habitrpg/android/habitica/ui/fragments/TaskRecyclerViewFragment.java @@ -1,9 +1,7 @@ package com.habitrpg.android.habitica.ui.fragments; -import android.graphics.Color; import android.os.Bundle; import android.support.annotation.Nullable; -import android.support.design.widget.FloatingActionButton; import android.support.v4.app.Fragment; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; @@ -14,8 +12,6 @@ import android.view.ViewGroup; import com.habitrpg.android.habitica.R; import com.habitrpg.android.habitica.events.commands.AddNewTaskCommand; import com.habitrpg.android.habitica.ui.adapter.HabitItemRecyclerViewAdapter; -import com.mikepenz.iconics.IconicsDrawable; -import com.mikepenz.iconics.typeface.FontAwesome; import de.greenrobot.event.EventBus; @@ -29,12 +25,10 @@ public class TaskRecyclerViewFragment extends Fragment implements View.OnClickLi public RecyclerView mRecyclerView; private RecyclerView.Adapter mAdapter; private String classType; - private boolean showFloatingButton; // TODO needs a bit of cleanup - public void SetInnerAdapter(HabitItemRecyclerViewAdapter adapter, String classType, boolean showFloatingButton) { + public void SetInnerAdapter(HabitItemRecyclerViewAdapter adapter, String classType) { this.classType = classType; - this.showFloatingButton = showFloatingButton; mAdapter = adapter; } @@ -48,32 +42,14 @@ public class TaskRecyclerViewFragment extends Fragment implements View.OnClickLi return view; } - private boolean alreadyCreated; - - LinearLayoutManager layoutManager = null; @Override public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { - //if (alreadyCreated) - // return; - mRecyclerView = (RecyclerView) view.findViewById(R.id.recyclerView); android.support.v4.app.FragmentActivity context = getActivity(); - FloatingActionButton fab = (FloatingActionButton) view.findViewById(R.id.fab); - - if (fab.getDrawable() == null) { - IconicsDrawable icon = new IconicsDrawable(context, FontAwesome.Icon.faw_plus).color(Color.WHITE).sizeDp(24); - - fab.setImageDrawable(icon); - fab.setOnClickListener(this); - fab.setClickable(true); - } - - fab.setVisibility(showFloatingButton ? View.VISIBLE : View.INVISIBLE); - layoutManager = (LinearLayoutManager) mRecyclerView.getLayoutManager(); if (layoutManager == null) { @@ -82,21 +58,13 @@ public class TaskRecyclerViewFragment extends Fragment implements View.OnClickLi mRecyclerView.setLayoutManager(layoutManager); } - //layoutManager.setSmoothScrollbarEnabled(true); - mRecyclerView.setAdapter(mAdapter); - - alreadyCreated = true; } public static TaskRecyclerViewFragment newInstance(HabitItemRecyclerViewAdapter adapter, String classType) { - return newInstance(adapter, classType, true); - } - - public static TaskRecyclerViewFragment newInstance(HabitItemRecyclerViewAdapter adapter, String classType, boolean showFloatingButton) { TaskRecyclerViewFragment fragment = new TaskRecyclerViewFragment(); - fragment.SetInnerAdapter(adapter, classType,showFloatingButton); + fragment.SetInnerAdapter(adapter, classType); return fragment; } diff --git a/Habitica/src/com/habitrpg/android/habitica/ui/helpers/FloatingActionMenuBehavior.java b/Habitica/src/com/habitrpg/android/habitica/ui/helpers/FloatingActionMenuBehavior.java new file mode 100644 index 000000000..622f6b069 --- /dev/null +++ b/Habitica/src/com/habitrpg/android/habitica/ui/helpers/FloatingActionMenuBehavior.java @@ -0,0 +1,70 @@ +package com.habitrpg.android.habitica.ui.helpers; + +// https://gist.github.com/lodlock/e3cd12130bad70a098db + +import android.content.Context; +import android.support.design.widget.CoordinatorLayout; +import android.support.design.widget.Snackbar; +import android.support.v4.view.ViewCompat; +import android.support.v4.view.ViewPropertyAnimatorListener; +import android.util.AttributeSet; +import android.view.View; + +import com.github.clans.fab.FloatingActionMenu; + +import java.util.List; + +public class FloatingActionMenuBehavior extends CoordinatorLayout.Behavior { + private float mTranslationY; + + public FloatingActionMenuBehavior(Context context, AttributeSet attrs) { + super(); + } + + @Override + public boolean layoutDependsOn(CoordinatorLayout parent, View child, View dependency) { + return dependency instanceof Snackbar.SnackbarLayout; + } + + @Override + public boolean onDependentViewChanged(CoordinatorLayout parent, View child, View dependency) { + if (child instanceof FloatingActionMenu && dependency instanceof Snackbar.SnackbarLayout) { + this.updateTranslation(parent, child, dependency); + } + + return false; + } + + private void updateTranslation(CoordinatorLayout parent, View child, View dependency) { + float translationY = this.getTranslationY(parent, child); + if (translationY != this.mTranslationY) { + ViewCompat.animate(child) + .cancel(); + if (Math.abs(translationY - this.mTranslationY) == (float) dependency.getHeight()) { + ViewCompat.animate(child) + .translationY(translationY) + .setListener((ViewPropertyAnimatorListener) null); + } else { + ViewCompat.setTranslationY(child, translationY); + } + + this.mTranslationY = translationY; + } + + } + + private float getTranslationY(CoordinatorLayout parent, View child) { + float minOffset = 0.0F; + List dependencies = parent.getDependencies(child); + int i = 0; + + for (int z = dependencies.size(); i < z; ++i) { + View view = (View) dependencies.get(i); + if (view instanceof Snackbar.SnackbarLayout && parent.doViewsOverlap(child, view)) { + minOffset = Math.min(minOffset, ViewCompat.getTranslationY(view) - (float) view.getHeight()); + } + } + + return minOffset; + } +} \ No newline at end of file