Commit b5df98ac authored by Gauthier Ambard's avatar Gauthier Ambard Committed by Commit Bot

[iOS] Add animation for "Switch to this tab"

This CL adds animations when the user is tapping the "switch to this
tab" indicator in the omnibox suggestions.

Bug: 893121
Change-Id: Ia7af97f6175efa959bbb2e84ab5661f00adedf81
Reviewed-on: https://chromium-review.googlesource.com/c/1322871Reviewed-by: default avatarMark Cogan <marq@chromium.org>
Commit-Queue: Gauthier Ambard <gambard@chromium.org>
Cr-Commit-Position: refs/heads/master@{#607174}
parent a622b5f8
......@@ -184,12 +184,14 @@
#import "ios/chrome/browser/ui/recent_tabs/recent_tabs_coordinator.h"
#import "ios/chrome/browser/ui/sad_tab/sad_tab_legacy_coordinator.h"
#import "ios/chrome/browser/ui/side_swipe/side_swipe_controller.h"
#import "ios/chrome/browser/ui/side_swipe/swipe_view.h"
#import "ios/chrome/browser/ui/snackbar/snackbar_coordinator.h"
#import "ios/chrome/browser/ui/static_content/static_html_native_content.h"
#import "ios/chrome/browser/ui/tabs/background_tab_animation_view.h"
#import "ios/chrome/browser/ui/tabs/foreground_tab_animation_view.h"
#import "ios/chrome/browser/ui/tabs/requirements/tab_strip_constants.h"
#import "ios/chrome/browser/ui/tabs/requirements/tab_strip_presentation.h"
#import "ios/chrome/browser/ui/tabs/switch_to_tab_animation_view.h"
#import "ios/chrome/browser/ui/tabs/tab_strip_legacy_coordinator.h"
#import "ios/chrome/browser/ui/toolbar/adaptive_toolbar_coordinator.h"
#import "ios/chrome/browser/ui/toolbar/adaptive_toolbar_view_controller.h"
......@@ -4770,26 +4772,66 @@ applicationCommandEndpoint:(id<ApplicationCommands>)applicationCommandEndpoint {
}
- (void)unfocusOmniboxAndSwitchToTabWithURL:(const GURL&)URL {
// TODO(crbug.com/893121): Add animations.
// Cancelling the omnibox edit makes |URL| unsafe as it is not longer
// retained.
GURL retainedURL = URL;
[self.dispatcher cancelOmniboxEdit];
// TODO(crbug.com/893121): This should probably live in the WebState.
NSInteger newWebStateIndex = 0;
WebStateList* webStateList = self.tabModel.webStateList;
web::WebState* currentWebState = webStateList->GetActiveWebState();
for (NSInteger index = 0; index < webStateList->count(); index++) {
web::WebState* webState = webStateList->GetWebStateAt(index);
// TODO(crbug.com/893121): This should probably live in the WebStateList.
while (newWebStateIndex < webStateList->count()) {
web::WebState* webState = webStateList->GetWebStateAt(newWebStateIndex);
if (webState != currentWebState &&
retainedURL == webState->GetVisibleURL()) {
self.tabModel.webStateList->ActivateWebStateAt(index);
return;
if (webState != currentWebState && URL == webState->GetVisibleURL()) {
break;
}
newWebStateIndex++;
}
if (newWebStateIndex >= webStateList->count())
return;
web::WebState* webStateBeingActivated =
webStateList->GetWebStateAt(newWebStateIndex);
UIView* snapshotView = [self.view snapshotViewAfterScreenUpdates:NO];
SwipeView* swipeView = [[SwipeView alloc]
initWithFrame:self.contentArea.frame
topMargin:[self snapshotEdgeInsetsForWebState:webStateBeingActivated]
.top];
[swipeView setTopToolbarImage:[self.primaryToolbarCoordinator
toolbarSideSwipeSnapshotForWebState:
webStateBeingActivated]];
[swipeView setBottomToolbarImage:[self.secondaryToolbarCoordinator
toolbarSideSwipeSnapshotForWebState:
webStateBeingActivated]];
SnapshotTabHelper::FromWebState(webStateBeingActivated)
->RetrieveColorSnapshot(^(UIImage* image) {
if (PagePlaceholderTabHelper::FromWebState(webStateBeingActivated)
->will_add_placeholder_for_next_navigation()) {
[swipeView setImage:SnapshotTabHelper::GetDefaultSnapshotImage()];
} else {
[swipeView setImage:image];
}
});
SwitchToTabAnimationView* animationView =
[[SwitchToTabAnimationView alloc] initWithFrame:self.view.bounds];
[self.view addSubview:animationView];
SwitchToTabAnimationPosition position =
newWebStateIndex > webStateList->active_index()
? SwitchToTabAnimationPositionAfter
: SwitchToTabAnimationPositionBefore;
[animationView animateFromCurrentView:snapshotView
toNewView:swipeView
inPosition:position];
[self.dispatcher cancelOmniboxEdit];
webStateList->ActivateWebStateAt(newWebStateIndex);
}
#pragma mark - TabModelObserver methods
......
......@@ -254,7 +254,7 @@ class BrowserViewControllerTest : public BlockCleanupTest {
std::make_unique<web::TestNavigationManager>());
id mockJsInjectionReceiver = OCMClassMock([CRWJSInjectionReceiver class]);
web_state->SetJSInjectionReceiver(mockJsInjectionReceiver);
AttachTabHelpers(web_state.get(), true);
AttachTabHelpers(web_state.get(), false);
return web_state;
}
......
......@@ -9,6 +9,8 @@ source_set("tabs") {
"background_tab_animation_view.mm",
"foreground_tab_animation_view.h",
"foreground_tab_animation_view.mm",
"switch_to_tab_animation_view.h",
"switch_to_tab_animation_view.mm",
"tab_strip_controller+placeholder_view.h",
"tab_strip_controller.h",
"tab_strip_controller.mm",
......
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef IOS_CHROME_BROWSER_UI_TABS_SWITCH_TO_TAB_ANIMATION_VIEW_H_
#define IOS_CHROME_BROWSER_UI_TABS_SWITCH_TO_TAB_ANIMATION_VIEW_H_
#import <UIKit/UIKit.h>
// Position of the tab the SwitchToTabAnimationView will switch to, relatively
// to the currently active tab.
typedef NS_ENUM(NSInteger, SwitchToTabAnimationPosition) {
SwitchToTabAnimationPositionBefore,
SwitchToTabAnimationPositionAfter,
};
// View to manage the animation when switching tabs.
@interface SwitchToTabAnimationView : UIView
- (instancetype)init NS_UNAVAILABLE;
- (instancetype)initWithCoder:(NSCoder*)aDecoder NS_UNAVAILABLE;
// Starts the animation between the |currentView|, to the |newView| which has a
// |position| relatively to the |currentView|. At the end of the animation, this
// view is removing itself from its parent.
- (void)animateFromCurrentView:(UIView*)currentView
toNewView:(UIView*)newView
inPosition:(SwitchToTabAnimationPosition)position;
@end
#endif // IOS_CHROME_BROWSER_UI_TABS_SWITCH_TO_TAB_ANIMATION_VIEW_H_
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#import "ios/chrome/browser/ui/tabs/switch_to_tab_animation_view.h"
#include "base/i18n/rtl.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
namespace {
const CGFloat kMiddleMargin = 80;
const CGFloat kAnimationTime = 0.35;
} // namespace
@implementation SwitchToTabAnimationView
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
self.backgroundColor = [UIColor colorWithWhite:0.13 alpha:1];
}
return self;
}
- (void)animateFromCurrentView:(UIView*)currentView
toNewView:(UIView*)newView
inPosition:(SwitchToTabAnimationPosition)position {
CGRect leftViewInitialFrame = self.bounds;
CGRect rightViewInitialFrame = self.bounds;
CGRect leftViewFinalFrame = self.bounds;
CGRect rightViewFinalFrame = self.bounds;
UIView* rightView;
UIView* leftView;
BOOL directionLeft =
((position == SwitchToTabAnimationPositionBefore) &&
!base::i18n::IsRTL()) ||
((position == SwitchToTabAnimationPositionAfter) && base::i18n::IsRTL());
if (directionLeft) {
rightView = currentView;
leftView = newView;
leftViewInitialFrame.origin.x -= self.bounds.size.width + kMiddleMargin;
rightViewFinalFrame.origin.x += self.bounds.size.width + kMiddleMargin;
} else {
rightView = newView;
leftView = currentView;
rightViewInitialFrame.origin.x += self.bounds.size.width + kMiddleMargin;
leftViewFinalFrame.origin.x -= self.bounds.size.width + kMiddleMargin;
}
[self addSubview:rightView];
[self addSubview:leftView];
leftView.frame = leftViewInitialFrame;
rightView.frame = rightViewInitialFrame;
[UIView animateWithDuration:kAnimationTime
animations:^{
leftView.frame = leftViewFinalFrame;
rightView.frame = rightViewFinalFrame;
}
completion:^(BOOL finished) {
[self removeFromSuperview];
}];
}
@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