Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(7)

Side by Side Diff: chrome/android/java/src/org/chromium/chrome/browser/widget/ContextMenuDialog.java

Issue 2868403003: added scale animation for context menu (Closed)
Patch Set: fixing broken tests Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 package org.chromium.chrome.browser.widget;
6
7 import android.app.Activity;
8 import android.graphics.Color;
9 import android.graphics.Rect;
10 import android.graphics.drawable.ColorDrawable;
11 import android.support.v4.view.animation.LinearOutSlowInInterpolator;
12 import android.view.MotionEvent;
13 import android.view.View;
14 import android.view.View.OnLayoutChangeListener;
15 import android.view.ViewGroup;
16 import android.view.ViewGroup.LayoutParams;
17 import android.view.Window;
18 import android.view.animation.Animation;
19 import android.view.animation.Animation.AnimationListener;
20 import android.view.animation.ScaleAnimation;
21
22 import org.chromium.chrome.browser.contextmenu.TabularContextMenuViewPager;
23 import org.chromium.content.browser.RenderCoordinates;
24
25 /**
26 * ContextMenuDialog is a subclass of AlwaysDismissedDialog that ensures that th e proper scale
27 * animation is played upon calling {@link #show()} and {@link #dismiss()}.
28 */
29 public class ContextMenuDialog extends AlwaysDismissedDialog {
30 private static final long ENTER_ANIMATION_DURATION_MS = 250;
31 // Exit animation duration should be set to 60% of the enter animation durat ion.
32 private static final long EXIT_ANIMATION_DURATION_MS = 150;
33
34 private final Activity mActivity;
35 private final View mContentView;
36 private final float mTouchPointXPx;
37 private final float mTouchPointYPx;
38 private final RenderCoordinates mRenderCoordinates;
39
40 private float mContextMenuSourceXPx;
41 private float mContextMenuSourceYPx;
42 private int mContextMenuFirstLocationYPx;
43
44 /**
45 * Creates an instance of the ContextMenuDialog.
46 * @param ownerActivity The activity in which the dialog should run
47 * @param theme A style resource describing the theme to use for the window, or {@code 0} to use
48 * the default dialog theme
49 * @param touchPointXPx The x-coordinate of the touch that triggered the con text menu.
50 * @param touchPointYPx The y-coordinate of the touch that triggered the con text menu.
51 * @param contentView The The {@link TabularContextMenuViewPager} to display on the dialog.
52 * @param renderCoordinates The render coordinates to get the y offset of th e window.
53 */
54 public ContextMenuDialog(Activity ownerActivity, int theme, float touchPoint XPx,
55 float touchPointYPx, View contentView, RenderCoordinates renderCoord inates) {
56 super(ownerActivity, theme);
57 mActivity = ownerActivity;
58 mTouchPointXPx = touchPointXPx;
59 mTouchPointYPx = touchPointYPx;
60 mContentView = contentView;
61 mRenderCoordinates = renderCoordinates;
62 }
63
64 @Override
65 public void show() {
66 Window dialogWindow = getWindow();
67 dialogWindow.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)) ;
68 dialogWindow.setLayout(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PAR ENT);
69
70 mContentView.setVisibility(View.INVISIBLE);
71 mContentView.addOnLayoutChangeListener(new OnLayoutChangeListener() {
72 @Override
73 public void onLayoutChange(View v, int left, int top, int right, int bottom,
74 int oldLeft, int oldTop, int oldRight, int oldBottom) {
75 ViewGroup group = (ViewGroup) v;
76 for (int i = 0; i < group.getChildCount(); i++) {
77 if (group.getChildAt(i).getMeasuredHeight() == 0
78 && group.getChildAt(i).getVisibility() == View.VISIB LE) {
79 // Return early because not all the views have been meas ured, so animation
80 // pivots will be off.
81 return;
82 }
83 }
84 mContentView.setVisibility(View.VISIBLE);
85 startEnterAnimation();
86 mContentView.removeOnLayoutChangeListener(this);
87 }
88 });
89 super.show();
90 }
91
92 private void startEnterAnimation() {
93 Rect rectangle = new Rect();
94 Window window = mActivity.getWindow();
95 window.getDecorView().getWindowVisibleDisplayFrame(rectangle);
96
97 float xOffsetPx = rectangle.left;
98 float yOffsetPx = rectangle.top + mRenderCoordinates.getContentOffsetYPi x();
99
100 int[] currentLocationOnScreenPx = new int[2];
101 mContentView.getLocationOnScreen(currentLocationOnScreenPx);
102
103 mContextMenuFirstLocationYPx = currentLocationOnScreenPx[1];
104
105 mContextMenuSourceXPx = mTouchPointXPx - currentLocationOnScreenPx[0] + xOffsetPx;
106 mContextMenuSourceYPx = mTouchPointYPx - currentLocationOnScreenPx[1] + yOffsetPx;
107
108 Animation animation = getScaleAnimation(true, mContextMenuSourceXPx, mCo ntextMenuSourceYPx);
109 mContentView.startAnimation(animation);
110 }
111
112 @Override
113 public void dismiss() {
114 int[] contextMenuFinalLocationPx = new int[2];
115 mContentView.getLocationOnScreen(contextMenuFinalLocationPx);
116 // Recalculate mContextMenuDestinationY because the context menu's final location may not be
117 // the same as its first location if it changed in height.
118 float contextMenuDestinationYPx = mContextMenuSourceYPx
119 + (mContextMenuFirstLocationYPx - contextMenuFinalLocationPx[1]) ;
120
121 Animation exitAnimation =
122 getScaleAnimation(false, mContextMenuSourceXPx, contextMenuDesti nationYPx);
123 exitAnimation.setAnimationListener(new AnimationListener() {
124 @Override
125 public void onAnimationStart(Animation animation) {}
126
127 @Override
128 public void onAnimationRepeat(Animation animation) {}
129
130 @Override
131 public void onAnimationEnd(Animation animation) {
132 ContextMenuDialog.super.dismiss();
133 }
134 });
135 mContentView.startAnimation(exitAnimation);
136 }
137
138 @Override
139 public boolean onTouchEvent(MotionEvent event) {
140 if (event.getAction() == MotionEvent.ACTION_DOWN) {
141 dismiss();
142 return true;
143 }
144 return false;
145 }
146
147 /**
148 * @param isEnterAnimation Whether the animation to be returned is for showi ng the context menu
149 * as opposed to hiding it.
150 * @param pivotX The X coordinate of the point about which the object is bei ng scaled, specified
151 * as an absolute number where 0 is the left edge.
152 * @param pivotY The Y coordinate of the point about which the object is bei ng scaled, specified
153 * as an absolute number where 0 is the top edge.
154 * @return Returns the scale animation for the context menu.
155 */
156 public Animation getScaleAnimation(boolean isEnterAnimation, float pivotX, f loat pivotY) {
157 float fromX = isEnterAnimation ? 0f : 1f;
158 float toX = isEnterAnimation ? 1f : 0f;
159 float fromY = fromX;
160 float toY = toX;
161
162 ScaleAnimation animation = new ScaleAnimation(
163 fromX, toX, fromY, toY, Animation.ABSOLUTE, pivotX, Animation.AB SOLUTE, pivotY);
164
165 long duration = isEnterAnimation ? ENTER_ANIMATION_DURATION_MS : EXIT_AN IMATION_DURATION_MS;
166
167 animation.setDuration(duration);
168 animation.setInterpolator(new LinearOutSlowInInterpolator());
169 return animation;
170 }
171 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698