OLD | NEW |
(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.layouts.phone.stack; |
| 6 |
| 7 import static org.chromium.chrome.browser.compositor.layouts.ChromeAnimation.Ani
matableAnimation.addAnimation; |
| 8 import static org.chromium.chrome.browser.compositor.layouts.phone.stack.StackTa
b.Property.DISCARD_AMOUNT; |
| 9 import static org.chromium.chrome.browser.compositor.layouts.phone.stack.StackTa
b.Property.SCROLL_OFFSET; |
| 10 |
| 11 import android.view.animation.Interpolator; |
| 12 |
| 13 import org.chromium.chrome.browser.compositor.layouts.ChromeAnimation; |
| 14 import org.chromium.chrome.browser.compositor.layouts.ChromeAnimation.Animatable
; |
| 15 import org.chromium.chrome.browser.compositor.layouts.Layout.Orientation; |
| 16 import org.chromium.chrome.browser.compositor.layouts.components.LayoutTab; |
| 17 import org.chromium.ui.interpolators.BakedBezierInterpolator; |
| 18 |
| 19 /** |
| 20 * A factory that builds animations for the tab stack. |
| 21 */ |
| 22 public abstract class StackAnimation { |
| 23 public enum OverviewAnimationType { |
| 24 ENTER_STACK, |
| 25 NEW_TAB_OPENED, |
| 26 TAB_FOCUSED, |
| 27 VIEW_MORE, |
| 28 REACH_TOP, |
| 29 // Commit/uncommit tab discard animations |
| 30 DISCARD, |
| 31 DISCARD_ALL, |
| 32 UNDISCARD, |
| 33 // Start pinch animation un-tilt all the tabs. |
| 34 START_PINCH, |
| 35 // Special animation |
| 36 FULL_ROLL, |
| 37 // Used for when the current state of the system is not animating |
| 38 NONE, |
| 39 } |
| 40 |
| 41 public static final float SCALE_AMOUNT = 0.90f; |
| 42 protected static final float INITIAL_ALPHA_AMOUNT = 0.1f; |
| 43 protected static final float INITIAL_SCALE_AMOUNT = 0.75f; |
| 44 |
| 45 protected static final int ENTER_STACK_TOOLBAR_ALPHA_DURATION = 100; |
| 46 protected static final int ENTER_STACK_TOOLBAR_ALPHA_DELAY = 100; |
| 47 protected static final int ENTER_STACK_ANIMATION_DURATION = 300; |
| 48 protected static final int ENTER_STACK_RESIZE_DELAY = 10; |
| 49 protected static final int ENTER_STACK_BORDER_ALPHA_DURATION = 200; |
| 50 protected static final int ENTER_STACK_BORDER_ALPHA_DELAY = 0; |
| 51 protected static final float ENTER_STACK_SIZE_RATIO = 0.35f; |
| 52 |
| 53 protected static final int TAB_FOCUSED_TOOLBAR_ALPHA_DURATION = 250; |
| 54 protected static final int TAB_FOCUSED_TOOLBAR_ALPHA_DELAY = 0; |
| 55 protected static final int TAB_FOCUSED_ANIMATION_DURATION = 400; |
| 56 protected static final int TAB_FOCUSED_Y_STACK_DURATION = 200; |
| 57 protected static final int TAB_FOCUSED_BORDER_ALPHA_DURATION = 200; |
| 58 protected static final int TAB_FOCUSED_BORDER_ALPHA_DELAY = 0; |
| 59 protected static final int TAB_FOCUSED_MAX_DELAY = 100; |
| 60 |
| 61 protected static final int VIEW_MORE_ANIMATION_DURATION = 400; |
| 62 protected static final float VIEW_MORE_SIZE_RATIO = 0.75f; |
| 63 protected static final int VIEW_MORE_MIN_SIZE = 200; |
| 64 |
| 65 protected static final int REACH_TOP_ANIMATION_DURATION = 400; |
| 66 |
| 67 protected static final int UNDISCARD_ANIMATION_DURATION = 150; |
| 68 |
| 69 protected static final int TAB_OPENED_ANIMATION_DURATION = 300; |
| 70 protected static final int TAB_OPENED_BORDER_ALPHA_DURATION = 100; |
| 71 protected static final int TAB_OPENED_BORDER_ALPHA_DELAY = 100; |
| 72 |
| 73 protected static final int DISCARD_ANIMATION_DURATION = 150; |
| 74 protected static final int TAB_REORDER_DURATION = 500; |
| 75 protected static final int TAB_REORDER_START_SPAN = 400; |
| 76 |
| 77 protected static final int START_PINCH_ANIMATION_DURATION = 75; |
| 78 |
| 79 protected static final int FULL_ROLL_ANIMATION_DURATION = 1000; |
| 80 |
| 81 protected final float mWidth; |
| 82 protected final float mHeight; |
| 83 protected final float mHeightMinusTopControls; |
| 84 protected final float mBorderTopHeight; |
| 85 protected final float mBorderTopOpaqueHeight; |
| 86 protected final float mBorderLeftWidth; |
| 87 |
| 88 /** |
| 89 * Protected constructor. |
| 90 * |
| 91 * @param width The width of the layout in dp. |
| 92 * @param height The height of the layout in dp. |
| 93 * @param heightMinusTopControls The height of the layout minus the top
controls in dp. |
| 94 * @param borderFramePaddingTop The top padding of the border frame in
dp. |
| 95 * @param borderFramePaddingTopOpaque The opaque top padding of the border f
rame in dp. |
| 96 * @param borderFramePaddingLeft The left padding of the border frame i
n dp. |
| 97 */ |
| 98 protected StackAnimation(float width, float height, float heightMinusTopCont
rols, |
| 99 float borderFramePaddingTop, float borderFramePaddingTopOpaque, |
| 100 float borderFramePaddingLeft) { |
| 101 mWidth = width; |
| 102 mHeight = height; |
| 103 mHeightMinusTopControls = heightMinusTopControls; |
| 104 |
| 105 mBorderTopHeight = borderFramePaddingTop; |
| 106 mBorderTopOpaqueHeight = borderFramePaddingTopOpaque; |
| 107 mBorderLeftWidth = borderFramePaddingLeft; |
| 108 } |
| 109 |
| 110 /** |
| 111 * The factory method that creates the particular factory method based on th
e orientation |
| 112 * parameter. |
| 113 * |
| 114 * @param width The width of the layout in dp. |
| 115 * @param height The height of the layout in dp. |
| 116 * @param heightMinusTopControls The height of the layout minus the top
controls in dp. |
| 117 * @param borderFramePaddingTop The top padding of the border frame in
dp. |
| 118 * @param borderFramePaddingTopOpaque The opaque top padding of the border f
rame in dp. |
| 119 * @param borderFramePaddingLeft The left padding of the border frame i
n dp. |
| 120 * @param orientation The orientation that will be used to c
reate the |
| 121 * appropriate {@link StackAnimation}. |
| 122 * @return The TabSwitcherAnimationFactory instan
ce. |
| 123 */ |
| 124 public static StackAnimation createAnimationFactory(float width, float heigh
t, |
| 125 float heightMinusTopControls, float borderFramePaddingTop, |
| 126 float borderFramePaddingTopOpaque, float borderFramePaddingLeft, int
orientation) { |
| 127 StackAnimation factory = null; |
| 128 switch (orientation) { |
| 129 case Orientation.LANDSCAPE: |
| 130 factory = new StackAnimationLandscape(width, height, heightMinus
TopControls, |
| 131 borderFramePaddingTop, borderFramePaddingTopOpaque, bord
erFramePaddingLeft); |
| 132 break; |
| 133 case Orientation.PORTRAIT: |
| 134 default: |
| 135 factory = new StackAnimationPortrait(width, height, heightMinusT
opControls, |
| 136 borderFramePaddingTop, borderFramePaddingTopOpaque, bord
erFramePaddingLeft); |
| 137 break; |
| 138 } |
| 139 |
| 140 return factory; |
| 141 } |
| 142 |
| 143 /** |
| 144 * The wrapper method responsible for delegating the animations request to t
he appropriate |
| 145 * helper method. Not all parameters are used for each request. |
| 146 * |
| 147 * @param type The type of animation to be created. This is what |
| 148 * determines which helper method is called. |
| 149 * @param tabs The tabs that make up the current stack that will |
| 150 * be animated. |
| 151 * @param focusIndex The index of the tab that is the focus of this anima
tion. |
| 152 * @param sourceIndex The index of the tab that triggered this animation. |
| 153 * @param spacing The default spacing between the tabs. |
| 154 * @param scrollOffset The scroll offset in the current orientation. |
| 155 * @param warpSize The warp size of the transform from scroll space to
screen space. |
| 156 * @param discardRange The range of the discard amount value. |
| 157 * @return The resulting TabSwitcherAnimation that will animate
the tabs. |
| 158 */ |
| 159 public ChromeAnimation<?> createAnimatorSetForType(OverviewAnimationType typ
e, StackTab[] tabs, |
| 160 int focusIndex, int sourceIndex, int spacing, float scrollOffset, fl
oat warpSize, |
| 161 float discardRange) { |
| 162 ChromeAnimation<?> set = null; |
| 163 |
| 164 if (tabs != null) { |
| 165 switch (type) { |
| 166 case ENTER_STACK: |
| 167 set = createEnterStackAnimatorSet(tabs, focusIndex, spacing,
warpSize); |
| 168 break; |
| 169 case TAB_FOCUSED: |
| 170 set = createTabFocusedAnimatorSet(tabs, focusIndex, spacing,
warpSize); |
| 171 break; |
| 172 case VIEW_MORE: |
| 173 set = createViewMoreAnimatorSet(tabs, sourceIndex); |
| 174 break; |
| 175 case REACH_TOP: |
| 176 set = createReachTopAnimatorSet(tabs, warpSize); |
| 177 break; |
| 178 case DISCARD: |
| 179 // Purposeful fall through |
| 180 case DISCARD_ALL: |
| 181 // Purposeful fall through |
| 182 case UNDISCARD: |
| 183 set = createUpdateDiscardAnimatorSet(tabs, spacing, warpSize
, discardRange); |
| 184 break; |
| 185 case NEW_TAB_OPENED: |
| 186 set = createNewTabOpenedAnimatorSet(tabs, focusIndex, discar
dRange); |
| 187 break; |
| 188 case START_PINCH: |
| 189 set = createStartPinchAnimatorSet(tabs); |
| 190 break; |
| 191 case FULL_ROLL: |
| 192 set = createFullRollAnimatorSet(tabs); |
| 193 break; |
| 194 case NONE: |
| 195 break; |
| 196 } |
| 197 } |
| 198 return set; |
| 199 } |
| 200 |
| 201 protected abstract float getScreenSizeInScrollDirection(); |
| 202 |
| 203 protected abstract float getScreenPositionInScrollDirection(StackTab tab); |
| 204 |
| 205 protected abstract void addTiltScrollAnimation(ChromeAnimation<Animatable<?>
> set, |
| 206 LayoutTab tab, float end, int duration, int startTime); |
| 207 |
| 208 /** |
| 209 * @return The direction the tab should come from as it is created. -1 mean
s top/right, 1 means |
| 210 * bottom/left. |
| 211 */ |
| 212 protected abstract int getTabCreationDirection(); |
| 213 |
| 214 /** |
| 215 * Responsible for generating the animations that shows the stack |
| 216 * being entered. |
| 217 * |
| 218 * @param tabs The tabs that make up the stack. These are the |
| 219 * tabs that will be affected by the TabSwitcherAnimation. |
| 220 * @param focusIndex The focused index. In this case, this is the index of |
| 221 * the tab that was being viewed before entering the stack
. |
| 222 * @param spacing The default spacing between tabs. |
| 223 * @param warpSize The warp size of the transform from scroll space to scr
een space. |
| 224 * @return The TabSwitcherAnimation instance that will tween the |
| 225 * tabs to create the appropriate animation. |
| 226 */ |
| 227 protected abstract ChromeAnimation<?> createEnterStackAnimatorSet( |
| 228 StackTab[] tabs, int focusIndex, int spacing, float warpSize); |
| 229 |
| 230 /** |
| 231 * Responsible for generating the animations that shows a tab being |
| 232 * focused (the stack is being left). |
| 233 * |
| 234 * @param tabs The tabs that make up the stack. These are the |
| 235 * tabs that will be affected by the TabSwitcherAnimation. |
| 236 * @param focusIndex The focused index. In this case, this is the index of |
| 237 * the tab clicked and is being brought up to view. |
| 238 * @param spacing The default spacing between tabs. |
| 239 * @param warpSize The warp size of the transform from scroll space to scr
een space. |
| 240 * @return The TabSwitcherAnimation instance that will tween the |
| 241 * tabs to create the appropriate animation. |
| 242 */ |
| 243 protected abstract ChromeAnimation<?> createTabFocusedAnimatorSet( |
| 244 StackTab[] tabs, int focusIndex, int spacing, float warpSize); |
| 245 |
| 246 /** |
| 247 * Responsible for generating the animations that Shows more of the selected
tab. |
| 248 * |
| 249 * @param tabs The tabs that make up the stack. These are the |
| 250 * tabs that will be affected by the TabSwitcherAnimati
on. |
| 251 * @param selectedIndex The selected index. In this case, this is the index
of |
| 252 * the tab clicked and is being brought up to view. |
| 253 * @return The TabSwitcherAnimation instance that will tween th
e |
| 254 * tabs to create the appropriate animation. |
| 255 */ |
| 256 protected abstract ChromeAnimation<?> createViewMoreAnimatorSet( |
| 257 StackTab[] tabs, int selectedIndex); |
| 258 |
| 259 /** |
| 260 * Responsible for generating the TabSwitcherAnimation that moves the tabs u
p so they |
| 261 * reach the to top the screen. |
| 262 * |
| 263 * @param tabs The tabs that make up the stack. These are the |
| 264 * tabs that will be affected by the TabSwitcherAnimati
on. |
| 265 * @param warpSize The warp size of the transform from scroll space to s
creen space. |
| 266 * @return The TabSwitcherAnimation instance that will tween th
e |
| 267 * tabs to create the appropriate animation. |
| 268 */ |
| 269 protected abstract ChromeAnimation<?> createReachTopAnimatorSet( |
| 270 StackTab[] tabs, float warpSize); |
| 271 |
| 272 /** |
| 273 * Responsible for generating the animations that moves the tabs back in fro
m |
| 274 * discard attempt or commit the current discard (if any). It also re-even t
he tabs |
| 275 * if one of then is removed. |
| 276 * |
| 277 * @param tabs The tabs that make up the stack. These are the |
| 278 * tabs that will be affected by the TabSwitcherAnimatio
n. |
| 279 * @param spacing The default spacing between tabs. |
| 280 * @param warpSize The warp size of the transform from scroll space to s
creen space. |
| 281 * @param discardRange The maximum value the discard amount. |
| 282 * @return The TabSwitcherAnimation instance that will tween the |
| 283 * tabs to create the appropriate animation. |
| 284 */ |
| 285 protected ChromeAnimation<?> createUpdateDiscardAnimatorSet( |
| 286 StackTab[] tabs, int spacing, float warpSize, float discardRange) { |
| 287 ChromeAnimation<Animatable<?>> set = new ChromeAnimation<Animatable<?>>(
); |
| 288 |
| 289 int dyingTabsCount = 0; |
| 290 float firstDyingTabOffset = 0; |
| 291 for (int i = 0; i < tabs.length; ++i) { |
| 292 StackTab tab = tabs[i]; |
| 293 |
| 294 addTiltScrollAnimation(set, tab.getLayoutTab(), 0.0f, UNDISCARD_ANIM
ATION_DURATION, 0); |
| 295 |
| 296 if (tab.isDying()) { |
| 297 dyingTabsCount++; |
| 298 if (dyingTabsCount == 1) { |
| 299 firstDyingTabOffset = getScreenPositionInScrollDirection(tab
); |
| 300 } |
| 301 } |
| 302 } |
| 303 |
| 304 Interpolator interpolator = BakedBezierInterpolator.FADE_OUT_CURVE; |
| 305 |
| 306 int newIndex = 0; |
| 307 for (int i = 0; i < tabs.length; ++i) { |
| 308 StackTab tab = tabs[i]; |
| 309 long startTime = (long) Math.max(0, TAB_REORDER_START_SPAN |
| 310 / getScreenSizeInScrollDirection() |
| 311 * (getScreenPositionInScrollDirection(tab) - firstDy
ingTabOffset)); |
| 312 if (tab.isDying()) { |
| 313 float discard = tab.getDiscardAmount(); |
| 314 if (discard == 0.0f) discard = isDefaultDiscardDirectionPositive
() ? 0.0f : -0.0f; |
| 315 float s = Math.copySign(1.0f, discard); |
| 316 long duration = (long) (DISCARD_ANIMATION_DURATION |
| 317 * (1.0f - Math.abs(discard / discardRange))); |
| 318 addAnimation(set, tab, DISCARD_AMOUNT, discard, discardRange * s
, duration, |
| 319 startTime, false, interpolator); |
| 320 } else { |
| 321 if (tab.getDiscardAmount() != 0.f) { |
| 322 addAnimation(set, tab, DISCARD_AMOUNT, tab.getDiscardAmount(
), 0.0f, |
| 323 UNDISCARD_ANIMATION_DURATION, 0); |
| 324 } |
| 325 |
| 326 float newScrollOffset = StackTab.screenToScroll(spacing * newInd
ex, warpSize); |
| 327 |
| 328 // If the tab is not dying we want to readjust it's position |
| 329 // based on the new spacing requirements. For a fully discarded
tab, just |
| 330 // put it in the right place. |
| 331 if (tab.getDiscardAmount() >= discardRange) { |
| 332 tab.setScrollOffset(newScrollOffset); |
| 333 tab.setScale(SCALE_AMOUNT); |
| 334 } else { |
| 335 float start = tab.getScrollOffset(); |
| 336 if (start != newScrollOffset) { |
| 337 addAnimation(set, tab, SCROLL_OFFSET, start, newScrollOf
fset, |
| 338 TAB_REORDER_DURATION, startTime); |
| 339 } |
| 340 } |
| 341 newIndex++; |
| 342 } |
| 343 } |
| 344 return set; |
| 345 } |
| 346 |
| 347 /** |
| 348 * This is used to determine the discard direction when user just clicks X t
o close a tab. |
| 349 * On portrait, positive direction (x) is right hand side. |
| 350 * On landscape, positive direction (y) is towards bottom. |
| 351 * @return True, if default discard direction is positive. |
| 352 */ |
| 353 protected abstract boolean isDefaultDiscardDirectionPositive(); |
| 354 |
| 355 /** |
| 356 * Responsible for generating the animations that shows a new tab being open
ed. |
| 357 * |
| 358 * @param tabs The tabs that make up the stack. These are the |
| 359 * tabs that will be affected by the TabSwitcherAnimati
on. |
| 360 * @param focusIndex The focused index. In this case, this is the index
of |
| 361 * the tab that was just created. |
| 362 * @param discardRange The maximum value the discard amount. |
| 363 * @return The TabSwitcherAnimation instance that will tween th
e |
| 364 * tabs to create the appropriate animation. |
| 365 */ |
| 366 // TODO(dtrainor): Remove this after confirming nothing uses this. |
| 367 protected ChromeAnimation<?> createNewTabOpenedAnimatorSet( |
| 368 StackTab[] tabs, int focusIndex, float discardRange) { |
| 369 if (focusIndex < 0 || focusIndex >= tabs.length) return null; |
| 370 ChromeAnimation<Animatable<?>> set = new ChromeAnimation<Animatable<?>>(
); |
| 371 |
| 372 StackTab tab = tabs[focusIndex]; |
| 373 tab.getLayoutTab().setVisible(false); |
| 374 tab.setXInStackInfluence(0.0f); |
| 375 tab.setYInStackInfluence(0.0f); |
| 376 tab.setDiscardFromClick(true); |
| 377 tab.setDiscardOriginX(tab.getLayoutTab().getOriginalContentWidth()); |
| 378 tab.setDiscardOriginY(tab.getLayoutTab().getOriginalContentHeight() / 2.
f); |
| 379 tab.getLayoutTab().setAlpha(0.0f); |
| 380 tab.getLayoutTab().setBorderAlpha(0.0f); |
| 381 addAnimation(set, tab, DISCARD_AMOUNT, getTabCreationDirection() * disca
rdRange, 0.0f, |
| 382 TAB_OPENED_ANIMATION_DURATION, 0, false, |
| 383 ChromeAnimation.getAccelerateInterpolator()); |
| 384 return set; |
| 385 } |
| 386 |
| 387 /** |
| 388 * Responsible for generating the animations that flattens tabs when a pinch
begins. |
| 389 * |
| 390 * @param tabs The tabs that make up the stack. These are the tabs that will |
| 391 * be affected by the animations. |
| 392 * @return The TabSwitcherAnimation instance that will tween the tabs to |
| 393 * create the appropriate animation. |
| 394 */ |
| 395 protected ChromeAnimation<?> createStartPinchAnimatorSet(StackTab[] tabs) { |
| 396 ChromeAnimation<Animatable<?>> set = new ChromeAnimation<Animatable<?>>(
); |
| 397 |
| 398 for (int i = 0; i < tabs.length; ++i) { |
| 399 addTiltScrollAnimation( |
| 400 set, tabs[i].getLayoutTab(), 0, START_PINCH_ANIMATION_DURATI
ON, 0); |
| 401 } |
| 402 |
| 403 return set; |
| 404 } |
| 405 |
| 406 /** |
| 407 * Responsible for generating the animations that make all the tabs do a ful
l roll. |
| 408 * |
| 409 * @param tabs The tabs that make up the stack. These are the tabs that will
be affected by the |
| 410 * animations. |
| 411 * @return The TabSwitcherAnimation instance that will tween the tabs to
create the |
| 412 * appropriate animation. |
| 413 */ |
| 414 protected ChromeAnimation<?> createFullRollAnimatorSet(StackTab[] tabs) { |
| 415 ChromeAnimation<Animatable<?>> set = new ChromeAnimation<Animatable<?>>(
); |
| 416 |
| 417 for (int i = 0; i < tabs.length; ++i) { |
| 418 LayoutTab layoutTab = tabs[i].getLayoutTab(); |
| 419 // Set the pivot |
| 420 layoutTab.setTiltX(layoutTab.getTiltX(), layoutTab.getScaledContentH
eight() / 2.0f); |
| 421 layoutTab.setTiltY(layoutTab.getTiltY(), layoutTab.getScaledContentW
idth() / 2.0f); |
| 422 // Create the angle animation |
| 423 addTiltScrollAnimation(set, layoutTab, -360.0f, FULL_ROLL_ANIMATION_
DURATION, 0); |
| 424 } |
| 425 |
| 426 return set; |
| 427 } |
| 428 |
| 429 /** |
| 430 * @return The offset for the toolbar to line the top up with the opaque com
ponent of the |
| 431 * border. |
| 432 */ |
| 433 protected float getToolbarOffsetToLineUpWithBorder() { |
| 434 final float toolbarHeight = mHeight - mHeightMinusTopControls; |
| 435 return toolbarHeight - mBorderTopOpaqueHeight; |
| 436 } |
| 437 } |
OLD | NEW |