OLD | NEW |
---|---|
(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.Rect; | |
9 import android.support.v4.view.animation.LinearOutSlowInInterpolator; | |
10 import android.view.MotionEvent; | |
11 import android.view.View; | |
12 import android.view.View.OnLayoutChangeListener; | |
13 import android.view.ViewGroup; | |
14 import android.view.Window; | |
15 import android.view.animation.Animation; | |
16 import android.view.animation.Animation.AnimationListener; | |
17 import android.view.animation.ScaleAnimation; | |
18 | |
19 import org.chromium.content.browser.RenderCoordinates; | |
20 | |
21 /** | |
22 * ContextMenuDialog is a subclass of AlwaysDismissedDialog that ensures that th e proper scale | |
23 * animation is played upon calling dismiss(). | |
24 */ | |
25 public class ContextMenuDialog extends AlwaysDismissedDialog { | |
26 private static final int ENTER_ANIMATION_DURATION = 250; | |
27 // Exit animation duration should be set to 60% of the enter animation durat ion. | |
28 private static final int EXIT_ANIMATION_DURATION = 150; | |
29 | |
30 private View mContentView; | |
31 private float mContextMenuSourceX; | |
32 private float mContextMenuSourceY; | |
33 private int mContextMenuFirstLocationY; | |
34 | |
35 public ContextMenuDialog(Activity ownerActivity, int theme) { | |
36 super(ownerActivity, theme); | |
37 } | |
38 | |
39 /** | |
40 * @param contentView The content view to run the animation on. | |
41 * @param touchPointX The x-coordinate of the touch that triggered the conte xt menu in pixels. | |
42 * @param touchPointY The y-coordinate of the touch that triggered the conte xt menu in pixels. | |
43 * @param activity Activity to determine the number of pixels to the left an d above of the | |
44 * window. | |
45 * @param renderCoordinates Render coordinates to determine the y offset tak en by non content | |
46 * window items. | |
47 */ | |
48 public void setupEnterAnimationAndShow(final View contentView, final float t ouchPointX, | |
Theresa
2017/05/24 22:50:50
How about an init() methods that takes all of thes
Daniel Park
2017/05/25 17:12:36
Done.
| |
49 final float touchPointY, final Activity activity, | |
50 final RenderCoordinates renderCoordinates) { | |
51 mContentView = contentView; | |
52 mContentView.addOnLayoutChangeListener(new OnLayoutChangeListener() { | |
53 | |
54 @Override | |
55 public void onLayoutChange(View v, int left, int top, int right, int bottom, | |
56 int oldLeft, int oldTop, int oldRight, int oldBottom) { | |
57 ViewGroup group = (ViewGroup) v; | |
58 for (int i = 0; i < group.getChildCount(); i++) { | |
59 if (group.getChildAt(i).getHeight() == 0 | |
60 && group.getChildAt(i).getVisibility() == View.VISIB LE) { | |
61 // Return early because not all the views have been meas ured, so animation | |
62 // pivots will be off. | |
63 return; | |
64 } | |
65 } | |
66 mContentView.setVisibility(View.VISIBLE); | |
67 startEnterAnimation(touchPointX, touchPointY, activity, renderCo ordinates); | |
68 mContentView.removeOnLayoutChangeListener(this); | |
69 } | |
70 }); | |
71 super.show(); | |
72 } | |
73 | |
74 /** | |
75 * @param touchPointX The x-coordinate of the touch that triggered the conte xt menu in pixels. | |
76 * @param touchPointY The y-coordinate of the touch that triggered the conte xt menu in pixels. | |
77 * @param activity Activity to determine the number of pixels to the left an d above of the | |
78 * window. | |
79 * @param renderCoordinates Render coordinates to determine the y offset tak en by non content | |
80 * window items. | |
81 */ | |
82 private void startEnterAnimation(float touchPointX, float touchPointY, Activ ity activity, | |
83 RenderCoordinates renderCoordinates) { | |
84 int[] currentLocationOnScreen = new int[2]; | |
85 mContentView.getLocationOnScreen(currentLocationOnScreen); | |
86 | |
87 mContextMenuFirstLocationY = currentLocationOnScreen[1]; | |
88 Animation animation = getStartAnimation( | |
89 touchPointX, touchPointY, currentLocationOnScreen, activity, ren derCoordinates); | |
90 mContentView.startAnimation(animation); | |
91 } | |
92 | |
93 /** | |
94 * @param touchPointX The x-coordinate of the touch that triggered the conte xt menu in pixels. | |
95 * @param touchPointY The y-coordinate of the touch that triggered the conte xt menu in pixels. | |
96 * @param currentLocationOnScreen A 2-element array that stores the x,y coor dinates of the view | |
97 * in its 0th and 1st indices respectively. | |
98 * @param activity Activity to determine the number of pixels to the left an d above of the | |
99 * window. | |
100 * @param renderCoordinates Render coordinates to determine the y offset tak en by non content | |
101 * window items. | |
102 */ | |
103 private Animation getStartAnimation(float touchPointX, float touchPointY, | |
Theresa
2017/05/24 22:50:50
I would combine this with startEnterAnimation(). T
Daniel Park
2017/05/25 17:12:37
Done.
| |
104 int[] currentLocationOnScreen, Activity activity, RenderCoordinates renderCoordinates) { | |
105 Rect rectangle = new Rect(); | |
106 Window window = activity.getWindow(); | |
107 window.getDecorView().getWindowVisibleDisplayFrame(rectangle); | |
108 | |
109 float xOffset = rectangle.left; | |
110 float yOffset = rectangle.top + renderCoordinates.getContentOffsetYPix() ; | |
111 | |
112 mContextMenuSourceX = touchPointX - currentLocationOnScreen[0] + xOffset ; | |
113 mContextMenuSourceY = touchPointY - currentLocationOnScreen[1] + yOffset ; | |
114 | |
115 return getScaleAnimation(true, mContextMenuSourceX, mContextMenuSourceY) ; | |
116 } | |
117 | |
118 @Override | |
119 public void dismiss() { | |
120 int[] contextMenuFinalLocation = new int[2]; | |
121 mContentView.getLocationOnScreen(contextMenuFinalLocation); | |
122 // Recalculate mContextMenuDestinationY because the context menu's final location may not be | |
123 // the same as its first location if it changed in height. | |
124 float contextMenuDestinationY = | |
125 mContextMenuSourceY + (mContextMenuFirstLocationY - contextMenuF inalLocation[1]); | |
126 | |
127 Animation exitAnimation = | |
128 getScaleAnimation(false, mContextMenuSourceX, contextMenuDestina tionY); | |
129 exitAnimation.setAnimationListener(new AnimationListener() { | |
130 | |
131 @Override | |
132 public void onAnimationStart(Animation animation) {} | |
133 | |
134 @Override | |
135 public void onAnimationRepeat(Animation animation) {} | |
136 | |
137 @Override | |
138 public void onAnimationEnd(Animation animation) { | |
139 ContextMenuDialog.super.dismiss(); | |
140 } | |
141 }); | |
142 mContentView.startAnimation(exitAnimation); | |
143 } | |
144 | |
145 @Override | |
146 public boolean onTouchEvent(MotionEvent event) { | |
147 if (event.getAction() == MotionEvent.ACTION_DOWN) { | |
148 this.dismiss(); | |
Theresa
2017/05/24 22:50:50
Just to confirm onTouchEvent() doesn't get called
Daniel Park
2017/05/25 17:12:37
from testing, it does get called when an item is c
Daniel Park
2017/05/25 17:12:37
Done.
| |
149 } | |
150 return true; | |
151 } | |
152 | |
153 /** | |
154 * @param isEnterAnimation Whether or not the animation will be for when the context menu enters | |
155 * or not. | |
Theresa
2017/05/24 22:50:50
nit: "Whether animation is for showing the context
Daniel Park
2017/05/25 17:12:37
Done.
| |
156 * @param pivotX The X coordinate of the point about which the object is bei ng scaled, specified | |
157 * as an absolute number where 0 is the left edge. | |
158 * @param pivotY The Y coordinate of the point about which the object is bei ng scaled, specified | |
159 * as an absolute number where 0 is the top edge. | |
160 * @return Returns the scale animation for the context menu. | |
161 */ | |
162 public Animation getScaleAnimation(boolean isEnterAnimation, float pivotX, f loat pivotY) { | |
163 float fromX = isEnterAnimation ? 0f : 1f; | |
164 float toX = isEnterAnimation ? 1f : 0f; | |
165 float fromY = fromX; | |
166 float toY = toX; | |
167 | |
168 ScaleAnimation animation = new ScaleAnimation( | |
169 fromX, toX, fromY, toY, Animation.ABSOLUTE, pivotX, Animation.AB SOLUTE, pivotY); | |
170 | |
171 long duration = isEnterAnimation ? ENTER_ANIMATION_DURATION : EXIT_ANIMA TION_DURATION; | |
172 | |
173 animation.setDuration(duration); | |
174 animation.setInterpolator(new LinearOutSlowInInterpolator()); | |
175 return animation; | |
176 } | |
177 } | |
OLD | NEW |