Adaptive launch screen storyboards: is there a way to differentiate iPad orientations?
Asked Answered
S

4

15

I'm investigating the use of a storyboard for launch images for my app. The app has always used a large photo for the launch image, which is also used as the background for the first view. However the image is different when the app is launched in landscape on an iPad.

So is there any way to differentiate between an iPad in portrait and an iPad in landscape when using a an Adaptive storyboard for a launch screen? Because it's a launch screen I can't run any code, it would have to be done completely through the storyboard.

Salter answered 20/10, 2014 at 7:13 Comment(7)
You should be able to achieve that using size classes in your launchScreen.xib?Tran
@Tran iPad size classes are regular height and regular width when in both portrait and landscape... so that's my question, how do you differentiate?Salter
Take a look at #9122649Griseofulvin
You might be able to do this by adding both images, then using "placeholder" views between the images and say top border so that when in landscape, one image effectively moves off screen and the other stays.Mesquite
@SeanR, if use the older method, set lauch images (we can set portait and landscape lauch images) not use size class, does this fit your question .Pragmatism
were you ever able to figure this out? I am facing this issue now since my launch screen is some brandingMatland
@Matland no, I don't think it's possible. I ended up using a large enough image that would work for either orientation.Salter
Q
4

I found a solution using spacer views that position the correct image in the visible area and move the other one off screen (as suggested by David H).

You can't provide different images for different screen sizes (iPhone 4, iPhone X, ...), but if you want different images for iPhone and iPad and different images for portrait and landscape this solution is for you.

I created an example project on github if you want to try it out. It works on iPad and iPhone.

Constraints in Interface Builder

The important constraints are

PortraitSpacer.width ≤ 5 × view.width
PortraitSpacer.width ≤ 5 × view.height

LandscapeSpacer.width ≥ 5 × view.width
LandscapeSpacer.width ≥ 5 × view.height

PositionSpacer.width = 5 × view.width

where view.width and view.height are the main view's width and height.

The PortraitSpacer positions the portrait image at 5 × min(view.width, view.height), the LandscapeSpacer positions the landscape image at 5 × max(view.width, view.height), and the PositionSpacer has the same width as PortraitSpacer in portrait mode and the same width as LandscapeSpacer in landscape mode.

We multiply everything with 5 so the two images do not overlap. This works for all devices where the following is true

5 × min(view.width, view.height) + max(view.width, view.height) ≤ 5 × max(view.width, view.height)

In landscape mode this would mean

5 / 4 ≤ view.width / view.height

which is the case for all current devices: iPad has the lowest aspect ratio with 4:3 which is still greater than 5:4.

You can then of course configure images per device (iPhone, iPad) in the asset catalog.

Quiteri answered 23/4, 2019 at 15:25 Comment(1)
Not working for me on iOS 12 and 14 (a black launchscreen appears). on 13 it's fine. any clue?Madlynmadman
C
4

Apple these days encourages you to think of rotation not in terms of device orientation, but just as an animated bounds change (sometimes with a semantic hint).

We saw why with the iPhone 6 Plus — what used to be a "phone, portrait" interface becomes a sidebar interface in landscape on certain phones.

The more your view controllers assume about devices and their orientation, the harder is is to adapt to new devices that offer new ways of reusing view controllers.

Also, UIDeviceOrientation is not the same as UIInterfaceOrientation. If you use the former to make UI decisions, you'll be stymied when the device is face-up or face-down, and (IIRC) your users will be frustrated when your app doesn't respect Orientation Lock.

So what's the difference between a landscape and portrait iPad? Both are Regular x Regular in traits... But one has bounds that are taller than they are wide, and vice versa. It's totally okay to make high-level layout decisions based on aspect ratio (and use auto layout for the details).

