This is an automated email from the ASF dual-hosted git repository. manuelbeck pushed a commit to branch pr-ios-use-auto-layout in repository https://gitbox.apache.org/repos/asf/cordova-plugin-inappbrowser.git
commit ab600b4f135dfb5241575ab964011db9c25d6ef8 Author: Manuel Beck <[email protected]> AuthorDate: Mon Dec 22 13:42:51 2025 +0100 iOS: Use auto layout to respect safe areas - Generated-by: XCode 26, GPT-5 --- src/ios/CDVWKInAppBrowser.m | 343 ++++++++++++++++++++------------------------ 1 file changed, 159 insertions(+), 184 deletions(-) diff --git a/src/ios/CDVWKInAppBrowser.m b/src/ios/CDVWKInAppBrowser.m index 716b883..cc08fab 100644 --- a/src/ios/CDVWKInAppBrowser.m +++ b/src/ios/CDVWKInAppBrowser.m @@ -667,8 +667,8 @@ BOOL isExiting = FALSE; CGRect webViewBounds = self.view.bounds; BOOL toolbarIsAtBottom = ![_browserOptions.toolbarposition isEqualToString:kInAppBrowserToolbarBarPositionTop]; webViewBounds.size.height -= _browserOptions.location ? FOOTER_HEIGHT : TOOLBAR_HEIGHT; + WKUserContentController* userContentController = [[WKUserContentController alloc] init]; - WKWebViewConfiguration* configuration = [[WKWebViewConfiguration alloc] init]; NSString *userAgent = configuration.applicationNameForUserAgent; @@ -706,7 +706,6 @@ BOOL isExiting = FALSE; } - self.webView = [[WKWebView alloc] initWithFrame:webViewBounds configuration:configuration]; #if __IPHONE_OS_VERSION_MAX_ALLOWED >= 160400 @@ -723,61 +722,16 @@ BOOL isExiting = FALSE; } #endif - [self.view addSubview:self.webView]; [self.view sendSubviewToBack:self.webView]; - - - self.webView.navigationDelegate = self; - self.webView.UIDelegate = self.webViewUIDelegate; - self.webView.backgroundColor = [UIColor whiteColor]; - if ([self settingForKey:@"OverrideUserAgent"] != nil) { - self.webView.customUserAgent = [self settingForKey:@"OverrideUserAgent"]; - } - - self.webView.clearsContextBeforeDrawing = YES; - self.webView.clipsToBounds = YES; - self.webView.contentMode = UIViewContentModeScaleToFill; - self.webView.multipleTouchEnabled = YES; - self.webView.opaque = YES; - self.webView.userInteractionEnabled = YES; - self.automaticallyAdjustsScrollViewInsets = YES ; - [self.webView setAutoresizingMask:UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth]; - self.webView.allowsLinkPreview = NO; - self.webView.allowsBackForwardNavigationGestures = NO; - - [self.webView.scrollView setContentInsetAdjustmentBehavior:UIScrollViewContentInsetAdjustmentNever]; - - self.spinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray]; - self.spinner.alpha = 1.000; - self.spinner.autoresizesSubviews = YES; - self.spinner.autoresizingMask = (UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleRightMargin); - self.spinner.clearsContextBeforeDrawing = NO; - self.spinner.clipsToBounds = NO; - self.spinner.contentMode = UIViewContentModeScaleToFill; - self.spinner.frame = CGRectMake(CGRectGetMidX(self.webView.frame), CGRectGetMidY(self.webView.frame), 20.0, 20.0); - self.spinner.hidden = NO; - self.spinner.hidesWhenStopped = YES; - self.spinner.multipleTouchEnabled = NO; - self.spinner.opaque = NO; - self.spinner.userInteractionEnabled = NO; - [self.spinner stopAnimating]; - - self.closeButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(close)]; - self.closeButton.enabled = YES; - - UIBarButtonItem* flexibleSpaceButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil]; - - UIBarButtonItem* fixedSpaceButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:nil action:nil]; - fixedSpaceButton.width = 20; - - float toolbarY = toolbarIsAtBottom ? self.view.bounds.size.height - TOOLBAR_HEIGHT : 0.0; - CGRect toolbarFrame = CGRectMake(0.0, toolbarY, self.view.bounds.size.width, TOOLBAR_HEIGHT); - - self.toolbar = [[UIToolbar alloc] initWithFrame:toolbarFrame]; + + // Disable autoresizing mask translation for Auto Layout + self.webView.translatesAutoresizingMaskIntoConstraints = NO; + + // Toolbar init without frame + self.toolbar = [[UIToolbar alloc] init]; self.toolbar.alpha = 1.000; self.toolbar.autoresizesSubviews = YES; - self.toolbar.autoresizingMask = toolbarIsAtBottom ? (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin) : UIViewAutoresizingFlexibleWidth; self.toolbar.barStyle = UIBarStyleBlackOpaque; self.toolbar.clearsContextBeforeDrawing = NO; self.toolbar.clipsToBounds = NO; @@ -792,15 +746,14 @@ BOOL isExiting = FALSE; if (!_browserOptions.toolbartranslucent) { // Set toolbar translucent to no if user sets it in options self.toolbar.translucent = NO; } - + [self.view addSubview:self.toolbar]; + self.toolbar.translatesAutoresizingMaskIntoConstraints = NO; + CGFloat labelInset = 5.0; - float locationBarY = toolbarIsAtBottom ? self.view.bounds.size.height - FOOTER_HEIGHT : self.view.bounds.size.height - LOCATIONBAR_HEIGHT; - - self.addressLabel = [[UILabel alloc] initWithFrame:CGRectMake(labelInset, locationBarY, self.view.bounds.size.width - labelInset, LOCATIONBAR_HEIGHT)]; + self.addressLabel = [[UILabel alloc] init]; self.addressLabel.adjustsFontSizeToFitWidth = NO; self.addressLabel.alpha = 1.000; self.addressLabel.autoresizesSubviews = YES; - self.addressLabel.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleTopMargin; self.addressLabel.backgroundColor = [UIColor clearColor]; self.addressLabel.baselineAdjustment = UIBaselineAdjustmentAlignCenters; self.addressLabel.clearsContextBeforeDrawing = YES; @@ -824,6 +777,33 @@ BOOL isExiting = FALSE; self.addressLabel.textAlignment = NSTextAlignmentLeft; self.addressLabel.textColor = [UIColor colorWithWhite:1.000 alpha:1.000]; self.addressLabel.userInteractionEnabled = NO; + [self.view addSubview:self.addressLabel]; + self.addressLabel.translatesAutoresizingMaskIntoConstraints = NO; + + self.spinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray]; + self.spinner.alpha = 1.000; + self.spinner.autoresizesSubviews = YES; + self.spinner.autoresizingMask = (UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleRightMargin); + self.spinner.clearsContextBeforeDrawing = NO; + self.spinner.clipsToBounds = NO; + self.spinner.contentMode = UIViewContentModeScaleToFill; + self.spinner.frame = CGRectMake(CGRectGetMidX(self.webView.frame), CGRectGetMidY(self.webView.frame), 20.0, 20.0); + self.spinner.hidden = NO; + self.spinner.hidesWhenStopped = YES; + self.spinner.multipleTouchEnabled = NO; + self.spinner.opaque = NO; + self.spinner.userInteractionEnabled = NO; + [self.spinner stopAnimating]; + [self.view addSubview:self.spinner]; + self.spinner.translatesAutoresizingMaskIntoConstraints = NO; + + self.closeButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(close)]; + self.closeButton.enabled = YES; + + UIBarButtonItem* flexibleSpaceButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil]; + + UIBarButtonItem* fixedSpaceButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:nil action:nil]; + fixedSpaceButton.width = 20; NSString* frontArrowString = NSLocalizedString(@"►", nil); // create arrow from Unicode char self.forwardButton = [[UIBarButtonItem alloc] initWithTitle:frontArrowString style:UIBarButtonItemStylePlain target:self action:@selector(goForward:)]; @@ -853,11 +833,120 @@ BOOL isExiting = FALSE; } else { [self.toolbar setItems:@[self.closeButton, flexibleSpaceButton, self.backButton, fixedSpaceButton, self.forwardButton]]; } + + // Setup Auto Layout constraints + + // WebView horizontal constraints + if (@available(iOS 11.0, *)) { + UILayoutGuide *guide = self.view.safeAreaLayoutGuide; + [NSLayoutConstraint activateConstraints:@[ + [self.webView.leadingAnchor constraintEqualToAnchor:guide.leadingAnchor], + [self.webView.trailingAnchor constraintEqualToAnchor:guide.trailingAnchor] + ]]; + } else { + [NSLayoutConstraint activateConstraints:@[ + [self.webView.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor], + [self.webView.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor] + ]]; + } + + // Toolbar horizontal constraints and height + [NSLayoutConstraint activateConstraints:@[ + [self.toolbar.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor], + [self.toolbar.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor], + [self.toolbar.heightAnchor constraintEqualToConstant:TOOLBAR_HEIGHT] + ]]; + + // Address label horizontal constraints + [NSLayoutConstraint activateConstraints:@[ + [self.addressLabel.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor constant:labelInset], + [self.addressLabel.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor constant:-labelInset], + [self.addressLabel.heightAnchor constraintEqualToConstant:LOCATIONBAR_HEIGHT] + ]]; + + // Vertical constraints setup with variables + NSLayoutConstraint *webViewTopConstraint = nil; + NSLayoutConstraint *webViewBottomConstraint = nil; + NSLayoutConstraint *toolbarTopConstraint = nil; + NSLayoutConstraint *toolbarBottomConstraint = nil; + + BOOL locationbarVisible = !self.addressLabel.hidden; + + if (@available(iOS 11.0, *)) { + UILayoutGuide *guide = self.view.safeAreaLayoutGuide; + if (toolbarIsAtBottom) { + toolbarBottomConstraint = [self.toolbar.bottomAnchor constraintEqualToAnchor:guide.bottomAnchor]; + toolbarTopConstraint = [self.toolbar.topAnchor constraintEqualToAnchor:self.addressLabel.bottomAnchor]; + if (locationbarVisible) { + [self.addressLabel.bottomAnchor constraintEqualToAnchor:self.toolbar.topAnchor].active = YES; + webViewTopConstraint = [self.webView.topAnchor constraintEqualToAnchor:guide.topAnchor]; + webViewBottomConstraint = [self.webView.bottomAnchor constraintEqualToAnchor:self.addressLabel.topAnchor]; + } else { + // Address bar hidden, webView bottom to toolbar top + webViewTopConstraint = [self.webView.topAnchor constraintEqualToAnchor:guide.topAnchor]; + webViewBottomConstraint = [self.webView.bottomAnchor constraintEqualToAnchor:self.toolbar.topAnchor]; + } + } else { + toolbarTopConstraint = [self.toolbar.topAnchor constraintEqualToAnchor:guide.topAnchor]; + if (locationbarVisible) { + [self.addressLabel.bottomAnchor constraintEqualToAnchor:guide.bottomAnchor].active = YES; + webViewTopConstraint = [self.webView.topAnchor constraintEqualToAnchor:self.toolbar.bottomAnchor]; + webViewBottomConstraint = [self.webView.bottomAnchor constraintEqualToAnchor:self.addressLabel.topAnchor]; + } else { + webViewTopConstraint = [self.webView.topAnchor constraintEqualToAnchor:self.toolbar.bottomAnchor]; + webViewBottomConstraint = [self.webView.bottomAnchor constraintEqualToAnchor:guide.bottomAnchor]; + } + } + } else { + if (toolbarIsAtBottom) { + toolbarBottomConstraint = [self.toolbar.bottomAnchor constraintEqualToAnchor:self.bottomLayoutGuide.topAnchor]; + toolbarTopConstraint = [self.toolbar.topAnchor constraintEqualToAnchor:self.addressLabel.bottomAnchor]; + if (locationbarVisible) { + [self.addressLabel.bottomAnchor constraintEqualToAnchor:self.toolbar.topAnchor].active = YES; + webViewTopConstraint = [self.webView.topAnchor constraintEqualToAnchor:self.topLayoutGuide.bottomAnchor]; + webViewBottomConstraint = [self.webView.bottomAnchor constraintEqualToAnchor:self.addressLabel.topAnchor]; + } else { + webViewTopConstraint = [self.webView.topAnchor constraintEqualToAnchor:self.topLayoutGuide.bottomAnchor]; + webViewBottomConstraint = [self.webView.bottomAnchor constraintEqualToAnchor:self.toolbar.topAnchor]; + } + } else { + toolbarTopConstraint = [self.toolbar.topAnchor constraintEqualToAnchor:self.topLayoutGuide.bottomAnchor]; + if (locationbarVisible) { + [self.addressLabel.bottomAnchor constraintEqualToAnchor:self.bottomLayoutGuide.topAnchor].active = YES; + webViewTopConstraint = [self.webView.topAnchor constraintEqualToAnchor:self.toolbar.bottomAnchor]; + webViewBottomConstraint = [self.webView.bottomAnchor constraintEqualToAnchor:self.addressLabel.topAnchor]; + } else { + webViewTopConstraint = [self.webView.topAnchor constraintEqualToAnchor:self.toolbar.bottomAnchor]; + webViewBottomConstraint = [self.webView.bottomAnchor constraintEqualToAnchor:self.bottomLayoutGuide.topAnchor]; + } + } + } + + toolbarTopConstraint.active = YES; + if (toolbarBottomConstraint) { + toolbarBottomConstraint.active = toolbarIsAtBottom; + } + webViewTopConstraint.active = YES; + webViewBottomConstraint.active = YES; + + self.webView.navigationDelegate = self; + self.webView.UIDelegate = self.webViewUIDelegate; + self.webView.backgroundColor = [UIColor whiteColor]; + if ([self settingForKey:@"OverrideUserAgent"] != nil) { + self.webView.customUserAgent = [self settingForKey:@"OverrideUserAgent"]; + } - self.view.backgroundColor = [UIColor clearColor]; - [self.view addSubview:self.toolbar]; - [self.view addSubview:self.addressLabel]; - [self.view addSubview:self.spinner]; + self.webView.clearsContextBeforeDrawing = YES; + self.webView.clipsToBounds = YES; + self.webView.contentMode = UIViewContentModeScaleToFill; + self.webView.multipleTouchEnabled = YES; + self.webView.opaque = YES; + self.webView.userInteractionEnabled = YES; + self.automaticallyAdjustsScrollViewInsets = YES ; + self.webView.allowsLinkPreview = NO; + self.webView.allowsBackForwardNavigationGestures = NO; + + [self.webView.scrollView setContentInsetAdjustmentBehavior:UIScrollViewContentInsetAdjustmentNever]; } - (id)settingForKey:(NSString*)key @@ -888,114 +977,17 @@ BOOL isExiting = FALSE; - (void)showLocationBar:(BOOL)show { - CGRect locationbarFrame = self.addressLabel.frame; - - BOOL toolbarVisible = !self.toolbar.hidden; - - // prevent double show/hide - if (show == !(self.addressLabel.hidden)) { - return; - } - - if (show) { - self.addressLabel.hidden = NO; - - if (toolbarVisible) { - // toolBar at the bottom, leave as is - // put locationBar on top of the toolBar - - CGRect webViewBounds = self.view.bounds; - webViewBounds.size.height -= FOOTER_HEIGHT; - [self setWebViewFrame:webViewBounds]; - - locationbarFrame.origin.y = webViewBounds.size.height; - self.addressLabel.frame = locationbarFrame; - } else { - // no toolBar, so put locationBar at the bottom - - CGRect webViewBounds = self.view.bounds; - webViewBounds.size.height -= LOCATIONBAR_HEIGHT; - [self setWebViewFrame:webViewBounds]; - - locationbarFrame.origin.y = webViewBounds.size.height; - self.addressLabel.frame = locationbarFrame; - } - } else { - self.addressLabel.hidden = YES; - - if (toolbarVisible) { - // locationBar is on top of toolBar, hide locationBar - - // webView take up whole height less toolBar height - CGRect webViewBounds = self.view.bounds; - webViewBounds.size.height -= TOOLBAR_HEIGHT; - [self setWebViewFrame:webViewBounds]; - } else { - // no toolBar, expand webView to screen dimensions - [self setWebViewFrame:self.view.bounds]; - } - } + self.addressLabel.hidden = !show; + [self.view setNeedsLayout]; + [self.view layoutIfNeeded]; } - (void)showToolBar:(BOOL)show : (NSString *) toolbarPosition { - CGRect toolbarFrame = self.toolbar.frame; - CGRect locationbarFrame = self.addressLabel.frame; - - BOOL locationbarVisible = !self.addressLabel.hidden; - - // prevent double show/hide - if (show == !(self.toolbar.hidden)) { - return; - } - - if (show) { - self.toolbar.hidden = NO; - CGRect webViewBounds = self.view.bounds; - - if (locationbarVisible) { - // locationBar at the bottom, move locationBar up - // put toolBar at the bottom - webViewBounds.size.height -= FOOTER_HEIGHT; - locationbarFrame.origin.y = webViewBounds.size.height; - self.addressLabel.frame = locationbarFrame; - self.toolbar.frame = toolbarFrame; - } else { - // no locationBar, so put toolBar at the bottom - CGRect webViewBounds = self.view.bounds; - webViewBounds.size.height -= TOOLBAR_HEIGHT; - self.toolbar.frame = toolbarFrame; - } - - if ([toolbarPosition isEqualToString:kInAppBrowserToolbarBarPositionTop]) { - toolbarFrame.origin.y = 0; - webViewBounds.origin.y += toolbarFrame.size.height; - [self setWebViewFrame:webViewBounds]; - } else { - toolbarFrame.origin.y = (webViewBounds.size.height + LOCATIONBAR_HEIGHT); - } - [self setWebViewFrame:webViewBounds]; - - } else { - self.toolbar.hidden = YES; - - if (locationbarVisible) { - // locationBar is on top of toolBar, hide toolBar - // put locationBar at the bottom - - // webView take up whole height less locationBar height - CGRect webViewBounds = self.view.bounds; - webViewBounds.size.height -= LOCATIONBAR_HEIGHT; - [self setWebViewFrame:webViewBounds]; - - // move locationBar down - locationbarFrame.origin.y = webViewBounds.size.height; - self.addressLabel.frame = locationbarFrame; - } else { - // no locationBar, expand webView to screen dimensions - [self setWebViewFrame:self.view.bounds]; - } - } + self.toolbar.hidden = !show; + _browserOptions.toolbarposition = toolbarPosition; // keep state consistent if needed + [self.view setNeedsLayout]; + [self.view layoutIfNeeded]; } - (void)viewDidLoad @@ -1082,24 +1074,7 @@ BOOL isExiting = FALSE; } - (void) rePositionViews { - CGRect viewBounds = [self.webView bounds]; - CGFloat statusBarHeight = [self getStatusBarOffset]; - - // orientation portrait or portraitUpsideDown: status bar is on the top and web view is to be aligned to the bottom of the status bar - // orientation landscapeLeft or landscapeRight: status bar height is 0 in but lets account for it in case things ever change in the future - viewBounds.origin.y = statusBarHeight; - - // account for web view height portion that may have been reduced by a previous call to this method - viewBounds.size.height = viewBounds.size.height - statusBarHeight + lastReducedStatusBarHeight; - lastReducedStatusBarHeight = statusBarHeight; - - if ((_browserOptions.toolbar) && ([_browserOptions.toolbarposition isEqualToString:kInAppBrowserToolbarBarPositionTop])) { - // if we have to display the toolbar on top of the web view, we need to account for its height - viewBounds.origin.y += TOOLBAR_HEIGHT; - self.toolbar.frame = CGRectMake(self.toolbar.frame.origin.x, statusBarHeight, self.toolbar.frame.size.width, self.toolbar.frame.size.height); - } - - self.webView.frame = viewBounds; + /* Auto Layout handles positioning */ } // Helper function to convert hex color string to UIColor --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
