summaryrefslogtreecommitdiffstats
path: root/src/com/android/messaging/ui/SnackBarManager.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/android/messaging/ui/SnackBarManager.java')
-rw-r--r--src/com/android/messaging/ui/SnackBarManager.java365
1 files changed, 0 insertions, 365 deletions
diff --git a/src/com/android/messaging/ui/SnackBarManager.java b/src/com/android/messaging/ui/SnackBarManager.java
deleted file mode 100644
index e107999..0000000
--- a/src/com/android/messaging/ui/SnackBarManager.java
+++ /dev/null
@@ -1,365 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.android.messaging.ui;
-
-import android.content.Context;
-import android.graphics.Point;
-import android.graphics.Rect;
-import android.os.Handler;
-import android.text.TextUtils;
-import android.util.DisplayMetrics;
-import android.view.Gravity;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.View.MeasureSpec;
-import android.view.View.OnTouchListener;
-import android.view.ViewGroup;
-import android.view.ViewGroup.LayoutParams;
-import android.view.ViewPropertyAnimator;
-import android.view.ViewTreeObserver.OnGlobalLayoutListener;
-import android.view.WindowManager;
-import android.widget.PopupWindow;
-import android.widget.PopupWindow.OnDismissListener;
-
-import com.android.messaging.Factory;
-import com.android.messaging.R;
-import com.android.messaging.ui.SnackBar.Placement;
-import com.android.messaging.ui.SnackBar.SnackBarListener;
-import com.android.messaging.util.AccessibilityUtil;
-import com.android.messaging.util.Assert;
-import com.android.messaging.util.LogUtil;
-import com.android.messaging.util.OsUtil;
-import com.android.messaging.util.TextUtil;
-import com.android.messaging.util.UiUtils;
-import com.google.common.base.Joiner;
-
-import java.util.List;
-
-public class SnackBarManager {
-
- private static SnackBarManager sInstance;
-
- public static SnackBarManager get() {
- if (sInstance == null) {
- synchronized (SnackBarManager.class) {
- if (sInstance == null) {
- sInstance = new SnackBarManager();
- }
- }
- }
- return sInstance;
- }
-
- private final Runnable mDismissRunnable = new Runnable() {
- @Override
- public void run() {
- dismiss();
- }
- };
-
- private final OnTouchListener mDismissOnTouchListener = new OnTouchListener() {
- @Override
- public boolean onTouch(final View view, final MotionEvent event) {
- // Dismiss the {@link SnackBar} but don't consume the event.
- dismiss();
- return false;
- }
- };
-
- private final SnackBarListener mDismissOnUserTapListener = new SnackBarListener() {
- @Override
- public void onActionClick() {
- dismiss();
- }
- };
-
- private final int mTranslationDurationMs;
- private final Handler mHideHandler;
-
- private SnackBar mCurrentSnackBar;
- private SnackBar mLatestSnackBar;
- private SnackBar mNextSnackBar;
- private boolean mIsCurrentlyDismissing;
- private PopupWindow mPopupWindow;
-
- private SnackBarManager() {
- mTranslationDurationMs = Factory.get().getApplicationContext().getResources().getInteger(
- R.integer.snackbar_translation_duration_ms);
- mHideHandler = new Handler();
- }
-
- public SnackBar getLatestSnackBar() {
- return mLatestSnackBar;
- }
-
- public SnackBar.Builder newBuilder(final View parentView) {
- return new SnackBar.Builder(this, parentView);
- }
-
- /**
- * The given snackBar is not guaranteed to be shown. If the previous snackBar is animating away,
- * and another snackBar is requested to show after this one, this snackBar will be skipped.
- */
- public void show(final SnackBar snackBar) {
- Assert.notNull(snackBar);
-
- if (mCurrentSnackBar != null) {
- LogUtil.d(LogUtil.BUGLE_TAG, "Showing snack bar, but currentSnackBar was not null.");
-
- // Dismiss the current snack bar. That will cause the next snack bar to be shown on
- // completion.
- mNextSnackBar = snackBar;
- mLatestSnackBar = snackBar;
- dismiss();
- return;
- }
-
- mCurrentSnackBar = snackBar;
- mLatestSnackBar = snackBar;
-
- // We want to know when either button was tapped so we can dismiss.
- snackBar.setListener(mDismissOnUserTapListener);
-
- // Cancel previous dismisses & set dismiss for the delay time.
- mHideHandler.removeCallbacks(mDismissRunnable);
- mHideHandler.postDelayed(mDismissRunnable, snackBar.getDuration());
-
- snackBar.setEnabled(false);
-
- // For some reason, the addView function does not respect layoutParams.
- // We need to explicitly set it first here.
- final View rootView = snackBar.getRootView();
-
- if (LogUtil.isLoggable(LogUtil.BUGLE_TAG, LogUtil.DEBUG)) {
- LogUtil.d(LogUtil.BUGLE_TAG, "Showing snack bar: " + snackBar);
- }
- // Measure the snack bar root view so we know how much to translate by.
- measureSnackBar(snackBar);
- mPopupWindow = new PopupWindow(snackBar.getContext());
- mPopupWindow.setWidth(LayoutParams.MATCH_PARENT);
- mPopupWindow.setHeight(LayoutParams.WRAP_CONTENT);
- mPopupWindow.setBackgroundDrawable(null);
- mPopupWindow.setContentView(rootView);
- final Placement placement = snackBar.getPlacement();
- if (placement == null) {
- mPopupWindow.showAtLocation(
- snackBar.getParentView(), Gravity.BOTTOM | Gravity.START,
- 0, getScreenBottomOffset(snackBar));
- } else {
- final View anchorView = placement.getAnchorView();
-
- // You'd expect PopupWindow.showAsDropDown to ensure the popup moves with the anchor
- // view, which it does for scrolling, but not layout changes, so we have to manually
- // update while the snackbar is showing
- final OnGlobalLayoutListener listener = new OnGlobalLayoutListener() {
- @Override
- public void onGlobalLayout() {
- mPopupWindow.update(anchorView, 0, getRelativeOffset(snackBar),
- anchorView.getWidth(), LayoutParams.WRAP_CONTENT);
- }
- };
- anchorView.getViewTreeObserver().addOnGlobalLayoutListener(listener);
- mPopupWindow.setOnDismissListener(new OnDismissListener() {
- @Override
- public void onDismiss() {
- anchorView.getViewTreeObserver().removeOnGlobalLayoutListener(listener);
- }
- });
- mPopupWindow.showAsDropDown(anchorView, 0, getRelativeOffset(snackBar));
- }
-
-
- // Animate the toast bar into view.
- placeSnackBarOffScreen(snackBar);
- animateSnackBarOnScreen(snackBar).withEndAction(new Runnable() {
- @Override
- public void run() {
- mCurrentSnackBar.setEnabled(true);
- makeCurrentSnackBarDismissibleOnTouch();
- // Fire an accessibility event as needed
- String snackBarText = snackBar.getMessageText();
- if (!TextUtils.isEmpty(snackBarText) &&
- TextUtils.getTrimmedLength(snackBarText) > 0) {
- snackBarText = snackBarText.trim();
- final String snackBarActionText = snackBar.getActionLabel();
- if (!TextUtil.isAllWhitespace(snackBarActionText)) {
- snackBarText = Joiner.on(", ").join(snackBarText, snackBarActionText);
- }
- AccessibilityUtil.announceForAccessibilityCompat(snackBar.getSnackBarView(),
- null /*accessibilityManager*/, snackBarText);
- }
- }
- });
-
- // Animate any interaction views out of the way.
- animateInteractionsOnShow(snackBar);
- }
-
- /**
- * Dismisses the current toast that is showing. If there is a toast waiting to be shown, that
- * toast will be shown when the current one has been dismissed.
- */
- public void dismiss() {
- mHideHandler.removeCallbacks(mDismissRunnable);
-
- if (mCurrentSnackBar == null || mIsCurrentlyDismissing) {
- return;
- }
-
- final SnackBar snackBar = mCurrentSnackBar;
-
- LogUtil.d(LogUtil.BUGLE_TAG, "Dismissing snack bar.");
- mIsCurrentlyDismissing = true;
-
- snackBar.setEnabled(false);
-
- // Animate the toast bar down.
- final View rootView = snackBar.getRootView();
- animateSnackBarOffScreen(snackBar).withEndAction(new Runnable() {
- @Override
- public void run() {
- rootView.setVisibility(View.GONE);
- try {
- mPopupWindow.dismiss();
- } catch (IllegalArgumentException e) {
- // PopupWindow.dismiss() will fire an IllegalArgumentException if the activity
- // has already ended while we were animating
- }
-
- mCurrentSnackBar = null;
- mIsCurrentlyDismissing = false;
-
- // Show the next toast if one is waiting.
- if (mNextSnackBar != null) {
- final SnackBar localNextSnackBar = mNextSnackBar;
- mNextSnackBar = null;
- show(localNextSnackBar);
- }
- }
- });
-
- // Animate any interaction views back.
- animateInteractionsOnDismiss(snackBar);
- }
-
- private void makeCurrentSnackBarDismissibleOnTouch() {
- // Set touching on the entire view, the {@link SnackBar} itself, as
- // well as the button's dismiss the toast.
- mCurrentSnackBar.getRootView().setOnTouchListener(mDismissOnTouchListener);
- mCurrentSnackBar.getSnackBarView().setOnTouchListener(mDismissOnTouchListener);
- }
-
- private void measureSnackBar(final SnackBar snackBar) {
- final View rootView = snackBar.getRootView();
- final Point displaySize = new Point();
- getWindowManager(snackBar.getContext()).getDefaultDisplay().getSize(displaySize);
- final int widthSpec = ViewGroup.getChildMeasureSpec(
- MeasureSpec.makeMeasureSpec(displaySize.x, MeasureSpec.EXACTLY),
- 0, LayoutParams.MATCH_PARENT);
- final int heightSpec = ViewGroup.getChildMeasureSpec(
- MeasureSpec.makeMeasureSpec(displaySize.y, MeasureSpec.EXACTLY),
- 0, LayoutParams.WRAP_CONTENT);
- rootView.measure(widthSpec, heightSpec);
- }
-
- private void placeSnackBarOffScreen(final SnackBar snackBar) {
- final View rootView = snackBar.getRootView();
- final View snackBarView = snackBar.getSnackBarView();
- snackBarView.setTranslationY(rootView.getMeasuredHeight());
- }
-
- private ViewPropertyAnimator animateSnackBarOnScreen(final SnackBar snackBar) {
- final View snackBarView = snackBar.getSnackBarView();
- return normalizeAnimator(snackBarView.animate()).translationX(0).translationY(0);
- }
-
- private ViewPropertyAnimator animateSnackBarOffScreen(final SnackBar snackBar) {
- final View rootView = snackBar.getRootView();
- final View snackBarView = snackBar.getSnackBarView();
- return normalizeAnimator(snackBarView.animate()).translationY(rootView.getHeight());
- }
-
- private void animateInteractionsOnShow(final SnackBar snackBar) {
- final List<SnackBarInteraction> interactions = snackBar.getInteractions();
- for (final SnackBarInteraction interaction : interactions) {
- if (interaction != null) {
- final ViewPropertyAnimator animator = interaction.animateOnSnackBarShow(snackBar);
- if (animator != null) {
- normalizeAnimator(animator);
- }
- }
- }
- }
-
- private void animateInteractionsOnDismiss(final SnackBar snackBar) {
- final List<SnackBarInteraction> interactions = snackBar.getInteractions();
- for (final SnackBarInteraction interaction : interactions) {
- if (interaction != null) {
- final ViewPropertyAnimator animator =
- interaction.animateOnSnackBarDismiss(snackBar);
- if (animator != null) {
- normalizeAnimator(animator);
- }
- }
- }
- }
-
- private ViewPropertyAnimator normalizeAnimator(final ViewPropertyAnimator animator) {
- return animator
- .setInterpolator(UiUtils.DEFAULT_INTERPOLATOR)
- .setDuration(mTranslationDurationMs);
- }
-
- private WindowManager getWindowManager(final Context context) {
- return (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
- }
-
- /**
- * Get the offset from the bottom of the screen where the snack bar should be placed.
- */
- private int getScreenBottomOffset(final SnackBar snackBar) {
- final WindowManager windowManager = getWindowManager(snackBar.getContext());
- final DisplayMetrics displayMetrics = new DisplayMetrics();
- if (OsUtil.isAtLeastL()) {
- windowManager.getDefaultDisplay().getRealMetrics(displayMetrics);
- } else {
- windowManager.getDefaultDisplay().getMetrics(displayMetrics);
- }
- final int screenHeight = displayMetrics.heightPixels;
-
- if (OsUtil.isAtLeastL()) {
- // In L, the navigation bar is included in the space for the popup window, so we have to
- // offset by the size of the navigation bar
- final Rect displayRect = new Rect();
- snackBar.getParentView().getRootView().getWindowVisibleDisplayFrame(displayRect);
- return screenHeight - displayRect.bottom;
- }
-
- return 0;
- }
-
- private int getRelativeOffset(final SnackBar snackBar) {
- final Placement placement = snackBar.getPlacement();
- Assert.notNull(placement);
- final View anchorView = placement.getAnchorView();
- if (placement.getAnchorAbove()) {
- return -snackBar.getRootView().getMeasuredHeight() - anchorView.getHeight();
- } else {
- // Use the default dropdown positioning
- return 0;
- }
- }
-}