Come answered 18/11, 2014 at 0:32 Comment(2)
So, for the purposes of the launch image storyboard, there's no way to have a different launch image for iPad orientations? Because if it requires checks in code, these aren't done for the launch image storyboard.Salter
Ah, I missed that you're looking at launch storyboards specifically. Sorry, I don't know of a way to customize those for orientation. (I dunno if that means there isn't one, but it might not be a bad idea to file a bug regardless.)Come
Q
4

I found a solution using spacer views that position the correct image in the visible area and move the other one off screen (as suggested by David H).

You can't provide different images for different screen sizes (iPhone 4, iPhone X, ...), but if you want different images for iPhone and iPad and different images for portrait and landscape this solution is for you.

I created an example project on github if you want to try it out. It works on iPad and iPhone.

Constraints in Interface Builder

The important constraints are

PortraitSpacer.width ≤ 5 × view.width
PortraitSpacer.width ≤ 5 × view.height

LandscapeSpacer.width ≥ 5 × view.width
LandscapeSpacer.width ≥ 5 × view.height

PositionSpacer.width = 5 × view.width

where view.width and view.height are the main view's width and height.

The PortraitSpacer positions the portrait image at 5 × min(view.width, view.height), the LandscapeSpacer positions the landscape image at 5 × max(view.width, view.height), and the PositionSpacer has the same width as PortraitSpacer in portrait mode and the same width as LandscapeSpacer in landscape mode.

We multiply everything with 5 so the two images do not overlap. This works for all devices where the following is true

5 × min(view.width, view.height) + max(view.width, view.height) ≤ 5 × max(view.width, view.height)

In landscape mode this would mean

5 / 4 ≤ view.width / view.height

which is the case for all current devices: iPad has the lowest aspect ratio with 4:3 which is still greater than 5:4.

You can then of course configure images per device (iPhone, iPad) in the asset catalog.

Quiteri answered 23/4, 2019 at 15:25 Comment(1)
Not working for me on iOS 12 and 14 (a black launchscreen appears). on 13 it's fine. any clue?Madlynmadman
M
2

You actually can specify different launch screen images from inside of your LaunchScreen.storyboard with Xcode8. Using a LaunchScreen.storyboard is the preferred way of specifying a launch screen when targeting devices running iOS8 and above.

Here’s a quick step-by-step example of how to specify landscape images for the devices that support landscape launch screens:

  1. First add your your “splash screen” images to your projects Assets.xcassets. You should only need two separate Image Sets: one for portrait and one for landscape. Name them something like splash (this is the portrait image set) and splash-landscape (this is the landscape one).
  2. Now that you have your images in your projects assets go to your LaunchScreen.storyboard file. (I’m assuming you already have your launch screen view controller set up with the image and it’s constraints set up in the LaunchScreen.storyboard.)
  3. Select the ImageView that is in you launch screen’s viewcontroller.
  4. Go to the Assets Inspector for the ImageView.
  5. Add the “splash” image to the Image source field. This is your portrait image source.
  6. Click the + button next to the Image source field that you set up in step 5.
  7. From the pop-up that is now displayed select Regular for both the Width and Height selectors. This is specifying a new adaptive set for iPads that are in landscape. A new image source field will appear with the title wR hR. Add the “splash-landscape” image to the wR hR Image source field so the storyboard knows to use a different image when in landscape.
  8. Now we need to add support for the “iphone plus” devices when in landscape. So click the + button next to the Image source field again.
  9. This time select compact for the height and regular for the width selectors. This is specifying a new adaptive set for “iPhone plus” devices that are in landscape. A new image source field will appear with the title wR hC.
  10. Add the “splash-landscape” image to the wR hC Image source field so the storyboard knows to use a different image when in landscape on an “iphone plus device”.

By following these steps you won’t have to write any code, do anything weird, or rely on the old launchScreen image sets. The LaunchScreen.storyboard will handle everything for you! It’s pretty neat.

For more information on Size Classes and the Interface Builder check out the awesome article: https://medium.com/@craiggrummitt/size-classes-in-interface-builder-in-xcode-8-74f20a541195

Edit: This is just a brief contrived example of what I think I did to get the SplashScreen images to work using separate image sets, adaptive sets, and constraints. It took a lot of messing around with to get it to work (pretty much a whole night and then some). It’s tough to explain the Interface Builder and all the different aspects of it in a step by step post. So use this answer and example as a guide to get to where you need to be. Also, the link above is very helpful. Also, who knows, maybe I’m just wrong or misunderstanding something...

Hope someone will find this helpful.

Motorbus answered 7/9, 2017 at 7:0 Comment(6)
This is a great answer and very informative. But am I correct in that there is no way to differentiate iPad portrait and iPad landscape since they are both regular height / regular width?Salter
hmmm, I don't know if you can "differentiate" between the the two at run time using this, but by using the technique described here you should be able to specify different images/constraints/sizes/etc for when an iPad is in portrait or landscape. I'm pretty sure my project does exactly this (it specifies a larger image size when the iPad is in landscape). If you're looking for a way to handle/figure out these things at runtime then this answer probably isn't it, as it just allows you to specify what the app does when in these different situations (without having to write code or anything).Motorbus
I tried your solution and the "splash-landscape" image appears on iPad both in portrait and landscape. Because iPad is wR hR in both landscape and portrait, it uses the specified wR hR image. So in your example, "splash" will only appear for wC hR size classes. So yeah, I'm still leaning towards different images for landscape and portrait iPad launch screens not being possible.Salter
Did anyone get solution for this? If yes, can you show us sample launch screen?Dialect
How you will define image sizes if iPad alone launch both portrait and landscape? Ex: iPad 9.7 Portrait size is an 768x1024 and landscape 1024x768. (image will streched) Here how you will give two different images?Dialect
@KarthiKeyan this is just a brief example of what I did to get it to work. You need to tweak it and mess around with the IB. It took me a while to get it to work, and actually understand the Adaptive Layouts.Motorbus
D
1

The device orientation is pretty straightforward to check on the fly, and also receive notifications for orientation changes.

(Everything here is in Objective-C)

Head over to your App Delegate, and in your applicationDidFinishLaunchingMethod

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
//
//then call this, what we're telling the device is, "Hey, let me know when you change orientations!"

[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];

    //Not done yet, now we have to register a method to call on the notification
   [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(deviceOrientationDidChange) name:UIDeviceOrientationDidChangeNotification object:nil];
}

Now, you'll want to define the method that is called when the device is oriented.

so, somewhere in your app delegate...

- (void) deviceOrientationDidChange {
    UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];
    if (orientation == UIDeviceOrientationPortrait) {
        //do something if portrait
    }
    else {
         //do another thing if landscape
    }
}

And that's really all there is to it. You can then change your background image in that method!

Dennet answered 18/11, 2014 at 0:4 Comment(1)
Thanks, I know how to get the orientation in code. I want to know how to differentiate iPad orientations using adaptive size classes, specifically for the launch storyboard.Salter

© 2022 - 2024 — McMap. All rights reserved.