Commit 628cb5c4 authored by Jérôme Lebel's avatar Jérôme Lebel Committed by Commit Bot

[iOS] Update UI constraints for UserSigninViewController

Adding consent insets for buttons.
Adding max constraints for the user consent view (600x600px).
Centering the user consent on iPad.
Changing the button size between iPad and iPhone.
Attaching the gradient view to the bottom of user consent view.

Screenshots:
https://drive.google.com/open?id=17Eh7k968on1pifk0nJSRCArmgs9Csb98
(blue and yellow colors are just for debug reasons).

Bug: 971989
Change-Id: I3c767d717538a1d5de53eb66f33cf20db4336261
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2139723
Commit-Queue: Jérôme Lebel <jlebel@chromium.org>
Reviewed-by: default avatarNohemi Fernandez <fernandex@chromium.org>
Cr-Commit-Position: refs/heads/master@{#757786}
parent 247b96bf
......@@ -22,32 +22,40 @@
namespace {
// Button corner radius.
const CGFloat kButtonCornerRadius = 8;
// Inset between button contents and edge.
const CGFloat kButtonTitleContentInset = 8.0;
// Gradient height.
const CGFloat kGradientHeight = 40.;
// Max size for the user consent view.
const CGFloat kUserConsentMaxSize = 600.;
// Layout constants for buttons.
struct AuthenticationViewConstants {
CGFloat GradientHeight;
CGFloat PrimaryFontSize;
CGFloat SecondaryFontSize;
CGFloat ButtonHeight;
CGFloat ButtonHorizontalPadding;
CGFloat ButtonTopPadding;
CGFloat ButtonBottomPadding;
CGFloat ButtonVerticalPadding;
CGFloat ButtonTitleContentHorizontalInset;
CGFloat ButtonTitleContentVerticalInset;
};
const AuthenticationViewConstants kCompactConstants = {
40, // GradientHeight
24, // PrimaryFontSize
14, // SecondaryFontSize
36, // ButtonHeight
16, // ButtonHorizontalPadding
16, // ButtonTopPadding
16, // ButtonBottomPadding
16, // ButtonVerticalPadding
16, // ButtonTitleContentHorizontalInset
8, // ButtonTitleContentVerticalInset
};
const AuthenticationViewConstants kRegularConstants = {
kCompactConstants.GradientHeight,
1.5 * kCompactConstants.PrimaryFontSize,
1.5 * kCompactConstants.SecondaryFontSize,
1.5 * kCompactConstants.ButtonHeight,
32, // ButtonHorizontalPadding
32, // ButtonTopPadding
32, // ButtonBottomPadding
32, // ButtonVerticalPadding
16, // ButtonTitleContentInset
16, // ButtonTitleContentInset
};
// The style applied to a button type.
......@@ -60,6 +68,9 @@ enum AuthenticationButtonType {
@interface UserSigninViewController ()
// Container view used to center vertically the user consent view between the
// top of the controller view and the top of the button view.
@property(nonatomic, strong) UIView* containerView;
// Activity indicator used to block the UI when a sign-in operation is in
// progress.
@property(nonatomic, strong) MDCActivityIndicator* activityIndicator;
......@@ -73,12 +84,22 @@ enum AuthenticationButtonType {
@property(nonatomic, assign) BOOL hasUnifiedConsentScreenReachedBottom;
// Gradient used to hide text that is close to the bottom of the screen. This
// gives users the hint that there is more to scroll through.
@property(nonatomic, strong) GradientView* gradientView;
@property(nonatomic, strong, readonly) GradientView* gradientView;
// Lists of constraints that need to be activated when the view is in
// compact size class.
@property(nonatomic, strong, readonly) NSArray* compactSizeClassConstraints;
// Lists of constraints that need to be activated when the view is in
// regular size class.
@property(nonatomic, strong, readonly) NSArray* regularSizeClassConstraints;
@end
@implementation UserSigninViewController
@synthesize gradientView = _gradientView;
@synthesize compactSizeClassConstraints = _compactSizeClassConstraints;
@synthesize regularSizeClassConstraints = _regularSizeClassConstraints;
#pragma mark - Public
- (void)markUnifiedConsentScreenReachedBottom {
......@@ -138,52 +159,86 @@ enum AuthenticationButtonType {
self.view.backgroundColor = self.systemBackgroundColor;
[self addConfirmationButton];
[self embedUserConsentView];
[self addSkipSigninButton];
[self embedUserConsentView];
[self.view addSubview:self.gradientView];
// The layout constraints should be added at the end once all of the views
// have been created.
AuthenticationViewConstants constants = self.authenticationViewConstants;
// Embedded view constraints.
AddSameConstraintsWithInsets(
self.unifiedConsentViewController.view, self.view.safeAreaLayoutGuide,
ChromeDirectionalEdgeInsetsMake(0, 0,
constants.ButtonHeight +
constants.ButtonBottomPadding +
constants.ButtonTopPadding,
0));
// Skip sign-in button constraints.
AddSameConstraintsToSidesWithInsets(
self.skipSigninButton, self.view.safeAreaLayoutGuide,
LayoutSides::kBottom | LayoutSides::kLeading,
ChromeDirectionalEdgeInsetsMake(0, constants.ButtonHorizontalPadding,
constants.ButtonBottomPadding, 0));
// Confirmation button constraints.
AddSameConstraintsToSidesWithInsets(
self.confirmationButton, self.view.safeAreaLayoutGuide,
LayoutSides::kBottom | LayoutSides::kTrailing,
ChromeDirectionalEdgeInsetsMake(0, 0, constants.ButtonBottomPadding,
constants.ButtonHorizontalPadding));
// Gradient layer constraints.
[NSLayoutConstraint activateConstraints:@[
// Contraints for the container view. The bottom constraint has to be set
// according to the size class.
[self.containerView.topAnchor constraintEqualToAnchor:self.view.topAnchor],
[self.containerView.leadingAnchor
constraintEqualToAnchor:self.view.leadingAnchor],
[self.containerView.trailingAnchor
constraintEqualToAnchor:self.view.trailingAnchor],
]];
[self.containerView addSubview:self.gradientView];
self.gradientView.translatesAutoresizingMaskIntoConstraints = NO;
[NSLayoutConstraint activateConstraints:@[
// The gradient view needs to be attatched to the bottom of the user
// consent view which contains the scroll view.
[self.gradientView.bottomAnchor
constraintEqualToAnchor:self.unifiedConsentViewController.view
.bottomAnchor],
[self.gradientView.leadingAnchor
constraintEqualToAnchor:self.view.leadingAnchor],
constraintEqualToAnchor:self.unifiedConsentViewController.view
.leadingAnchor],
[self.gradientView.trailingAnchor
constraintEqualToAnchor:self.view.trailingAnchor],
constraintEqualToAnchor:self.unifiedConsentViewController.view
.trailingAnchor],
[self.gradientView.heightAnchor constraintEqualToConstant:kGradientHeight],
]];
[self updateViewsAndConstraints];
}
- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
[self updateViewsAndConstraints];
}
[self.gradientView.heightAnchor
constraintEqualToConstant:constants.GradientHeight],
#pragma mark - Constraints
// Generate default constraints based on the constants.
- (NSMutableArray*)generateConstraintsWithConstants:
(AuthenticationViewConstants)constants {
NSMutableArray* constraints = [NSMutableArray array];
// Confirmation button constraints
[constraints addObjectsFromArray:@[
[self.view.safeAreaLayoutGuide.trailingAnchor
constraintEqualToAnchor:self.confirmationButton.trailingAnchor
constant:constants.ButtonHorizontalPadding],
[self.view.safeAreaLayoutGuide.bottomAnchor
constraintEqualToAnchor:self.confirmationButton.bottomAnchor
constant:constants.ButtonVerticalPadding],
]];
// Skip button constraints
[constraints addObjectsFromArray:@[
[self.skipSigninButton.leadingAnchor
constraintEqualToAnchor:self.view.safeAreaLayoutGuide.leadingAnchor
constant:constants.ButtonHorizontalPadding],
[self.view.safeAreaLayoutGuide.bottomAnchor
constraintEqualToAnchor:self.skipSigninButton.bottomAnchor
constant:constants.ButtonVerticalPadding],
]];
return constraints;
}
// Updates view sizes and constraints.
- (void)updateViewsAndConstraints {
BOOL isRegularSizeClass = IsRegularXRegularSizeClass(self.traitCollection);
UIFontTextStyle fontStyle;
if (isRegularSizeClass) {
[NSLayoutConstraint deactivateConstraints:self.compactSizeClassConstraints];
[NSLayoutConstraint activateConstraints:self.regularSizeClassConstraints];
fontStyle = UIFontTextStyleTitle2;
} else {
[NSLayoutConstraint deactivateConstraints:self.regularSizeClassConstraints];
[NSLayoutConstraint activateConstraints:self.compactSizeClassConstraints];
fontStyle = UIFontTextStyleSubheadline;
}
[self applyDefaultSizeWithButton:self.confirmationButton fontStyle:fontStyle];
[self applyDefaultSizeWithButton:self.skipSigninButton fontStyle:fontStyle];
}
#pragma mark - Properties
......@@ -221,9 +276,6 @@ enum AuthenticationButtonType {
return isRegularSizeClass ? kRegularConstants : kCompactConstants;
}
// Sets up gradient that masks text when the iOS device size is a compact size.
// This is to hint to the user that there is additional text below the end of
// the screen.
- (UIView*)gradientView {
if (!_gradientView) {
_gradientView = [[GradientView alloc] init];
......@@ -231,6 +283,79 @@ enum AuthenticationButtonType {
return _gradientView;
}
- (NSArray*)compactSizeClassConstraints {
if (!_compactSizeClassConstraints) {
NSMutableArray* constraints =
[self generateConstraintsWithConstants:kCompactConstants];
[constraints addObjectsFromArray:@[
// Constraints for the user consent view inside the container view.
[self.unifiedConsentViewController.view.topAnchor
constraintEqualToAnchor:self.containerView.topAnchor],
[self.unifiedConsentViewController.view.bottomAnchor
constraintEqualToAnchor:self.containerView.bottomAnchor],
[self.unifiedConsentViewController.view.leadingAnchor
constraintEqualToAnchor:self.containerView.leadingAnchor],
[self.unifiedConsentViewController.view.trailingAnchor
constraintEqualToAnchor:self.containerView.trailingAnchor],
// Constraint between the container view and the confirmation button.
[self.confirmationButton.topAnchor
constraintEqualToAnchor:self.containerView.bottomAnchor
constant:kCompactConstants.ButtonVerticalPadding],
]];
_compactSizeClassConstraints = constraints;
}
return _compactSizeClassConstraints;
}
- (NSArray*)regularSizeClassConstraints {
if (!_regularSizeClassConstraints) {
NSMutableArray* constraints =
[self generateConstraintsWithConstants:kRegularConstants];
[constraints addObjectsFromArray:@[
// Constraints for the user consent view inside the container view, to
// make sure it is never bigger than the container view.
[self.unifiedConsentViewController.view.topAnchor
constraintGreaterThanOrEqualToAnchor:self.containerView.topAnchor],
[self.unifiedConsentViewController.view.bottomAnchor
constraintLessThanOrEqualToAnchor:self.containerView.bottomAnchor],
[self.unifiedConsentViewController.view.leadingAnchor
constraintGreaterThanOrEqualToAnchor:self.containerView
.leadingAnchor],
[self.unifiedConsentViewController.view.trailingAnchor
constraintLessThanOrEqualToAnchor:self.containerView.trailingAnchor],
// The user consent view needs to be centered if the container view is
// bigger than the max size authorized for the user consent view.
[self.unifiedConsentViewController.view.centerXAnchor
constraintEqualToAnchor:self.containerView.centerXAnchor],
[self.unifiedConsentViewController.view.centerYAnchor
constraintEqualToAnchor:self.containerView.centerYAnchor],
// Constraint between the container view and the confirmation button.
[self.confirmationButton.topAnchor
constraintEqualToAnchor:self.containerView.bottomAnchor
constant:kRegularConstants.ButtonVerticalPadding],
]];
// Adding constraints to ensure the user consent view has a limited size
// on iPad. If the screen is bigger than the max size, those constraints
// limit the user consent view.
// If the screen is smaller than the max size, those constraints are ignored
// since they have a lower priority than the constraints set aboved.
NSArray* lowerPriorityConstraints = @[
[self.unifiedConsentViewController.view.heightAnchor
constraintEqualToConstant:kUserConsentMaxSize],
[self.unifiedConsentViewController.view.widthAnchor
constraintEqualToConstant:kUserConsentMaxSize],
];
for (NSLayoutConstraint* constraints in lowerPriorityConstraints) {
// We do not use |UILayoutPriorityDefaultHigh| because it makes some
// multiline labels on one line and truncated on iPad.
constraints.priority = UILayoutPriorityRequired - 1;
}
[constraints addObjectsFromArray:lowerPriorityConstraints];
_regularSizeClassConstraints = constraints;
}
return _regularSizeClassConstraints;
}
#pragma mark - Subviews
// Sets up activity indicator properties and adds it to the user sign-in view.
......@@ -254,9 +379,11 @@ enum AuthenticationButtonType {
self.unifiedConsentViewController.view
.translatesAutoresizingMaskIntoConstraints = NO;
self.containerView = [[UIView alloc] init];
self.containerView.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addSubview:self.containerView];
[self addChildViewController:self.unifiedConsentViewController];
[self.view insertSubview:self.unifiedConsentViewController.view
belowSubview:self.confirmationButton];
[self.containerView addSubview:self.unifiedConsentViewController.view];
[self.unifiedConsentViewController didMoveToParentViewController:self];
}
......@@ -269,9 +396,6 @@ enum AuthenticationButtonType {
[self addSubviewWithButton:self.confirmationButton];
// Note that the button style will depend on the user sign-in state.
[self updatePrimaryButtonStyle];
self.confirmationButton.contentEdgeInsets =
UIEdgeInsetsMake(kButtonTitleContentInset, kButtonTitleContentInset,
kButtonTitleContentInset, kButtonTitleContentInset);
}
// Sets up skip sign-in button properties and adds it to the user sign-in view.
......@@ -286,15 +410,15 @@ enum AuthenticationButtonType {
[self.skipSigninButton addTarget:self
action:@selector(onSkipSigninButtonPressed:)
forControlEvents:UIControlEventTouchUpInside];
self.skipSigninButton.contentEdgeInsets =
UIEdgeInsetsMake(kButtonTitleContentInset, kButtonTitleContentInset,
kButtonTitleContentInset, kButtonTitleContentInset);
}
// Sets up button properties and adds it to view.
- (void)addSubviewWithButton:(UIButton*)button {
button.titleLabel.font =
[UIFont preferredFontForTextStyle:UIFontTextStyleSubheadline];
[button
setContentCompressionResistancePriority:UILayoutPriorityRequired
forAxis:UILayoutConstraintAxisVertical];
[button setContentHuggingPriority:UILayoutPriorityRequired
forAxis:UILayoutConstraintAxisVertical];
[self.view addSubview:button];
button.translatesAutoresizingMaskIntoConstraints = NO;
}
......@@ -325,6 +449,19 @@ enum AuthenticationButtonType {
[self setSkipSigninStylingWithButton:button];
}
// Applies font and inset to |button| according to the current size class.
- (void)applyDefaultSizeWithButton:(UIButton*)button
fontStyle:(UIFontTextStyle)fontStyle {
const AuthenticationViewConstants& constants =
self.authenticationViewConstants;
CGFloat horizontalContentInset = constants.ButtonTitleContentHorizontalInset;
CGFloat verticalContentInset = constants.ButtonTitleContentVerticalInset;
button.contentEdgeInsets =
UIEdgeInsetsMake(verticalContentInset, horizontalContentInset,
verticalContentInset, horizontalContentInset);
button.titleLabel.font = [UIFont preferredFontForTextStyle:fontStyle];
}
#pragma mark - Events
- (void)onSkipSigninButtonPressed:(id)sender {
......
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