Commit 7dbefa69 authored by Kurt Horimoto's avatar Kurt Horimoto Committed by Commit Bot

[iOS] Move content below header after rotation when scrolled to top.

When the expanded toolbar height is updated while the page is scrolled
to the top, the top of the page will be obscured behind the toolbar.
Toolbar heights only change during trait collection updates, so the
page can be re-scrolled to the top after the trait collection is
finished updating if it was detected that it was scrolled to the top
when the update began.

Bug: 1017146
Change-Id: I1065cae2c1824e61a8688b845b88211013fa1949
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1914968
Auto-Submit: Kurt Horimoto <kkhorimoto@chromium.org>
Reviewed-by: default avatarChris Lu <thegreenfrog@chromium.org>
Commit-Queue: Kurt Horimoto <kkhorimoto@chromium.org>
Cr-Commit-Position: refs/heads/master@{#715347}
parent 88711d84
...@@ -90,11 +90,11 @@ void FullscreenControllerImpl::DecrementDisabledCounter() { ...@@ -90,11 +90,11 @@ void FullscreenControllerImpl::DecrementDisabledCounter() {
} }
void FullscreenControllerImpl::BrowserTraitCollectionChangedBegin() { void FullscreenControllerImpl::BrowserTraitCollectionChangedBegin() {
mediator_.StopFrameChangeCompensation(); mediator_.SetIsBrowserTraitCollectionUpdating(true);
} }
void FullscreenControllerImpl::BrowserTraitCollectionChangedEnd() { void FullscreenControllerImpl::BrowserTraitCollectionChangedEnd() {
mediator_.StartFrameChangeCompensation(); mediator_.SetIsBrowserTraitCollectionUpdating(false);
} }
CGFloat FullscreenControllerImpl::GetProgress() const { CGFloat FullscreenControllerImpl::GetProgress() const {
......
...@@ -43,14 +43,16 @@ class FullscreenMediator : public FullscreenModelObserver { ...@@ -43,14 +43,16 @@ class FullscreenMediator : public FullscreenModelObserver {
// Sets the WebState which view is to be resized. // Sets the WebState which view is to be resized.
void SetWebState(web::WebState* webState); void SetWebState(web::WebState* webState);
// Sets whether the browser view is currently handling a trait collection
// update. UI changes received through the broadcaster must be handled
// differently when received for trait collection updates as opposed to normal
// rendering and scrolling events.
void SetIsBrowserTraitCollectionUpdating(bool updating);
// Enters or exits fullscreen, animating the changes. // Enters or exits fullscreen, animating the changes.
void EnterFullscreen(); void EnterFullscreen();
void ExitFullscreen(); void ExitFullscreen();
// Activate or deactivate the offset compensation for the frame changes.
void StopFrameChangeCompensation();
void StartFrameChangeCompensation();
// Instructs the mediator to stop observing its model. // Instructs the mediator to stop observing its model.
void Disconnect(); void Disconnect();
...@@ -78,13 +80,17 @@ class FullscreenMediator : public FullscreenModelObserver { ...@@ -78,13 +80,17 @@ class FullscreenMediator : public FullscreenModelObserver {
FullscreenModel* model_ = nullptr; FullscreenModel* model_ = nullptr;
// The active animator. // The active animator.
__strong FullscreenAnimator* animator_ = nil; __strong FullscreenAnimator* animator_ = nil;
// The FullscreenControllerObservers that need to get notified of model
// changes.
base::ObserverList<FullscreenControllerObserver>::Unchecked observers_;
// Fullscreen resizer, used to resize the WebView based on the fullscreen // Fullscreen resizer, used to resize the WebView based on the fullscreen
// progress. // progress.
FullscreenWebViewResizer* resizer_ = nil; FullscreenWebViewResizer* resizer_ = nil;
// Whether the browser's trait collection is being updated.
bool updating_browser_trait_collection_ = false;
// Whether the content view was scrolled to the top when the browser trait
// collection began updating.
bool scrolled_to_top_during_trait_collection_updates_ = false;
// The FullscreenControllerObservers that need to get notified of model
// changes.
base::ObserverList<FullscreenControllerObserver>::Unchecked observers_;
DISALLOW_COPY_AND_ASSIGN(FullscreenMediator); DISALLOW_COPY_AND_ASSIGN(FullscreenMediator);
}; };
......
...@@ -7,10 +7,12 @@ ...@@ -7,10 +7,12 @@
#include "base/logging.h" #include "base/logging.h"
#include "base/memory/ptr_util.h" #include "base/memory/ptr_util.h"
#import "ios/chrome/browser/ui/fullscreen/fullscreen_animator.h" #import "ios/chrome/browser/ui/fullscreen/fullscreen_animator.h"
#import "ios/chrome/browser/ui/fullscreen/fullscreen_content_adjustment_util.h"
#import "ios/chrome/browser/ui/fullscreen/fullscreen_controller_observer.h" #import "ios/chrome/browser/ui/fullscreen/fullscreen_controller_observer.h"
#import "ios/chrome/browser/ui/fullscreen/fullscreen_model.h" #import "ios/chrome/browser/ui/fullscreen/fullscreen_model.h"
#import "ios/chrome/browser/ui/fullscreen/fullscreen_web_view_resizer.h" #import "ios/chrome/browser/ui/fullscreen/fullscreen_web_view_resizer.h"
#include "ios/chrome/browser/ui/util/ui_util.h" #include "ios/chrome/browser/ui/util/ui_util.h"
#import "ios/web/public/web_state.h"
#if !defined(__has_feature) || !__has_feature(objc_arc) #if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support." #error "This file requires ARC support."
...@@ -36,6 +38,29 @@ void FullscreenMediator::SetWebState(web::WebState* webState) { ...@@ -36,6 +38,29 @@ void FullscreenMediator::SetWebState(web::WebState* webState) {
resizer_.webState = webState; resizer_.webState = webState;
} }
void FullscreenMediator::SetIsBrowserTraitCollectionUpdating(bool updating) {
if (updating_browser_trait_collection_ == updating)
return;
updating_browser_trait_collection_ = updating;
if (updating_browser_trait_collection_) {
resizer_.compensateFrameChangeByOffset = NO;
scrolled_to_top_during_trait_collection_updates_ =
model_->is_scrolled_to_top();
} else {
resizer_.compensateFrameChangeByOffset = YES;
if (scrolled_to_top_during_trait_collection_updates_) {
// If the content was scrolled to the top when the trait collection began
// updating, changes in toolbar heights may cause the top of the page to
// become hidden. Ensure that the page remains scrolled to the top after
// the trait collection finishes updating.
web::WebState* web_state = resizer_.webState;
if (web_state)
MoveContentBelowHeader(web_state->GetWebViewProxy(), model_);
scrolled_to_top_during_trait_collection_updates_ = false;
}
}
}
void FullscreenMediator::EnterFullscreen() { void FullscreenMediator::EnterFullscreen() {
if (model_->enabled()) if (model_->enabled())
AnimateWithStyle(FullscreenAnimatorStyle::ENTER_FULLSCREEN); AnimateWithStyle(FullscreenAnimatorStyle::ENTER_FULLSCREEN);
...@@ -50,14 +75,6 @@ void FullscreenMediator::ExitFullscreen() { ...@@ -50,14 +75,6 @@ void FullscreenMediator::ExitFullscreen() {
AnimateWithStyle(FullscreenAnimatorStyle::EXIT_FULLSCREEN); AnimateWithStyle(FullscreenAnimatorStyle::EXIT_FULLSCREEN);
} }
void FullscreenMediator::StopFrameChangeCompensation() {
resizer_.compensateFrameChangeByOffset = NO;
}
void FullscreenMediator::StartFrameChangeCompensation() {
resizer_.compensateFrameChangeByOffset = YES;
}
void FullscreenMediator::Disconnect() { void FullscreenMediator::Disconnect() {
for (auto& observer : observers_) { for (auto& observer : observers_) {
observer.FullscreenControllerWillShutDown(controller_); observer.FullscreenControllerWillShutDown(controller_);
......
...@@ -55,6 +55,11 @@ class FullscreenModel : public ChromeBroadcastObserverInterface { ...@@ -55,6 +55,11 @@ class FullscreenModel : public ChromeBroadcastObserverInterface {
return content_height_ > scroll_view_height_ + toolbar_height_delta(); return content_height_ > scroll_view_height_ + toolbar_height_delta();
} }
// Whether the view is scrolled all the way to the top.
bool is_scrolled_to_top() const {
return y_content_offset_ <= -expanded_toolbar_height_;
}
// Whether the view is scrolled all the way to the bottom. // Whether the view is scrolled all the way to the bottom.
bool is_scrolled_to_bottom() const { bool is_scrolled_to_bottom() const {
return y_content_offset_ + scroll_view_height_ >= content_height_; return y_content_offset_ + scroll_view_height_ >= content_height_;
......
...@@ -293,3 +293,24 @@ TEST_F(FullscreenModelTest, IgnoreContentHeightChangesWhileScrolling) { ...@@ -293,3 +293,24 @@ TEST_F(FullscreenModelTest, IgnoreContentHeightChangesWhileScrolling) {
model().SetScrollViewIsDragging(true); model().SetScrollViewIsDragging(true);
EXPECT_FALSE(model().enabled()); EXPECT_FALSE(model().enabled());
} }
// Tests that the model detects when the page is scrolled to the top and bottom.
TEST_F(FullscreenModelTest, ScrolledToTopAndBottom) {
// Scroll to the top of the page and verify that only is_scrolled_to_top()
// returns true.
model().SetYContentOffset(-kToolbarHeight);
EXPECT_TRUE(model().is_scrolled_to_top());
EXPECT_FALSE(model().is_scrolled_to_bottom());
// Scroll to the middle of the page and verify that neither
// is_scrolled_to_top() nor is_scrolled_to_bottom() returns true.
model().SetYContentOffset(kContentHeight / 2.0);
EXPECT_FALSE(model().is_scrolled_to_top());
EXPECT_FALSE(model().is_scrolled_to_bottom());
// Scroll to the bottom of the page and verify that only
// is_scrolled_to_bottom() returns true.
model().SetYContentOffset(kContentHeight - kScrollViewHeight);
EXPECT_FALSE(model().is_scrolled_to_top());
EXPECT_TRUE(model().is_scrolled_to_bottom());
}
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