summaryrefslogtreecommitdiff
path: root/java
diff options
context:
space:
mode:
authorcalderwoodra <calderwoodra@google.com>2017-10-09 16:59:04 -0700
committerEric Erfanian <erfanian@google.com>2017-10-10 07:13:45 -0700
commit6007f5208514c4f69ca6fa75507abba92ef5372d (patch)
treede82c4575349ebd7c211ace9785cf51100c1723a /java
parent19e6dbd30ae88e68cd68f3d3873440d50d19d902 (diff)
Improved FAB UX.
One of the biggest issues with the FAB is that it doesn't scale in/out properly. It looked more like setVisibility was being called instead. This CL migrates the FAB controller to use the built in scale in/out methods #show and #hide and the animation is much nicer. Some of the other issues were: - Now scaling animation is correct and visible. - No longer flashes when going in/out of search. - No longer shows on top of the return to call controller. - No longer bugs when switching between VVM TOS and contacts. - No longer shows FAB over VVM TOS when entering/exiting search Bug: 62588192,35359563,64116334,27458212,37991480,67419607 Test: manual PiperOrigin-RevId: 171608105 Change-Id: I9b3f61df35abf3659a432adf411b1b7d20eba683
Diffstat (limited to 'java')
-rw-r--r--java/com/android/dialer/app/DialtactsActivity.java43
-rw-r--r--java/com/android/dialer/app/calllog/CallLogFragment.java7
-rw-r--r--java/com/android/dialer/app/list/ListsFragment.java11
-rw-r--r--java/com/android/dialer/dialpadview/DialpadFragment.java20
-rw-r--r--java/com/android/dialer/widget/FloatingActionButtonController.java (renamed from java/com/android/contacts/common/widget/FloatingActionButtonController.java)45
5 files changed, 75 insertions, 51 deletions
diff --git a/java/com/android/dialer/app/DialtactsActivity.java b/java/com/android/dialer/app/DialtactsActivity.java
index 5f3620b1c..164c1ea82 100644
--- a/java/com/android/dialer/app/DialtactsActivity.java
+++ b/java/com/android/dialer/app/DialtactsActivity.java
@@ -38,6 +38,7 @@ import android.support.annotation.NonNull;
import android.support.annotation.VisibleForTesting;
import android.support.design.widget.CoordinatorLayout;
import android.support.design.widget.FloatingActionButton;
+import android.support.design.widget.FloatingActionButton.OnVisibilityChangedListener;
import android.support.design.widget.Snackbar;
import android.support.v4.app.ActivityCompat;
import android.support.v4.view.ViewPager;
@@ -67,7 +68,6 @@ import com.android.contacts.common.list.OnPhoneNumberPickerActionListener;
import com.android.contacts.common.list.PhoneNumberListAdapter;
import com.android.contacts.common.list.PhoneNumberPickerFragment.CursorReranker;
import com.android.contacts.common.list.PhoneNumberPickerFragment.OnLoadFinishedListener;
-import com.android.contacts.common.widget.FloatingActionButtonController;
import com.android.dialer.animation.AnimUtils;
import com.android.dialer.animation.AnimationListenerAdapter;
import com.android.dialer.app.calllog.CallLogActivity;
@@ -98,6 +98,7 @@ import com.android.dialer.callintent.CallIntentBuilder;
import com.android.dialer.callintent.CallSpecificAppData;
import com.android.dialer.common.Assert;
import com.android.dialer.common.LogUtil;
+import com.android.dialer.common.concurrent.ThreadUtil;
import com.android.dialer.configprovider.ConfigProviderBindings;
import com.android.dialer.constants.ActivityRequestCodes;
import com.android.dialer.contactsfragment.ContactsFragment;
@@ -133,6 +134,7 @@ import com.android.dialer.util.PermissionsUtil;
import com.android.dialer.util.TouchPointManager;
import com.android.dialer.util.TransactionSafeActivity;
import com.android.dialer.util.ViewUtil;
+import com.android.dialer.widget.FloatingActionButtonController;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -548,7 +550,7 @@ public class DialtactsActivity extends TransactionSafeActivity
mDialerDatabaseHelper.startSmartDialUpdateThread();
}
if (mIsDialpadShown) {
- mFloatingActionButtonController.setVisible(false);
+ mFloatingActionButtonController.scaleOut();
} else {
mFloatingActionButtonController.align(getFabAlignment(), false /* animate */);
}
@@ -857,7 +859,7 @@ public class DialtactsActivity extends TransactionSafeActivity
mFloatingActionButtonController.scaleOut();
maybeEnterSearchUi();
} else {
- mFloatingActionButtonController.setVisible(false);
+ mFloatingActionButtonController.scaleOut();
maybeEnterSearchUi();
}
mActionBarController.onDialpadUp();
@@ -955,7 +957,7 @@ public class DialtactsActivity extends TransactionSafeActivity
ft.hide(mDialpadFragment);
ft.commit();
}
- mFloatingActionButtonController.scaleIn(AnimUtils.NO_DELAY);
+ mFloatingActionButtonController.scaleIn();
}
private void updateSearchFragmentPosition() {
@@ -1271,12 +1273,28 @@ public class DialtactsActivity extends TransactionSafeActivity
setNotInSearchUi();
- // Restore the FAB for the lists fragment.
- if (getFabAlignment() != FloatingActionButtonController.ALIGN_END) {
- mFloatingActionButtonController.setVisible(false);
+ // There are four states the fab can be in:
+ // - Not visible and should remain not visible (do nothing)
+ // - Not visible (move then show the fab)
+ // - Visible, in the correct position (do nothing)
+ // - Visible, in the wrong position (hide, move, then show the fab)
+ if (mFloatingActionButtonController.isVisible()
+ && getFabAlignment() != FloatingActionButtonController.ALIGN_END) {
+ mFloatingActionButtonController.scaleOut(
+ new OnVisibilityChangedListener() {
+ @Override
+ public void onHidden(FloatingActionButton floatingActionButton) {
+ super.onHidden(floatingActionButton);
+ onPageScrolled(
+ mListsFragment.getCurrentTabIndex(), 0 /* offset */, 0 /* pixelOffset */);
+ mFloatingActionButtonController.scaleIn();
+ }
+ });
+ } else if (!mFloatingActionButtonController.isVisible() && mListsFragment.shouldShowFab()) {
+ onPageScrolled(mListsFragment.getCurrentTabIndex(), 0 /* offset */, 0 /* pixelOffset */);
+ ThreadUtil.getUiThreadHandler()
+ .postDelayed(() -> mFloatingActionButtonController.scaleIn(), FAB_SCALE_IN_DELAY_MS);
}
- mFloatingActionButtonController.scaleIn(FAB_SCALE_IN_DELAY_MS);
- onPageScrolled(mListsFragment.getCurrentTabIndex(), 0 /* offset */, 0 /* pixelOffset */);
final FragmentTransaction transaction = getFragmentManager().beginTransaction();
if (mSmartDialSearchFragment != null) {
@@ -1527,8 +1545,10 @@ public class DialtactsActivity extends TransactionSafeActivity
public void onPageSelected(int position) {
updateMissedCalls();
int tabIndex = mListsFragment.getCurrentTabIndex();
+ if (tabIndex != mPreviouslySelectedTabIndex) {
+ mFloatingActionButtonController.scaleIn();
+ }
mPreviouslySelectedTabIndex = tabIndex;
- mFloatingActionButtonController.setVisible(true);
timeTabSelected = SystemClock.elapsedRealtime();
}
@@ -1563,7 +1583,8 @@ public class DialtactsActivity extends TransactionSafeActivity
return mActionBarHeight;
}
- private int getFabAlignment() {
+ @VisibleForTesting
+ public int getFabAlignment() {
if (!mIsLandscape
&& !isInSearchUi()
&& mListsFragment.getCurrentTabIndex() == DialtactsPagerAdapter.TAB_INDEX_SPEED_DIAL) {
diff --git a/java/com/android/dialer/app/calllog/CallLogFragment.java b/java/com/android/dialer/app/calllog/CallLogFragment.java
index a82afa5fe..5cb0244c5 100644
--- a/java/com/android/dialer/app/calllog/CallLogFragment.java
+++ b/java/com/android/dialer/app/calllog/CallLogFragment.java
@@ -602,11 +602,14 @@ public class CallLogFragment extends Fragment
public void onVisible() {
LogUtil.enterBlock("CallLogFragment.onPageSelected");
if (getActivity() != null && getActivity() instanceof HostInterface) {
- ((HostInterface) getActivity())
- .enableFloatingButton(mModalAlertManager == null || mModalAlertManager.isEmpty());
+ ((HostInterface) getActivity()).enableFloatingButton(!isModalAlertVisible());
}
}
+ public boolean isModalAlertVisible() {
+ return mModalAlertManager != null && !mModalAlertManager.isEmpty();
+ }
+
@CallSuper
public void onNotVisible() {
LogUtil.enterBlock("CallLogFragment.onPageUnselected");
diff --git a/java/com/android/dialer/app/list/ListsFragment.java b/java/com/android/dialer/app/list/ListsFragment.java
index a94f9c137..362997a5a 100644
--- a/java/com/android/dialer/app/list/ListsFragment.java
+++ b/java/com/android/dialer/app/list/ListsFragment.java
@@ -35,6 +35,7 @@ import com.android.contacts.common.list.ViewPagerTabs;
import com.android.dialer.app.R;
import com.android.dialer.app.calllog.CallLogFragment;
import com.android.dialer.app.calllog.CallLogNotificationsService;
+import com.android.dialer.app.calllog.VisualVoicemailCallLogFragment;
import com.android.dialer.app.voicemail.error.VoicemailStatusCorruptionHandler;
import com.android.dialer.app.voicemail.error.VoicemailStatusCorruptionHandler.Source;
import com.android.dialer.common.LogUtil;
@@ -409,6 +410,16 @@ public class ListsFragment extends Fragment implements OnPageChangeListener, Lis
return mTabIndex;
}
+ public boolean shouldShowFab() {
+ // If the VVM TOS is visible, don't show the fab
+ if (mCurrentPage instanceof VisualVoicemailCallLogFragment
+ && ((VisualVoicemailCallLogFragment) mCurrentPage).isModalAlertVisible()) {
+ return false;
+ }
+
+ return true;
+ }
+
/**
* External method to update unread count because the unread count changes when the user expands a
* voicemail in the call log or when the user expands an unread call in the call history tab.
diff --git a/java/com/android/dialer/dialpadview/DialpadFragment.java b/java/com/android/dialer/dialpadview/DialpadFragment.java
index 7dd557863..c4e6c61d8 100644
--- a/java/com/android/dialer/dialpadview/DialpadFragment.java
+++ b/java/com/android/dialer/dialpadview/DialpadFragment.java
@@ -69,7 +69,6 @@ import android.widget.RelativeLayout;
import android.widget.TextView;
import com.android.contacts.common.dialog.CallSubjectDialog;
import com.android.contacts.common.util.StopWatch;
-import com.android.contacts.common.widget.FloatingActionButtonController;
import com.android.dialer.animation.AnimUtils;
import com.android.dialer.callintent.CallInitiationType;
import com.android.dialer.callintent.CallIntentBuilder;
@@ -79,6 +78,7 @@ import com.android.dialer.common.LogUtil;
import com.android.dialer.common.concurrent.DialerExecutor;
import com.android.dialer.common.concurrent.DialerExecutor.Worker;
import com.android.dialer.common.concurrent.DialerExecutors;
+import com.android.dialer.common.concurrent.ThreadUtil;
import com.android.dialer.location.GeoUtil;
import com.android.dialer.logging.UiAction;
import com.android.dialer.oem.MotorolaUtils;
@@ -88,6 +88,7 @@ import com.android.dialer.telecom.TelecomUtil;
import com.android.dialer.util.CallUtil;
import com.android.dialer.util.DialerUtils;
import com.android.dialer.util.PermissionsUtil;
+import com.android.dialer.widget.FloatingActionButtonController;
import java.util.HashSet;
import java.util.List;
@@ -1193,7 +1194,7 @@ public class DialpadFragment extends Fragment
mOverflowPopupMenu.dismiss();
}
- mFloatingActionButtonController.setVisible(false);
+ mFloatingActionButtonController.scaleOut();
mDialpadChooser.setVisibility(View.VISIBLE);
// Instantiate the DialpadChooserAdapter and hook it up to the
@@ -1207,6 +1208,7 @@ public class DialpadFragment extends Fragment
if (mDialpadView != null) {
LogUtil.i("DialpadFragment.showDialpadChooser", "mDialpadView not null");
mDialpadView.setVisibility(View.VISIBLE);
+ mFloatingActionButtonController.scaleIn();
} else {
LogUtil.i("DialpadFragment.showDialpadChooser", "mDialpadView null");
mDigits.setVisibility(View.VISIBLE);
@@ -1217,7 +1219,7 @@ public class DialpadFragment extends Fragment
if (!mFloatingActionButtonController.isVisible()) {
// Just call 'scaleIn()' method if the mFloatingActionButtonController was not already
// previously visible.
- mFloatingActionButtonController.scaleIn(0);
+ mFloatingActionButtonController.scaleIn();
}
mDialpadChooser.setVisibility(View.GONE);
}
@@ -1433,17 +1435,15 @@ public class DialpadFragment extends Fragment
if (mAnimate) {
dialpadView.animateShow();
}
- mFloatingActionButtonController.setVisible(false);
- mFloatingActionButtonController.scaleIn(mAnimate ? mDialpadSlideInDuration : 0);
+ ThreadUtil.getUiThreadHandler()
+ .postDelayed(
+ () -> mFloatingActionButtonController.scaleIn(),
+ mAnimate ? mDialpadSlideInDuration : 0);
FragmentUtils.getParentUnsafe(this, DialpadListener.class).onDialpadShown();
mDigits.requestFocus();
}
if (hidden) {
- if (mAnimate) {
- mFloatingActionButtonController.scaleOut();
- } else {
- mFloatingActionButtonController.setVisible(false);
- }
+ mFloatingActionButtonController.scaleOut();
}
}
diff --git a/java/com/android/contacts/common/widget/FloatingActionButtonController.java b/java/com/android/dialer/widget/FloatingActionButtonController.java
index d924681ea..a0c4e6ddd 100644
--- a/java/com/android/contacts/common/widget/FloatingActionButtonController.java
+++ b/java/com/android/dialer/widget/FloatingActionButtonController.java
@@ -14,17 +14,17 @@
* limitations under the License.
*/
-package com.android.contacts.common.widget;
+package com.android.dialer.widget;
import android.app.Activity;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.support.design.widget.FloatingActionButton;
+import android.support.design.widget.FloatingActionButton.OnVisibilityChangedListener;
import android.view.View;
import android.view.animation.AnimationUtils;
import android.view.animation.Interpolator;
import com.android.contacts.common.R;
-import com.android.dialer.animation.AnimUtils;
import com.android.dialer.common.Assert;
/** Controls the movement and appearance of the FAB (Floating Action Button). */
@@ -34,10 +34,6 @@ public class FloatingActionButtonController {
public static final int ALIGN_QUARTER_END = 1;
public static final int ALIGN_END = 2;
- private static final int FAB_SCALE_IN_DURATION = 266;
- private static final int FAB_SCALE_IN_FADE_IN_DELAY = 100;
- private static final int FAB_ICON_FADE_OUT_DURATION = 66;
-
private final int mAnimationDuration;
private final int mFloatingActionButtonWidth;
private final int mFloatingActionButtonMarginRight;
@@ -67,20 +63,22 @@ public class FloatingActionButtonController {
mScreenWidth = screenWidth;
}
+ /** @see FloatingActionButton#isShown() */
public boolean isVisible() {
- return mFab.getVisibility() == View.VISIBLE;
+ return mFab.isShown();
}
/**
* Sets FAB as shown or hidden.
*
- * @param visible Whether or not to make the container visible.
+ * @see #scaleIn()
+ * @see #scaleOut()
*/
public void setVisible(boolean visible) {
if (visible) {
- mFab.show();
+ scaleIn();
} else {
- mFab.hide();
+ scaleOut();
}
}
@@ -141,27 +139,18 @@ public class FloatingActionButtonController {
}
}
- /**
- * Scales the floating action button from no height and width to its actual dimensions. This is an
- * animation for showing the floating action button.
- *
- * @param delayMs The delay for the effect, in milliseconds.
- */
- public void scaleIn(int delayMs) {
- setVisible(true);
- AnimUtils.scaleIn(mFab, FAB_SCALE_IN_DURATION, delayMs);
- AnimUtils.fadeIn(mFab, FAB_SCALE_IN_DURATION, delayMs + FAB_SCALE_IN_FADE_IN_DELAY, null);
+ /** @see FloatingActionButton#show() */
+ public void scaleIn() {
+ mFab.show();
}
- /**
- * Scales the floating action button from its actual dimensions to no height and width. This is an
- * animation for hiding the floating action button.
- */
+ /** @see FloatingActionButton#hide() */
public void scaleOut() {
- AnimUtils.scaleOut(mFab, mAnimationDuration);
- // Fade out the icon faster than the scale out animation, so that the icon scaling is less
- // obvious. We don't want it to scale, but the resizing the container is not as performant.
- AnimUtils.fadeOut(mFab, FAB_ICON_FADE_OUT_DURATION, null);
+ mFab.hide();
+ }
+
+ public void scaleOut(OnVisibilityChangedListener listener) {
+ mFab.hide(listener);
}
/**