blob: 399b4e37098bbfd4a38a757ade2f722d6580176f [file] [log] [blame]
// Copyright 2012 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/ntp/centering_scrollview.h"
#include "base/logging.h"
#include "ios/chrome/browser/ui/ui_util.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
namespace {
// Thickness of scrollbar images inserted by UIScrollView (circa iOS 5.0).
const CGFloat kScrollBarThickness = 7.0;
} // namespace
@interface CenteringScrollView ()
// Returns the one and only subview. There may be other subviews
// (e.g. UIImageView for the scrollbars) created by UIScrollView.
- (UIView*)findContentView;
@end
@implementation CenteringScrollView
- (void)layoutSubviews {
[super layoutSubviews];
// Find the movable content view inside this scroll view.
UIView* contentView = [self findContentView];
// UIScrollView does not send |layoutSubviews| message to its subviews.
// Since layoutSubviews may change the frame of |contentView|, this must be
// called before the centering computation below.
[contentView layoutSubviews];
// Place content view in the center of frame.
CGRect frame = self.frame;
CGRect contentRect = contentView.frame;
contentRect.origin = AlignPointToPixel(CGPointMake(
std::max((frame.size.width - contentRect.size.width) / 2.0, 0.0),
std::max((frame.size.height - contentRect.size.height) / 2.0, 0.0)));
contentView.frame = contentRect;
if (contentRect.size.width > frame.size.width ||
contentRect.size.height > frame.size.height) {
// If size of content view is larger than frame size, adjust content size
// so it becomes scrollable.
self.contentSize =
CGSizeMake(std::max(contentRect.size.width, frame.size.width),
std::max(contentRect.size.height, frame.size.height));
} else {
// Reset the content size as the view need not be scollable.
self.contentSize = CGSizeMake(0.0, 0.0);
}
}
#pragma mark -
#pragma mark Private
- (UIView*)findContentView {
UIView* soloView = nil;
NSUInteger viewCount = 0;
for (UIView* view in [self subviews]) {
// Ignore any UIImageView that has a smaller dimension less than the
// thickness of a scroll bar. This detection heuristics is based on the
// scrollbar sizing of iOS UIScrollView circa iOS 5.0. If this changes,
// the DCHECK following this for-loop will likely fail.
CGFloat thickness = std::min(view.frame.size.width, view.frame.size.height);
if ([view isKindOfClass:[UIImageView class]] &&
thickness <= kScrollBarThickness)
continue;
soloView = view;
++viewCount;
}
DCHECK(viewCount == 1);
return soloView;
}
@end