diff options
Diffstat (limited to 'src/com/android/messaging/ui/SnackBarManager.java')
-rw-r--r-- | src/com/android/messaging/ui/SnackBarManager.java | 365 |
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; - } - } -} |