Landscape vs. Portrait background image in Asset C

2019-08-07 06:21发布

I have a use case that seems to fall into the cracks between asset catalogs and size classes. My Universal app needs a full screen background image that is different in Landscape and Portrait orientations, and Landscape is only supported for the iPad & iPhone 6.

Since I can't add landscape images to the asset catalog for a new image set, my current solution looks like this (supports iOS 7 & 8):

// permit landscape mode only for iPads & iPhone 6 (would prefer to use size classes, but...?)
override func shouldAutorotate() -> Bool {
    let size = view.frame.size
    let maxv = max(size.width, size.height)
    return ((maxv > 700.0) || (maxv == 512.0)) ? true : false
}

// this will be triggered only for iOS 7, as long as viewWillTransitionToSize:withTransitionCoordinator: is also implemented!
override func willRotateToInterfaceOrientation(toInterfaceOrientation: UIInterfaceOrientation, duration: NSTimeInterval) {
    adjustToOrientation(toInterfaceOrientation)
}

// this will be triggered only for iOS 8
override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) {

    let orientation = UIApplication.sharedApplication().statusBarOrientation

    // need to reverse the sense of the orientation here; Application still has the previous orientation
    switch orientation {
        case .Portrait, .PortraitUpsideDown:
            adjustToOrientation(.LandscapeLeft)
        case .LandscapeLeft, .LandscapeRight:
            adjustToOrientation(.Portrait)
        default:
            adjustToOrientation(.Portrait)
    }

}

func adjustToOrientation(newInterfaceOrientation: UIInterfaceOrientation) {

    let size = view.frame.size

    // rotation already permitted only for iPad & iPhone 6, but need to know which one (size classes useless here?)
    switch (max(size.width, size.height)) {
        case 1024.0:
            if UIInterfaceOrientationIsLandscape(newInterfaceOrientation) {
                backgroundImage.image = UIImage(named: "Background-Landscape@2x~ipad.png")
            } else {
                backgroundImage.image = UIImage(named: "Background@2x~ipad.png")
            }
        case 736.0:
            if UIInterfaceOrientationIsLandscape(newInterfaceOrientation) {
                backgroundImage.image = UIImage(named: "Background-Landscape@3x~iphone.png")
            } else {
                backgroundImage.image = UIImage(named: "Background@3x~iphone.png")
            }
        case 512.0:
            if UIInterfaceOrientationIsLandscape(newInterfaceOrientation) {
                backgroundImage.image = UIImage(named: "Background-Landscape~ipad.png")
            } else {
                backgroundImage.image = UIImage(named: "Background~ipad.png")
            }
        default:
            break
    }

}

This works, but seems fragile. Is there a more correct way to identify the device as something that supports a regular size class in Landscape, before actually being in Landscape mode? Or some way that I've missed to specify the Landscape equivalents for an image set?

2条回答
放我归山
2楼-- · 2019-08-07 06:48

You can use size classes in assets catalog or you can have two image sets: one for portrait and one for landspace mode. Then you can access images by asset name. This will reduce your code a little. But I'd recommend to cosider using size classes everywhere it's possible.

查看更多
成全新的幸福
3楼-- · 2019-08-07 07:08

So the final solution was:

-Set the Width property on the image asset to Any+Regular and added a couple of Landscape images for the iPhone 6+ and iPad, and UIImage automatically does the rest

-A more elegant way to permit rotation only for those two devices, in both iOS 7 & iOS 8:

override func shouldAutorotate() -> Bool {
    let scale = UIScreen.mainScreen().scale
    let idiom = UIDevice.currentDevice().userInterfaceIdiom
    return ((idiom == .Pad) || (scale > 2.0)) ? true : false
}

So all of the above down to 5 lines of code!

查看更多
登录 后发表回答