0

[ios] Use UIStackView to simplify web_view_shell layout code

By making |headerBackgroundView| and |headerContentView| UIStackView
instances, we can let UIStackView figure out a lot of the constraints on
its own and simplify the code significantly:

* |headerBackgroundView| is a 1-item UIStackView that just contains
  |headerContentView|. It inherits the root view's margins so that
  |headerContentView| is laid out respecting the safe area and the
  layout guide margins.

* |headerContentView| is a horizontal UIStackView containing the
  navigation buttons and the location bar. The items are vertically
  centralized and fill the UIStackView horizontally according to the
  content hugging settings (i.e. the location bar expands horizontally,
  the buttons do not).

By comparing screenshots of before and after with //tools/image_diff,
the only difference is a small change to the location bar in height, as
it no longer has a hardcoded size of 32 points.

Change-Id: I9f27dd1e4e60b59b2ac1844c0ae965dad17f9fc6
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6176975
Auto-Submit: Raphael Kubo da Costa <kubo@igalia.com>
Reviewed-by: John Wu <jzw@chromium.org>
Commit-Queue: John Wu <jzw@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1407650}
This commit is contained in:
Raphael Kubo da Costa
2025-01-16 16:43:01 -08:00
committed by Chromium LUCI CQ
parent 6f158a09d7
commit 7223a2c09f

