Commit 38ea2d27 authored by Gauthier Ambard's avatar Gauthier Ambard Committed by Commit Bot

[iOS] Make the TableView's empty view scrollable

This CL adds a scroll view containing the text displayed when the table
view is empty. It allows the user to scroll the text if the font size
used is big.
As the safe area insets aren't propagated to the empty view, this is
using dummy view to fake the safe area insets in the scroll view.

Bug: 893535
Change-Id: I63b658c1bc9d5cacdb4e86d201a2bb2ca7621a96
Reviewed-on: https://chromium-review.googlesource.com/c/1353941
Commit-Queue: Gauthier Ambard <gambard@chromium.org>
Reviewed-by: default avatarKurt Horimoto <kkhorimoto@chromium.org>
Reviewed-by: default avatarSergio Collazos <sczs@chromium.org>
Cr-Commit-Position: refs/heads/master@{#613087}
parent 1fdfec86
...@@ -62,6 +62,7 @@ ...@@ -62,6 +62,7 @@
if (_emptyView == emptyView) if (_emptyView == emptyView)
return; return;
_emptyView = emptyView; _emptyView = emptyView;
_emptyView.scrollViewContentInsets = self.view.safeAreaInsets;
self.tableView.backgroundView = _emptyView; self.tableView.backgroundView = _emptyView;
// Since this would replace any loadingView, set it to nil. // Since this would replace any loadingView, set it to nil.
self.loadingView = nil; self.loadingView = nil;
...@@ -73,6 +74,13 @@ ...@@ -73,6 +74,13 @@
_tableViewModel = [[TableViewModel alloc] init]; _tableViewModel = [[TableViewModel alloc] init];
} }
- (void)viewSafeAreaInsetsDidChange {
[super viewSafeAreaInsetsDidChange];
// The safe area insets aren't propagated to the inner scroll view. Manually
// set the content insets.
self.emptyView.scrollViewContentInsets = self.view.safeAreaInsets;
}
- (void)viewDidLoad { - (void)viewDidLoad {
[super viewDidLoad]; [super viewDidLoad];
......
...@@ -28,6 +28,9 @@ ...@@ -28,6 +28,9 @@
// message iteself. // message iteself.
@property(nonatomic, strong) NSString* messageAccessibilityLabel; @property(nonatomic, strong) NSString* messageAccessibilityLabel;
// Insets of the inner ScrollView.
@property(nonatomic, assign) UIEdgeInsets scrollViewContentInsets;
// The empty view's accessibility identifier. // The empty view's accessibility identifier.
+ (NSString*)accessibilityIdentifier; + (NSString*)accessibilityIdentifier;
......
...@@ -36,12 +36,14 @@ NSAttributedString* GetAttributedMessage(NSString* message) { ...@@ -36,12 +36,14 @@ NSAttributedString* GetAttributedMessage(NSString* message) {
@property(nonatomic, strong) UILabel* messageLabel; @property(nonatomic, strong) UILabel* messageLabel;
// The image that will be displayed. // The image that will be displayed.
@property(nonatomic, strong) UIImage* image; @property(nonatomic, strong) UIImage* image;
// The inner ScrollView so the whole content can be seen even if it is taller
// than the TableView.
@property(nonatomic, strong) UIScrollView* scrollView;
// The height constraint of the ScrollView.
@property(nonatomic, strong) NSLayoutConstraint* scrollViewHeight;
@end @end
@implementation TableViewEmptyView @implementation TableViewEmptyView
@synthesize message = _message;
@synthesize messageLabel = _messageLabel;
@synthesize image = _image;
- (instancetype)initWithFrame:(CGRect)frame - (instancetype)initWithFrame:(CGRect)frame
message:(NSString*)message message:(NSString*)message
...@@ -83,13 +85,34 @@ NSAttributedString* GetAttributedMessage(NSString* message) { ...@@ -83,13 +85,34 @@ NSAttributedString* GetAttributedMessage(NSString* message) {
return @"TableViewEmptyView"; return @"TableViewEmptyView";
} }
- (void)setScrollViewContentInsets:(UIEdgeInsets)scrollViewContentInsets {
_scrollViewContentInsets = scrollViewContentInsets;
self.scrollView.contentInset = scrollViewContentInsets;
self.scrollViewHeight.constant =
scrollViewContentInsets.top + scrollViewContentInsets.bottom;
}
#pragma mark - UIView #pragma mark - UIView
- (void)willMoveToSuperview:(UIView*)newSuperview { - (void)willMoveToSuperview:(UIView*)newSuperview {
[super willMoveToSuperview:newSuperview];
[self createSubviews];
}
#pragma mark - Private
- (void)createSubviews {
// Return if the subviews have already been created and added. // Return if the subviews have already been created and added.
if (!(self.subviews.count == 0)) if (!(self.subviews.count == 0))
return; return;
// Scroll view used to scroll the content if it is too big.
UIScrollView* scrollView = [[UIScrollView alloc] init];
scrollView.translatesAutoresizingMaskIntoConstraints = NO;
scrollView.contentInset = self.scrollViewContentInsets;
self.scrollView = scrollView;
UIImageView* imageView = [[UIImageView alloc] initWithImage:self.image]; UIImageView* imageView = [[UIImageView alloc] initWithImage:self.image];
imageView.contentMode = UIViewContentModeScaleAspectFit; imageView.contentMode = UIViewContentModeScaleAspectFit;
imageView.clipsToBounds = YES; imageView.clipsToBounds = YES;
...@@ -106,13 +129,40 @@ NSAttributedString* GetAttributedMessage(NSString* message) { ...@@ -106,13 +129,40 @@ NSAttributedString* GetAttributedMessage(NSString* message) {
verticalStack.axis = UILayoutConstraintAxisVertical; verticalStack.axis = UILayoutConstraintAxisVertical;
verticalStack.spacing = kStackViewVerticalSpacing; verticalStack.spacing = kStackViewVerticalSpacing;
verticalStack.distribution = UIStackViewDistributionFill; verticalStack.distribution = UIStackViewDistributionFill;
verticalStack.layoutMarginsRelativeArrangement = YES;
verticalStack.layoutMargins = UIEdgeInsetsMake(kStackViewVerticalSpacing, 0,
kStackViewVerticalSpacing, 0);
verticalStack.translatesAutoresizingMaskIntoConstraints = NO; verticalStack.translatesAutoresizingMaskIntoConstraints = NO;
[self addSubview:verticalStack];
[scrollView addSubview:verticalStack];
[self addSubview:scrollView];
// The scroll view should contains the stack view without scrolling enabled if
// it is small enough.
NSLayoutConstraint* scrollViewHeightConstraint = [scrollView.heightAnchor
constraintEqualToAnchor:verticalStack.heightAnchor
constant:(self.scrollViewContentInsets.top +
self.scrollViewContentInsets.bottom)];
scrollViewHeightConstraint.priority = UILayoutPriorityDefaultLow;
scrollViewHeightConstraint.active = YES;
self.scrollViewHeight = scrollViewHeightConstraint;
[NSLayoutConstraint activateConstraints:@[ [NSLayoutConstraint activateConstraints:@[
[verticalStack.centerYAnchor constraintEqualToAnchor:self.centerYAnchor], // The vertical stack is horizontal centered.
[verticalStack.topAnchor constraintEqualToAnchor:scrollView.topAnchor],
[verticalStack.bottomAnchor
constraintEqualToAnchor:scrollView.bottomAnchor],
[verticalStack.centerXAnchor constraintEqualToAnchor:self.centerXAnchor], [verticalStack.centerXAnchor constraintEqualToAnchor:self.centerXAnchor],
[verticalStack.widthAnchor constraintEqualToConstant:kStackViewWidth] [verticalStack.widthAnchor constraintEqualToConstant:kStackViewWidth],
// Have the scroll view taking the full width of self and be vertically
// centered, which is useful when the label isn't taking the full height.
[scrollView.centerYAnchor constraintEqualToAnchor:self.centerYAnchor],
[scrollView.topAnchor constraintGreaterThanOrEqualToAnchor:self.topAnchor],
[scrollView.bottomAnchor
constraintLessThanOrEqualToAnchor:self.bottomAnchor],
[scrollView.leadingAnchor constraintEqualToAnchor:self.leadingAnchor],
[scrollView.trailingAnchor constraintEqualToAnchor:self.trailingAnchor],
]]; ]];
} }
......
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