iOS screen sizes, iPhone X

Hi, I’m trying to port an app with a pixel-based GUI over to JUCE and have noticed something strange: the pixel screen size on any iPhone model (including iPhone X on the simulator) is reported as 320x568. Is this normal? I see that even on an iPhone 8 Plus rendered text is nice and sharp, so “under the hood”, things seem to be done correctly, but it basically makes pixel-precise scaling and alignment of bitmaps impossible. Also, does it mean that it’s not possible to take advantage of the whole screen on the iPhone X?

EDIT: While on the screen of the iPhone 8 Plus, it does look flawless, there’s actually significant blurring over up to 4 pixels in x or y direction when I zoom in on a screenshot. So I guess it is really a 640x1136 image that is upscaled…

iOS will report a screen size depending on the launch image that you supply:

This strange quirk about iOS never fails to baffle me and I can’t quite understand how not more people run into this.

Thank you for the explanation, Fabian!

I don’t know if that has changed in the latest version of the Projucer, but the default launch image asset has just image size “slots” for iPad, iPhone 4/4S, and iPhone 5/5S/SE. So I tried to add an iPhone X sized launch image in a new asset (right click -> add assets -> app icons & launch images -> new iOS launch image). And indeed it worked! (After copying my old launch images and choosing the new asset as my “official” launch screen asset). And yes, it does really just render those resolutions for which I’ve specified images.

Now my question for you: is there any Projucer version that directly provides a slot for the iPhone X launch screen? That would make the process easier. Or am I missing somethingy? Could I specify the launch images in the Projucer project? I’ve seen the “customs Xcassets folder” parameter, but don’t quite understand how to use it.

And as a side note: why is there no iPad Pro launch screen size in XCode? Is it not possible to use the full resolution of the iPad Pro when you’re using a launch image?

1 Like

Any updates to whether or not Projucer has settings for this on iOS ?

I am also curious about whether the Projucer supports this, or will in the future.

I’ve ended up doing this dirty obj-c file which fills a juce::Rectangle<float>.

It’s quite ugly due to quick’n’dirty linking and include order.

#ifdef __APPLE__
#include "TargetConditionals.h"
#if TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR
#include <UIKit/UIKit.h>
void ios_getSafeArea (float& top, float& bottom, float& left, float& right)
{
    if (@available( iOS 11.0, * )) {
        auto res = [[[UIApplication sharedApplication] keyWindow] safeAreaInsets];
        top = res.top; bottom = res.bottom; left = res.left; right = res.right;
    }
}
#endif
#endif

This works quite well. Only thing I had to do so I do resize correctly is:

void parentHierarchyChanged() override
{
#if JUCE_IOS
    // safe area only valid after view is visible.
    resized();
#endif
}

Tested in simulator on multiple iPads, iPhones, etc…

There’s also Display::safeAreaInsets which was added here:

3 Likes

Ahh! great :slight_smile:

Many times JUCE got those hidden gems we just need to search enough :slight_smile:

Thank you for pointing it out.

1 Like

One strange thing with the JUCE / Display::safeAreaInsets is that it doesn’t report any bottom area. so you cannot adjust elements to not draw on it.

You will need to set your minimum iOS deployment target to iOS 11 or higher.

We’ve recently made some changes to take advantage of the runtime @available keyword where we can in the codebase. As long as you are building against the iOS 11 SDK, you can keep a lower deployment target and the iOS version of the device will be checked at runtime to determine whether the safe insets property is available instead of previously where we were excluding the code at compile-time:

3 Likes

How should Display::safeAreaInsets be used? It seems that standard practice is to put mobile apps into setFullScreen(true); but it doesn’t look like safeAreaInset is being considered in full screen mode…

To answer my own question, this seems to be working fine, but I think safe areas should be incorporated into full screen mode…

MainWindow::resized()
{
    juce::DocumentWindow::resized();
            
    auto contentComp = getContentComponent();
            
    if(contentComp != nullptr)
    {
        auto safeAreaBorder = juce::Desktop::getInstance().getDisplays().getPrimaryDisplay()->safeAreaInsets;
        auto contentBorder = getContentComponentBorder();
        juce::BorderSize<int> totalBorder(
                                    safeAreaBorder.getTop() + contentBorder.getTop(),
                                    safeAreaBorder.getLeft() + contentBorder.getLeft(),
                                    safeAreaBorder.getBottom() + contentBorder.getBottom(),
                                    safeAreaBorder.getRight() + contentBorder.getRight()
                                    );
        getContentComponent()->setBoundsInset(totalBorder);
    }
}
1 Like