@ -28,9 +28,9 @@ NSString* const kWebViewShellJavaScriptDialogTextFieldAccessibilityIdentifier =
UIScrollViewDelegate,
UITextFieldDelegate>
// Header containing navigation buttons and |field|.
@property(nonatomic, strong) UIView* headerBackgroundView;
@property(nonatomic, strong) UIStackView* headerBackgroundView;
// Header containing navigation buttons and |field|.
@property(nonatomic, strong) UIView* headerContentView;
@property(nonatomic, strong) UIStackView* headerContentView;
// Button to navigate backwards.
@property(nonatomic, strong) UIButton* backButton;
// Button to navigate forwards.
@ -103,8 +103,8 @@ NSString* const kWebViewShellJavaScriptDialogTextFieldAccessibilityIdentifier =
self.popupWebViews = [[NSMutableArray alloc] init];
// View creation.
self.headerBackgroundView = [[UIView alloc] init];
self.headerContentView = [[UIView alloc] init];
self.headerBackgroundView = [[UIStackView alloc] init];
self.headerContentView = [[UIStackView alloc] init];
self.contentView = [[UIView alloc] init];
self.backButton = [[UIButton alloc] init];
self.forwardButton = [[UIButton alloc] init];
@ -113,20 +113,36 @@ NSString* const kWebViewShellJavaScriptDialogTextFieldAccessibilityIdentifier =
self.field = [[UITextField alloc] init];
// View hierarchy.
// `_headerBackgroundView` is a 1-item UIStackView. We use a UIStackView so
// that we can:
// 1. Easily hide `_headerContentView` when entering fullscreen mode in a way
// that removes it from the layout.
// 2. Let UIStackView figure out most constraints for `_headerContentView` so
// that we do not have to do it manually.
[self.view addSubview:_headerBackgroundView];
[self.view addSubview:_contentView];
[_headerBackgroundView addSubview:_headerContentView];
[_headerContentView addSubview:_backButton];
[_headerContentView addSubview:_forwardButton];
[_headerContentView addSubview:_reloadOrStopButton];
[_headerContentView addSubview:_menuButton];
[_headerContentView addSubview:_field];
[_headerBackgroundView addArrangedSubview:_headerContentView];
[_headerContentView addArrangedSubview:_backButton];
[_headerContentView addArrangedSubview:_forwardButton];
[_headerContentView addArrangedSubview:_reloadOrStopButton];
[_headerContentView addArrangedSubview:_menuButton];
[_headerContentView addArrangedSubview:_field];
// Additional view setup.
_headerBackgroundView.backgroundColor = [UIColor colorWithRed:66.0 / 255.0
green:133.0 / 255.0
blue:244.0 / 255.0
alpha:1.0];
_headerBackgroundView.alignment = UIStackViewAlignmentBottom;
_headerBackgroundView.axis = UILayoutConstraintAxisHorizontal;
// Use the root view's layout margins (which account for safe areas and the
// system's minimum margins).
_headerBackgroundView.layoutMarginsRelativeArrangement = YES;
_headerBackgroundView.preservesSuperviewLayoutMargins = YES;
_headerContentView.alignment = UIStackViewAlignmentCenter;
_headerContentView.axis = UILayoutConstraintAxisHorizontal;
_headerContentView.spacing = 16.0;
[_backButton setImage:[UIImage imageNamed:@"ic_back"]
forState:UIControlStateNormal];
@ -184,21 +200,10 @@ NSString* const kWebViewShellJavaScriptDialogTextFieldAccessibilityIdentifier =
constraintEqualToAnchor:self.view.leadingAnchor],
[_headerBackgroundView.trailingAnchor
constraintEqualToAnchor:self.view.trailingAnchor],
[_headerBackgroundView.bottomAnchor
constraintEqualToAnchor:_headerContentView.bottomAnchor],
]];
_headerContentView.translatesAutoresizingMaskIntoConstraints = NO;
[NSLayoutConstraint activateConstraints:@[
[_headerContentView.topAnchor
constraintEqualToAnchor:_headerBackgroundView.safeAreaLayoutGuide
.topAnchor],
[_headerContentView.leadingAnchor
constraintEqualToAnchor:_headerBackgroundView.safeAreaLayoutGuide
.leadingAnchor],
[_headerContentView.trailingAnchor
constraintEqualToAnchor:_headerBackgroundView.safeAreaLayoutGuide
.trailingAnchor],
[_headerContentView.heightAnchor constraintEqualToConstant:56.0],
]];
@ -213,55 +218,6 @@ NSString* const kWebViewShellJavaScriptDialogTextFieldAccessibilityIdentifier =
[_contentView.bottomAnchor constraintEqualToAnchor:self.view.bottomAnchor],
]];
_backButton.translatesAutoresizingMaskIntoConstraints = NO;
[NSLayoutConstraint activateConstraints:@[
[_backButton.leadingAnchor
constraintEqualToAnchor:_headerContentView.safeAreaLayoutGuide
.leadingAnchor
constant:16.0],
[_backButton.centerYAnchor
constraintEqualToAnchor:_headerContentView.centerYAnchor],
]];
_forwardButton.translatesAutoresizingMaskIntoConstraints = NO;
[NSLayoutConstraint activateConstraints:@[
[_forwardButton.leadingAnchor
constraintEqualToAnchor:_backButton.trailingAnchor
constant:16.0],
[_forwardButton.centerYAnchor
constraintEqualToAnchor:_headerContentView.centerYAnchor],
]];
_reloadOrStopButton.translatesAutoresizingMaskIntoConstraints = NO;
[NSLayoutConstraint activateConstraints:@[
[_reloadOrStopButton.leadingAnchor
constraintEqualToAnchor:_forwardButton.trailingAnchor
constant:16.0],
[_reloadOrStopButton.centerYAnchor
constraintEqualToAnchor:_headerContentView.centerYAnchor],
]];
_menuButton.translatesAutoresizingMaskIntoConstraints = NO;
[NSLayoutConstraint activateConstraints:@[
[_menuButton.leadingAnchor
constraintEqualToAnchor:_reloadOrStopButton.trailingAnchor
constant:16.0],
[_menuButton.centerYAnchor
constraintEqualToAnchor:_headerContentView.centerYAnchor],
]];
_field.translatesAutoresizingMaskIntoConstraints = NO;
[NSLayoutConstraint activateConstraints:@[
[_field.leadingAnchor constraintEqualToAnchor:_menuButton.trailingAnchor
constant:16.0],
[_field.centerYAnchor
constraintEqualToAnchor:_headerContentView.centerYAnchor],
[_field.trailingAnchor
constraintEqualToAnchor:_headerContentView.safeAreaLayoutGuide
.trailingAnchor
constant:-16.0],
[_field.heightAnchor constraintEqualToConstant:32.0],
]];
[CWVWebView setUserAgentProduct:@"Dummy/1.0"];
CWVWebView.chromeContextMenuEnabled = YES;