Ionic v1 safe areas not working on Xcode 11.5 simulator

Viewed 910

After upgrading Xcode 10 to 11.5 and upgrading other components for cordova/ionic v1 app, the previous solutions for getting full screen - notch safe zones/no white/black bars - on an iPhoneX/iPhone11 are no longer working. The screen pushes up behind the notch.

In index.html: <meta name="viewport" content="viewport-fit=cover, width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">

And in CSS body{ } and Ionics .tabs { } the following code is no longer working:

body {
  padding-top: constant(safe-area-inset-top) ;
  padding-top: env(safe-area-inset-top) ;
}

.tabs {
  padding-top: constant(safe-area-inset-top) ;
  padding-top: env(safe-area-inset-top) ;
}

Does anyone have a solution to this?

I am not certain if this related or not, but I am beginning to suspect it is. I am getting some gulp messages cannot load gulp ... at the start of the compile of app from CLI. My app compiles with error or failing - and deploys to simulator devices just fine. But I am wondering if the gulp/sass issues is contributing the safe zone UI layout issues I am seeing.

% ionic cordova build ios
> ionic-v1 build
[08:16:10] Cannot load gulp: ReferenceError: primordials is not defined
[08:16:10] Cannot load gulp: ReferenceError: primordials is not defined
[08:16:10] Cannot run sass task: missing in gulpfile.js
[08:16:10] Cannot load gulp: ReferenceError: primordials is not defined
> cordova build ios

and my build environment:

% ionic info

Ionic:
   Ionic CLI         : 6.10.1 (/usr/local/lib/node_modules/@ionic/cli)
   Ionic Framework   : ionic1 1.0.0
   @ionic/v1-toolkit : 1.0.22

Cordova:
   Cordova CLI       : 9.0.0 (cordova-lib@9.0.1)
   Cordova Platforms : ios 5.1.1
   Cordova Plugins   : cordova-plugin-ionic-keyboard 2.2.0, cordova-plugin-ionic-webview 5.0.0, (and 32 other plugins)

Utility:
   cordova-res : 0.15.1
   native-run  : not installed

System:
   ios-deploy : 1.10.0
   ios-sim    : 8.0.2
   NodeJS     : v14.5.0 (/usr/local/Cellar/node/14.5.0/bin/node)
   npm        : 6.14.5
   OS         : macOS Catalina
   Xcode      : Xcode 11.5 Build version 11E608c

% gulp -v
CLI version: 2.3.0
Local version: 3.9.1
2 Answers

My previous answer was for Ionic v1 apps still running UIWebView on iPhones. But since the App Store will no longer accept app with UIWebView I had to switch my app to WKWebView. CORS was a bit of a pain in the butt, but the bigger issue is all the code that worked for Ionic v1 UIWebView apps broke in the same Ionic v1 app running WkWebView.

I don't know why I keep having to do special things to deal with notch iPhones, but I do think its related to still being on Ionic V1. Below took me quite sometime to figure out, but solution is much more simple than solution for the UIWebView above:

Using Ionic v1 TABS with cordova-plugin-ionic-webview:

In app.js:

if (window.StatusBar) {
  StatusBar.hide() ;
}

In custom.css file:

/* this pushes down the ion-header-bar for 'notch' iPhones */
.platform-ios.platform-cordova:not(.fullscreen) .bar-header:not(.bar-subheader) {
  height: 44px;
  margin-top: constant(safe-area-inset-top); /* iOS 11.0 */
  margin-top: env(safe-area-inset-top) ;
}
/* this is for parent of ion-nav-title for 'notch' iPhones */
.platform-ios.platform-cordova:not(.fullscreen) .bar-header:not(.bar-subheader) > * {
  margin-top: 0px;
}
/* this pushes down ion-content for 'notch' iPhones */
.platform-ios.platform-cordova:not(.fullscreen) .has-header:not(.bar-subheader) {
  top: 44px;  /* this needs to match the height set for ion-header-bar */
  padding-top: constant(safe-area-inset-top); /* iOS 11.0 */
  padding-top: env(safe-area-inset-top) ;
}
/* this pushes button tab bar up from behind iPhone HOME button */
.tabs {
  /* padding not needed, but it eliminates a 1px border at top of nav bar */
  padding-top:0px !important;  /* over rides .tabs @media i ionic.app.css */
  margin-bottom: constant(safe-area-inset-bottom); /* iOS 11.0 */
  margin-bottom: env(safe-area-inset-bottom); /* iOS 11.2 */
}

I have my tabs at the bottom of my app now - my original post the tab bar was still at the top. I know others will criticize this answer but after months of wrestling with notch phone layouts here is how I finally resolved things:

NOTE: The below solution is for phones that were using UIWebView - which is no longer accepted for iOS. Below is a custom solution for WkWebView

In Xcode, on Target -> General, uncheck Hide Status Bar & Requires full screen.

In project index.xml:

In body tag...counter intuitive to all the other posts, I removed:

body {
  //padding-top: constant(safe-area-inset-top) ;  - remove both of these lines.
  //padding-top: env(safe-area-inset-top) ;  
}

I then added:

/* this is for ion-header-bar for 'notch' iPhones*/
/* the default is 64px and creates a very large/tall nav-title bar */
.platform-ios.platform-cordova:not(.fullscreen) .bar-header:not(.bar-subheader) {  
  height: 44px;
}

/* this is for parent of ion-nav-title for 'notch' iPhones */
.platform-ios.platform-cordova:not(.fullscreen) .bar-header:not(.bar-subheader) > * {
  margin-top: 0px; 
}

/* sets margin beneath tabs, pushing them up so they are not behind iPhone home button */
.tab-nav {
  margin-bottom: constant(safe-area-inset-bottom); /* iOS 11.0 */
  margin-bottom: env(safe-area-inset-bottom); /* iOS 11.2 */
}

And then in my app.js file, I added this code to detect if phone has notch or not - and then hide/show status bar accordingly. With the a notch phone, StatusBar.show() will push the ion-header-bar down below the notch.

if (ionic.Platform.isIOS()) {
  deviceData.iosStatusBar = 20 ;
  if (hasNotch() == true) {
    //global object to track if phone has notch or not.
    deviceData.iosNotch = true ;
    console.log("NOTCH FOUND, Applying safe-area CSS") ;
    // do NOT apply ionic.Platform.fullScreen() if phone has notch
    if (window.StatusBar) {          
      StatusBar.show() ;  // show ios status bar, forces ion-header-bar down below notch
      StatusBar.overlaysWebView(false); 
    }
  } else {
    deviceData.iosNotch = false ;
    // if not notch, then force app to full screen. 
    ionic.Platform.fullScreen();
    if (window.StatusBar) {
      StatusBar.hide();   // hide ios status bar
      StatusBar.overlaysWebView(true);
    }
  }
}

And then function to detect if phone has notch or not:

function hasNotch() {
  if (CSS.supports('padding-bottom: env(safe-area-inset-bottom)')) {
    let div = document.createElement('div');
    div.style.paddingBottom = 'env(safe-area-inset-bottom)';
    document.body.appendChild(div);
    let calculatedPadding = parseInt(window.getComputedStyle(div).paddingBottom, 10);
    document.body.removeChild(div);
    if (calculatedPadding > 0) {
      return true;
    }
  }
  return false;
}
Related