Chromium Code Reviews| Index: chrome/android/java/src/org/chromium/chrome/browser/snackbar/SnackbarView.java |
| diff --git a/chrome/android/java/src/org/chromium/chrome/browser/snackbar/SnackbarView.java b/chrome/android/java/src/org/chromium/chrome/browser/snackbar/SnackbarView.java |
| index 3671d5cb88a5544dca859c46895f8313258f6ddc..cf20bdbb2c914182736e540893829974205a2757 100644 |
| --- a/chrome/android/java/src/org/chromium/chrome/browser/snackbar/SnackbarView.java |
| +++ b/chrome/android/java/src/org/chromium/chrome/browser/snackbar/SnackbarView.java |
| @@ -4,24 +4,32 @@ |
| package org.chromium.chrome.browser.snackbar; |
| -import android.content.Context; |
| +import android.animation.Animator; |
| +import android.animation.AnimatorListenerAdapter; |
| +import android.animation.ObjectAnimator; |
| +import android.app.Activity; |
| import android.graphics.Bitmap; |
| import android.graphics.Rect; |
| import android.graphics.drawable.GradientDrawable; |
| +import android.support.design.widget.CoordinatorLayout; |
| +import android.support.design.widget.CoordinatorLayout.Behavior; |
| +import android.support.design.widget.CoordinatorLayout.LayoutParams; |
| import android.view.LayoutInflater; |
| +import android.view.MotionEvent; |
| +import android.view.SurfaceView; |
| import android.view.View; |
| import android.view.View.OnClickListener; |
| +import android.view.View.OnLayoutChangeListener; |
| import android.view.ViewGroup; |
| import android.view.ViewGroup.MarginLayoutParams; |
| import android.view.ViewTreeObserver.OnGlobalLayoutListener; |
| -import android.view.animation.Animation; |
| -import android.view.animation.AnimationUtils; |
| import android.view.animation.DecelerateInterpolator; |
| import android.widget.ImageView; |
| import android.widget.TextView; |
| import org.chromium.base.ApiCompatibilityUtils; |
| import org.chromium.chrome.R; |
| +import org.chromium.chrome.browser.ChromeActivity; |
| import org.chromium.ui.base.DeviceFormFactor; |
| /** |
| @@ -29,13 +37,14 @@ import org.chromium.ui.base.DeviceFormFactor; |
| * has a fixed width and is anchored at the start-bottom corner of the current window. |
| */ |
| class SnackbarView { |
| + private final Activity mActivity; |
| private final ViewGroup mView; |
| - private final ViewGroup mParent; |
| private final TemplatePreservingTextView mMessageView; |
| private final TextView mActionButtonView; |
| private final ImageView mProfileImageView; |
| private final int mAnimationDuration; |
| private final boolean mIsTablet; |
| + private ViewGroup mParent; |
| private Snackbar mSnackbar; |
| // Variables used to calculate the virtual keyboard's height. |
| @@ -55,17 +64,39 @@ class SnackbarView { |
| }; |
| /** |
| + * Behavior that intercepts touch event from the CompositorViewHoder. |
| + */ |
| + private Behavior<View> mBehavior = new Behavior<View>() { |
|
gone
2016/05/17 23:48:24
final?
Ian Wen
2016/05/18 00:23:46
Done.
|
| + @Override |
| + public boolean onInterceptTouchEvent(CoordinatorLayout parent, View child, MotionEvent ev) { |
| + return ev.getX() - child.getX() < child.getWidth() |
| + && ev.getY() - child.getY() < child.getHeight(); |
| + } |
| + |
| + @Override |
| + public boolean onTouchEvent(CoordinatorLayout parent, View child, MotionEvent ev) { |
| + ev.offsetLocation(-child.getX(), -child.getY()); |
| + boolean consumed = child.dispatchTouchEvent(ev); |
| + ev.offsetLocation(child.getX(), child.getY()); |
| + return consumed; |
| + } |
| + }; |
| + |
| + /** |
| * Creates an instance of the {@link SnackbarView}. |
|
gone
2016/05/17 23:48:24
Need the @param activity
Ian Wen
2016/05/18 00:23:46
Done.
|
| - * @param parent The main view of the embedding Activity. |
| * @param listener An {@link OnClickListener} that will be called when the action button is |
| * clicked. |
| * @param snackbar The snackbar to be displayed. |
| */ |
| - SnackbarView(ViewGroup parent, OnClickListener listener, Snackbar snackbar) { |
| - Context context = parent.getContext(); |
| - mIsTablet = DeviceFormFactor.isTablet(context); |
| - mParent = parent; |
| - mView = (ViewGroup) LayoutInflater.from(context).inflate(R.layout.snackbar, mParent, false); |
| + SnackbarView(Activity activity, OnClickListener listener, Snackbar snackbar) { |
| + mActivity = activity; |
| + mIsTablet = DeviceFormFactor.isTablet(activity); |
| + mParent = (ViewGroup) activity.findViewById(R.id.compositor_view_holder); |
|
gone
2016/05/17 23:48:24
This logic is kind of gross because it's directly
Ian Wen
2016/05/18 00:23:46
Good suggestion. Done.
|
| + if (mParent == null) { |
| + mParent = (ViewGroup) activity.findViewById(android.R.id.content); |
| + } |
| + mView = (ViewGroup) LayoutInflater.from(activity).inflate(R.layout.snackbar, mParent, |
|
gone
2016/05/17 23:48:24
indent right before R.layout.snackbar
Ian Wen
2016/05/18 00:23:46
Done.
|
| + false); |
| mAnimationDuration = mView.getResources() |
| .getInteger(android.R.integer.config_mediumAnimTime); |
| mMessageView = (TemplatePreservingTextView) mView.findViewById(R.id.snackbar_message); |
| @@ -77,34 +108,45 @@ class SnackbarView { |
| } |
| void show() { |
| - mParent.addView(mView); |
| + if (mParent instanceof CoordinatorLayout) { |
| + CoordinatorLayout.LayoutParams lp = (LayoutParams) mView.getLayoutParams(); |
| + lp.setBehavior(mBehavior); |
| + mParent.addView(mView, lp); |
| + } else { |
| + mParent.addView(mView); |
| + } |
| adjustViewPosition(); |
| mView.getViewTreeObserver().addOnGlobalLayoutListener(mLayoutListener); |
| - // Animation, instead of Animator or ViewPropertyAnimator is prefered here because: |
| - // 1. Animation xml allows specifying 100% as translation, which is much more convenient |
| - // than waiting for mView to be laid out to get measured height. |
| - // 2. Animation avoids SurfaceView's clipping issue when doing translating animation. |
| - Animation fadeIn = AnimationUtils.loadAnimation(mParent.getContext(), R.anim.snackbar_in); |
| - mView.startAnimation(fadeIn); |
| + mView.addOnLayoutChangeListener(new OnLayoutChangeListener() { |
| + @Override |
| + public void onLayoutChange(View v, int left, int top, int right, int bottom, |
| + int oldLeft, int oldTop, int oldRight, int oldBottom) { |
| + mView.removeOnLayoutChangeListener(this); |
| + mView.setTranslationY(mView.getHeight()); |
| + Animator animator = ObjectAnimator.ofFloat(mView, View.TRANSLATION_Y, 0); |
| + animator.setInterpolator(new DecelerateInterpolator()); |
| + animator.setDuration(mAnimationDuration); |
| + startAnimatorOnSurfaceView(animator); |
| + } |
| + }); |
| } |
| void dismiss() { |
| // Disable action button during animation. |
| mActionButtonView.setEnabled(false); |
| mView.getViewTreeObserver().removeOnGlobalLayoutListener(mLayoutListener); |
| - // ViewPropertyAnimator is prefered here because Animation is not canceled when the activity |
| - // is in backbround. |
| - mView.animate() |
| - .alpha(0f) |
| - .setDuration(mAnimationDuration) |
| - .setInterpolator(new DecelerateInterpolator()) |
| - .withEndAction(new Runnable() { |
| - @Override |
| - public void run() { |
| - mParent.removeView(mView); |
| - } |
| - }).start(); |
| + |
| + Animator animator = ObjectAnimator.ofFloat(mView, View.TRANSLATION_Y, mView.getHeight()); |
| + animator.setInterpolator(new DecelerateInterpolator()); |
| + animator.setDuration(mAnimationDuration); |
| + animator.addListener(new AnimatorListenerAdapter() { |
| + @Override |
| + public void onAnimationEnd(Animator animation) { |
| + mParent.removeView(mView); |
| + } |
| + }); |
| + startAnimatorOnSurfaceView(animator); |
| } |
| void adjustViewPosition() { |
| @@ -194,6 +236,17 @@ class SnackbarView { |
| return true; |
| } |
| + /** |
| + * Starts the animation with {@link SurfaceView} optimization disabled. |
|
gone
2016/05/17 23:48:24
This comment only applies to the top of the condit
Ian Wen
2016/05/18 00:23:46
Done.
|
| + */ |
| + private void startAnimatorOnSurfaceView(Animator animator) { |
| + if (mActivity instanceof ChromeActivity) { |
| + ((ChromeActivity) mActivity).getWindowAndroid().startAnimationOverContent(animator); |
| + } else { |
| + animator.start(); |
| + } |
| + } |
| + |
| private void setViewText(TextView view, CharSequence text, boolean animate) { |
| if (view.getText().toString().equals(text)) return; |
| view.animate().cancel(); |