Commit 906a5ee4 authored by Mark Cogan's avatar Mark Cogan Committed by Commit Bot

[iOS] Tune grid dismissal when only one tab is present.

This CL tweaks the dismissal animation into the tab grid when only the
selected cell is present.

Prior to this CL, because there were no non-selected cells animating, the
animation which runs the completion block ("(4)" in the comments) would
(I think) be a no-op, so the completion block would run immediately. The
net effect is that the selected cell just jumps into place with no real
transition.

To handle this, this CL restructures the animations when there is only a
single (selected) cell to animate. Updated comments explain the new
structure.

This CL also factors out the completion block and longer animation blocks
for readability, and renumbers the animations for clarity.

Bug: 820410
Cq-Include-Trybots: master.tryserver.chromium.mac:ios-simulator-cronet;master.tryserver.chromium.mac:ios-simulator-full-configs
Change-Id: Iaedbc131fd44b28a7fcc8b94cf5e97e46a86241c
Reviewed-on: https://chromium-review.googlesource.com/973206Reviewed-by: default avataredchin <edchin@chromium.org>
Commit-Queue: Mark Cogan <marq@chromium.org>
Cr-Commit-Position: refs/heads/master@{#545027}
parent 979a7404
...@@ -105,25 +105,52 @@ ...@@ -105,25 +105,52 @@
// of the overall animation duration. // of the overall animation duration.
// (1) Fading out the view being dismissed. This happens during the first 20% // (1) Fading out the view being dismissed. This happens during the first 20%
// of the overall animation. // of the overall animation.
// (2) Zooming the selected cell into position. This starts immediately and // (2) Fading in the selected cell highlight indicator. This starts after a
// has a duration of |staggeredDuration|.
// (3) Fading in the selected cell highlight indicator. This starts after a
// delay of |staggeredDuration| and runs to the end of the transition. // delay of |staggeredDuration| and runs to the end of the transition.
// This means it starts as soon as (2) ends. // This means it starts as soon as (3) ends.
// (3) Zooming the selected cell into position. This starts immediately and
// has a duration of |staggeredDuration|.
// (4) Zooming all other cells into position. This ends at the end of the // (4) Zooming all other cells into position. This ends at the end of the
// transition and has a duration of |staggeredDuration|. // transition and has a duration of |staggeredDuration|.
// //
// Animation (4) always runs the whole duration of the transition, so it's // Animation (4) always runs the whole duration of the transition, so it's
// where the completion block that does overall cleanup is run. // where the completion block that does overall cleanup is run.
// In the case where there is only a single cell to animate (the selected
// one), not all of the above animations are required. Instead of animations
// (3), and (4), instead the following animation will be used:
// (5) Zooming the selected cell into position as in (3), but running the
// whole duration of the transition.
// In this case animation (5) will run the completion block.
// TODO(crbug.com/804539): Factor all of these animations into a single // TODO(crbug.com/804539): Factor all of these animations into a single
// Orchestrator object that the present and dismiss animation can both use. // Orchestrator object that the present and dismiss animation can both use.
// TODO(crbug.com/820410): Tune the timing, relative pacing, and curves of // TODO(crbug.com/820410): Tune the timing, relative pacing, and curves of
// these animations. // these animations.
// Completion block to be run when the transition completes.
auto completion = ^(BOOL finished) {
// Clean up all of the proxy cells.
for (GridTransitionLayoutItem* item in layout.items) {
[item.cell removeFromSuperview];
}
// If the transition was cancelled, restore the dismissing view and
// remove the grid view.
// If not, remove the dismissing view.
if (transitionContext.transitionWasCancelled) {
dismissingView.alpha = 1.0;
[gridView removeFromSuperview];
} else {
[dismissingView removeFromSuperview];
}
// Mark the transition as completed.
[transitionContext completeTransition:YES];
};
NSTimeInterval duration = [self transitionDuration:transitionContext]; NSTimeInterval duration = [self transitionDuration:transitionContext];
CGFloat staggeredDuration = duration * 0.7; CGFloat staggeredDuration = duration * 0.7;
UICollectionViewCell* selectedCell = layout.selectedItem.cell;
// (1) Fade out active tab view. // (1) Fade out active tab view.
[UIView animateWithDuration:duration / 5 [UIView animateWithDuration:duration / 5
...@@ -132,24 +159,7 @@ ...@@ -132,24 +159,7 @@
} }
completion:nil]; completion:nil];
// (2) Zoom selected cell into place. Also round its corners. // (2) Show highlight state on selected cell.
UICollectionViewCell* selectedCell = layout.selectedItem.cell;
[UIView animateWithDuration:staggeredDuration
delay:0.0
options:UIViewAnimationOptionCurveEaseOut
animations:^{
selectedCell.center = [containerView
convertPoint:layout.selectedItem.attributes.center
fromView:nil];
selectedCell.bounds =
layout.selectedItem.attributes.bounds;
selectedCell.transform = CGAffineTransformIdentity;
selectedCell.contentView.layer.cornerRadius =
finalSelectedCellCornerRadius;
}
completion:nil];
// (3) Show highlight state on selected cell.
[UIView animateWithDuration:duration - staggeredDuration [UIView animateWithDuration:duration - staggeredDuration
delay:staggeredDuration delay:staggeredDuration
options:UIViewAnimationOptionCurveEaseIn options:UIViewAnimationOptionCurveEaseIn
...@@ -158,37 +168,53 @@ ...@@ -158,37 +168,53 @@
} }
completion:nil]; completion:nil];
// (4) Zoom other cells into place. // Animation block for zooming the selected cell into place and rounding
[UIView animateWithDuration:staggeredDuration // its corners.
delay:duration - staggeredDuration auto selectedCellAnimation = ^{
options:UIViewAnimationOptionCurveEaseOut selectedCell.center =
animations:^{ [containerView convertPoint:layout.selectedItem.attributes.center
for (GridTransitionLayoutItem* item in layout.items) { fromView:nil];
if (item == layout.selectedItem) selectedCell.bounds = layout.selectedItem.attributes.bounds;
continue; selectedCell.transform = CGAffineTransformIdentity;
UIView* cell = item.cell; selectedCell.contentView.layer.cornerRadius = finalSelectedCellCornerRadius;
cell.center = };
[containerView convertPoint:item.attributes.center fromView:nil];
cell.transform = CGAffineTransformIdentity; // If there's more than one cell to animate, run animations (3) and (4), and
} // call the completion block after (4). If there's only one cell to animate,
// run (5) and have it call the completion block.
if (layout.items.count > 1) {
// (3) Zoom selected cell into place.
[UIView animateWithDuration:staggeredDuration
delay:0.0
options:UIViewAnimationOptionCurveEaseOut
animations:selectedCellAnimation
completion:nil];
// (4) Zoom other cells into place.
auto unselectedCellsAnimation = ^{
for (GridTransitionLayoutItem* item in layout.items) {
if (item == layout.selectedItem)
continue;
UIView* cell = item.cell;
cell.center =
[containerView convertPoint:item.attributes.center fromView:nil];
cell.transform = CGAffineTransformIdentity;
} }
completion:^(BOOL finished) { };
// Clean up all of the proxy cells.
for (GridTransitionLayoutItem* item in layout.items) { [UIView animateWithDuration:staggeredDuration
[item.cell removeFromSuperview]; delay:duration - staggeredDuration
} options:UIViewAnimationOptionCurveEaseOut
// If the transition was cancelled, restore the dismissing view and animations:unselectedCellsAnimation
// remove the grid view. completion:completion];
// If not, remove the dismissing view. } else {
if (transitionContext.transitionWasCancelled) { // (5) Zoom selected cell into place over whole duration, with completion.
dismissingView.alpha = 1.0; [UIView animateWithDuration:duration
[gridView removeFromSuperview]; delay:0
} else { options:UIViewAnimationOptionCurveEaseOut
[dismissingView removeFromSuperview]; animations:selectedCellAnimation
} completion:completion];
// Mark the transition as completed. }
[transitionContext completeTransition:YES];
}];
} }
@end @end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment