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

Side by Side Diff: chrome/android/java/src/org/chromium/chrome/browser/compositor/bottombar/contextualsearch/ContextualSearchPanelAnimation.java

Issue 987883002: Upstream Layout.java and associated files (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Move to SuppressFBWarnings from findbugs_exclude.xml Created 5 years, 9 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 2015 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.compositor.bottombar.contextualsearch;
6
7 import static org.chromium.chrome.browser.compositor.layouts.ChromeAnimation.Ani matableAnimation.createAnimation;
8
9 import android.content.Context;
10 import android.view.animation.Interpolator;
11
12 import org.chromium.chrome.browser.compositor.bottombar.contextualsearch.Context ualSearchPanel.PanelState;
13 import org.chromium.chrome.browser.compositor.bottombar.contextualsearch.Context ualSearchPanel.StateChangeReason;
14 import org.chromium.chrome.browser.compositor.layouts.ChromeAnimation;
15 import org.chromium.chrome.browser.compositor.layouts.ChromeAnimation.Animatable ;
16 import org.chromium.chrome.browser.compositor.layouts.ChromeAnimation.Animation;
17 import org.chromium.chrome.browser.compositor.layouts.LayoutUpdateHost;
18 import org.chromium.chrome.browser.util.MathUtils;
19
20 /**
21 * Base abstract class for animating the Contextual Search Panel.
22 */
23 abstract class ContextualSearchPanelAnimation extends ContextualSearchPanelBase
24 implements Animatable<ContextualSearchPanelAnimation.Property> {
25
26 /**
27 * Animation properties.
28 */
29 protected enum Property {
30 PANEL_HEIGHT,
31 FIRST_RUN_PANEL_HEIGHT,
32 }
33
34 /**
35 * The base duration of animations in milliseconds. This value is based on
36 * the Kennedy specification for slow animations.
37 */
38 private static final long BASE_ANIMATION_DURATION_MS = 218;
39
40 /**
41 * The maximum animation duration in milliseconds.
42 */
43 private static final long MAXIMUM_ANIMATION_DURATION_MS = 350;
44
45 /**
46 * The minimum animation duration in milliseconds.
47 */
48 private static final long MINIMUM_ANIMATION_DURATION_MS = Math.round(7 * 100 0 / 60);
49
50 /**
51 * Average animation velocity in dps per second.
52 */
53 private static final float INITIAL_ANIMATION_VELOCITY_DP_PER_SECOND = 1750f;
54
55 /**
56 * The PanelState to which the Panel is being animated.
57 */
58 private PanelState mAnimatingState;
59
60 /**
61 * The StateChangeReason for which the Panel is being animated.
62 */
63 private StateChangeReason mAnimatingStateReason;
64
65 /**
66 * The animation set.
67 */
68 private ChromeAnimation<Animatable<?>> mLayoutAnimations;
69
70 /**
71 * The {@link LayoutUpdateHost} used to request a new frame to be updated an d rendered.
72 */
73 private final LayoutUpdateHost mUpdateHost;
74
75 // ========================================================================= ===================
76 // Constructor
77 // ========================================================================= ===================
78
79 /**
80 * @param context The current Android {@link Context}.
81 * @param updateHost The {@link LayoutUpdateHost} used to request updates in the Layout.
82 */
83 public ContextualSearchPanelAnimation(Context context, LayoutUpdateHost upda teHost) {
84 super(context);
85 mUpdateHost = updateHost;
86 }
87
88 // ========================================================================= ===================
89 // Animation API
90 // ========================================================================= ===================
91
92 /**
93 * Animates the Contextual Search Panel to its maximized state.
94 *
95 * @param reason The reason for the change of panel state.
96 */
97 protected void maximizePanel(StateChangeReason reason) {
98 animatePanelToState(PanelState.MAXIMIZED, reason);
99 }
100
101 /**
102 * Animates the Contextual Search Panel to its intermediary state.
103 *
104 * @param reason The reason for the change of panel state.
105 */
106 protected void expandPanel(StateChangeReason reason) {
107 animatePanelToState(getIntermediaryState(), reason);
108 }
109
110 /**
111 * Animates the Contextual Search Panel to its peeked state.
112 *
113 * @param reason The reason for the change of panel state.
114 */
115 protected void peekPanel(StateChangeReason reason) {
116 // Indicate to the Compositor that for now on the Panel should be
117 // rendered, until it's closed.
118 startShowing();
119
120 // TODO(pedrosimonetti): Implement custom animation with the following v alues.
121 // int SEARCH_BAR_ANIMATION_DURATION_MS = 218;
122 // float SEARCH_BAR_SLIDE_OFFSET_DP = 40;
123 // float mSearchBarHeightDp;
124 // setTranslationY(mIsShowingFirstRunFlow
125 // ? mSearchBarHeightDp : SEARCH_BAR_SLIDE_OFFSET_DP);
126 // setInterpolator(BakedBezierInterpolator.FADE_IN_CURVE);
127 animatePanelToState(PanelState.PEEKED, reason);
128 }
129
130 /**
131 * Animates the Contextual Search Panel to its closed state.
132 *
133 * @param reason The reason for the change of panel state.
134 */
135 protected void closePanel(StateChangeReason reason, boolean animate) {
136 if (animate) {
137 animatePanelToState(PanelState.CLOSED, reason);
138 } else {
139 resizePanelToState(PanelState.CLOSED, reason);
140 }
141 }
142
143 /**
144 * Animates the Contextual Search Panel to a given |state| with a default du ration.
145 *
146 * @param state The state to animate to.
147 * @param reason The reason for the change of panel state.
148 */
149 private void animatePanelToState(PanelState state, StateChangeReason reason) {
150 animatePanelToState(state, reason, BASE_ANIMATION_DURATION_MS);
151 }
152
153 /**
154 * Animates the Contextual Search Panel to a given |state| with a custom |du ration|.
155 *
156 * @param state The state to animate to.
157 * @param reason The reason for the change of panel state.
158 * @param duration The animation duration in milliseconds.
159 */
160 protected void animatePanelToState(PanelState state, StateChangeReason reaso n, long duration) {
161 mAnimatingState = state;
162 mAnimatingStateReason = reason;
163
164 final float height = getPanelHeightFromState(state);
165 animatePanelTo(height, duration);
166 }
167
168 /**
169 * Resizes the Contextual Search Panel to a given |state|.
170 *
171 * @param state The state to resize to.
172 * @param reason The reason for the change of panel state.
173 */
174 private void resizePanelToState(PanelState state, StateChangeReason reason) {
175 final float height = getPanelHeightFromState(state);
176 setPanelHeight(height);
177 setPanelState(state, reason);
178 requestUpdate();
179 }
180
181 // ========================================================================= ===================
182 // Animation Helpers
183 // ========================================================================= ===================
184
185 /**
186 * Animates the Contextual Search panel after first-run success.
187 */
188 protected void animateAfterFirstRunSuccess() {
189 final PanelState desiredState = PanelState.EXPANDED;
190 mAnimatingState = desiredState;
191 mAnimatingStateReason = StateChangeReason.OPTIN;
192
193 final float desiredHeight = getPanelHeightFromState(desiredState);
194 animateProperty(Property.FIRST_RUN_PANEL_HEIGHT, getHeight(), desiredHei ght,
195 BASE_ANIMATION_DURATION_MS);
196 }
197
198 /**
199 * Animates the Panel to its nearest state.
200 */
201 protected void animateToNearestState() {
202 // Calculate the nearest state from the current position, and then calcu late the duration
203 // of the animation that will start with a desired initial velocity and move the desired
204 // amount of dps (displacement).
205 final PanelState nearestState = findNearestPanelStateFromHeight(getHeigh t());
206 final float displacement = getPanelHeightFromState(nearestState) - getHe ight();
207 final long duration = calculateAnimationDuration(
208 INITIAL_ANIMATION_VELOCITY_DP_PER_SECOND, displacement);
209
210 animatePanelToState(nearestState, StateChangeReason.SWIPE, duration);
211 }
212
213 /**
214 * Animates the Panel to its projected state, given a particular vertical |v elocity|.
215 *
216 * @param velocity The velocity of the gesture in dps per second.
217 */
218 protected void animateToProjectedState(float velocity) {
219 final float kickY = calculateAnimationDisplacement(velocity, BASE_ANIMAT ION_DURATION_MS);
220 final float projectedHeight = getHeight() - kickY;
221
222 // Calculate the projected state the Panel will be at the end of the fli ng movement and the
223 // duration of the animation given the current velocity and the projecte d displacement.
224 final PanelState projectedState = findNearestPanelStateFromHeight(projec tedHeight);
225 final float displacement = getPanelHeightFromState(projectedState) - get Height();
226 final long duration = calculateAnimationDuration(velocity, displacement) ;
227
228 animatePanelToState(projectedState, StateChangeReason.FLING, duration);
229 }
230
231 /**
232 * Calculates the animation displacement given the |initialVelocity| and a
233 * desired |duration|.
234 *
235 * @param initialVelocity The initial velocity of the animation in dps per s econd.
236 * @param duration The desired duration of the animation in milliseconds.
237 * @return The animation displacement in dps.
238 */
239 protected float calculateAnimationDisplacement(float initialVelocity, float duration) {
240 // NOTE(pedrosimonetti): This formula assumes the deceleration curve is
241 // quadratic (t^2),
242 // hence the displacement formula should be:
243 // displacement = initialVelocity * duration / 2
244 //
245 // We are also converting the duration from milliseconds to seconds,
246 // which explains why
247 // we are dividing by 2000 (2 * 1000) instead of 2.
248 return initialVelocity * duration / 2000;
249 }
250
251 /**
252 * Calculates the animation duration given the |initialVelocity| and a
253 * desired |displacement|.
254 *
255 * @param initialVelocity The initial velocity of the animation in dps per s econd.
256 * @param displacement The displacement of the animation in dps.
257 * @return The animation duration in milliseconds.
258 */
259 private long calculateAnimationDuration(float initialVelocity, float displac ement) {
260 // NOTE(pedrosimonetti): This formula assumes the deceleration curve is
261 // quadratic (t^2),
262 // hence the duration formula should be:
263 // duration = 2 * displacement / initialVelocity
264 //
265 // We are also converting the duration from seconds to milliseconds,
266 // which explains why
267 // we are multiplying by 2000 (2 * 1000) instead of 2.
268 return MathUtils.clamp(Math.round(Math.abs(2000 * displacement / initial Velocity)),
269 MINIMUM_ANIMATION_DURATION_MS, MAXIMUM_ANIMATION_DURATION_MS);
270 }
271
272 // ========================================================================= ===================
273 // Layout Integration
274 // ========================================================================= ===================
275
276 /**
277 * Requests a new frame to be updated and rendered.
278 */
279 protected void requestUpdate() {
280 // NOTE(pedrosimonetti): mUpdateHost will be null in the ContextualSearc hEventFilterTest,
281 // so we always need to check if it's null before calling requestUpdate.
282 if (mUpdateHost != null) {
283 mUpdateHost.requestUpdate();
284 }
285 }
286
287 // ========================================================================= ===================
288 // Animation Framework
289 // ========================================================================= ===================
290
291 /**
292 * Animates the Contextual Search Panel to a given |height| with a custom |d uration|.
293 *
294 * @param height The height to animate to.
295 * @param duration The animation duration in milliseconds.
296 */
297 private void animatePanelTo(float height, long duration) {
298 animateProperty(Property.PANEL_HEIGHT, getHeight(), height, duration);
299 }
300
301 /**
302 * Animates the Contextual Search Panel.
303 *
304 * @param property The property which will be animated.
305 * @param start The initial value.
306 * @param end The final value.
307 * @param duration The animation duration in milliseconds.
308 */
309 protected void animateProperty(Property property, float start, float end, lo ng duration) {
310 if (duration > 0) {
311 if (animationIsRunning()) {
312 cancelAnimation(this, property);
313 }
314 addToAnimation(this, property, start, end, duration, 0);
315 }
316 }
317
318 /**
319 * Sets a property for an animation.
320 *
321 * @param prop The property to update.
322 * @param value New value of the property.
323 */
324 @Override
325 public void setProperty(Property prop, float value) {
326 if (prop == Property.PANEL_HEIGHT) {
327 setPanelHeight(value);
328 } else if (prop == Property.FIRST_RUN_PANEL_HEIGHT) {
329 setPanelHeightForPromoOptInAnimation(value);
330 }
331 }
332
333 /**
334 * Steps the animation forward and updates all the animated values.
335 * @param time The current time of the app in ms.
336 * @param jumpToEnd Whether to finish the animation.
337 * @return Whether the animation was finished.
338 */
339 public boolean onUpdateAnimation(long time, boolean jumpToEnd) {
340 boolean finished = true;
341 if (mLayoutAnimations != null) {
342 if (jumpToEnd) {
343 finished = mLayoutAnimations.finished();
344 mLayoutAnimations.updateAndFinish();
345 } else {
346 finished = mLayoutAnimations.update(time);
347 }
348
349 if (finished || jumpToEnd) {
350 mLayoutAnimations = null;
351 onAnimationFinished();
352 }
353 requestUpdate();
354 }
355 return finished;
356 }
357
358 /**
359 * Called when layout-specific actions are needed after the animation finish es.
360 */
361 protected void onAnimationStarted() {
362 }
363
364 /**
365 * Called when layout-specific actions are needed after the animation finish es.
366 */
367 protected void onAnimationFinished() {
368 // If animating to a particular PanelState, and after completing
369 // resizing the Panel to its desired state, then the Panel's state
370 // should be updated. This method also is called when an animation
371 // is cancelled (which can happen by a subsequent gesture while
372 // an animation is happening). That's why the actual height should
373 // be checked.
374 if (mAnimatingState != PanelState.UNDEFINED
375 && getHeight() == getPanelHeightFromState(mAnimatingState)) {
376 setPanelState(mAnimatingState, mAnimatingStateReason);
377 }
378
379 mAnimatingState = PanelState.UNDEFINED;
380 mAnimatingStateReason = StateChangeReason.UNKNOWN;
381 }
382
383 /**
384 * Creates an {@link org.chromium.chrome.browser.compositor.layouts.ChromeAn imation.Animatable}
385 * and adds it to the animation.
386 * Automatically sets the start value at the beginning of the animation.
387 */
388 protected <T extends Enum<?>> void addToAnimation(Animatable<T> object, T pr op, float start,
389 float end, long duration, long startTime) {
390 addToAnimation(object, prop, start, end, duration, startTime, false);
391 }
392
393 /**
394 * Creates an {@link org.chromium.chrome.browser.compositor.layouts.ChromeAn imation.Animatable}
395 * and adds it to the animation. Uses a deceleration interpolator by default .
396 */
397 protected <T extends Enum<?>> void addToAnimation(Animatable<T> object, T pr op, float start,
398 float end, long duration, long startTime, boolean setStartValueAfter Delay) {
399 addToAnimation(object, prop, start, end, duration, startTime, setStartVa lueAfterDelay,
400 ChromeAnimation.getDecelerateInterpolator());
401 }
402
403 /**
404 * Creates an {@link org.chromium.chrome.browser.compositor.layouts.ChromeAn imation.Animatable}
405 * and adds it to the animation.
406 *
407 * @param <T> The Enum type of the Property being used
408 * @param object The object being animated
409 * @param prop The property being animated
410 * @param start The starting value of the animation
411 * @param end The ending value of the animation
412 * @param duration The duration of the animation in ms
413 * @param startTime The start time in ms
414 * @param setStartValueAfterDelay See {@link Animation#setStartValueAfterSta rtDelay(boolean)}
415 * @param interpolator The interpolator to use for the animation
416 */
417 protected <T extends Enum<?>> void addToAnimation(Animatable<T> object, T pr op, float start,
418 float end, long duration, long startTime, boolean setStartValueAfter Delay,
419 Interpolator interpolator) {
420 ChromeAnimation.Animation<Animatable<?>> component = createAnimation(obj ect, prop, start,
421 end, duration, startTime, setStartValueAfterDelay, interpolator) ;
422 addToAnimation(component);
423 }
424
425 /**
426 * Appends an Animation to the current animation set and starts it immediate ly. If the set is
427 * already finished or doesn't exist, the animation set is also started.
428 */
429 protected void addToAnimation(ChromeAnimation.Animation<Animatable<?>> compo nent) {
430 if (mLayoutAnimations == null || mLayoutAnimations.finished()) {
431 onAnimationStarted();
432 mLayoutAnimations = new ChromeAnimation<Animatable<?>>();
433 mLayoutAnimations.start();
434 }
435 component.start();
436 mLayoutAnimations.add(component);
437 requestUpdate();
438 }
439
440 /**
441 * @return whether or not the animation is currently being run.
442 */
443 protected boolean animationIsRunning() {
444 return mLayoutAnimations != null && !mLayoutAnimations.finished();
445 }
446
447 /**
448 * Cancels any animation for the given object and property.
449 * @param object The object being animated.
450 * @param prop The property to search for.
451 */
452 protected <T extends Enum<?>> void cancelAnimation(Animatable<T> object, T p rop) {
453 if (mLayoutAnimations != null) {
454 mLayoutAnimations.cancel(object, prop);
455 }
456 }
457 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698