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

左心房为你撑大大i 提交于 2019-11-27 19:22:40

问题


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.


回答1:


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.

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.




回答2:


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).




回答3:


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!




回答4:


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.



来源:https://stackoverflow.com/questions/26460216/adaptive-launch-screen-storyboards-is-there-a-way-to-differentiate-ipad-orienta

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!