Full page background image sizes after new Iphone models has been released (Xcode)

Viewed 3445

here are the iPhone Resolutions as you know;

  • Iphone Xs Max 414x896 points Render at 3x, 1242x2688 px
  • Iphone Xr 414x896 points Render at 2x, 828x1792 px
  • Iphone X, Xs 375x812 points. Render at 3x, 1125x2436 px
  • Iphone 6+, 6s+, 7+, 8+ 414x716 points, Render at 3x, 1242x2208 px
  • Iphone 6, 6s, 7, 8 375x667 points, Render at 2x, 750x1334px

Let's assume I would like to create a full page background image. Can you confirm x, @2x, and @3x sizes please?

  • Is 375x667 px true for @x?
  • Is 750x1334 px true for @2x?
  • What about 3x size? 1242x2688 ( Reference should be iPhone Xs Max for the @3x size?)
4 Answers

THIS IS UNOFFICIAL TRICK TO DEFINE IMAGES FOR DIFFERENT SCREEN SIZES (iPhone XS Max, iPhone XS, iPhone Xr).

I found a trick. In my application we have launch screens for all iPhone Devices (see screenshot). Lanuch screen example

Next screen which appears after Launch screen is Login. It should have the same image like Launch screen. Unfortunately Xcode creates the following image set in Assets out of box (iPhone 1x, 2x, 3, iPad 1x, 2x - see image). Xcode generates Image Assets template

And during transitions from Launch Screen to Login screen I see artifacts because Image stretching on iPhone X, Xs Max, iPhone Xr

To fix the issue I copied Contents.json file from LaunchImage.launchimage folder to BackgroundImage.imageset folder in Finder (see steps on image below) copy steps

UPDATE the content of AppImages.xcassets/BackgroundImage.imageset/Contents.json file:

{
  "images" : [
    {
      "idiom" : "iphone",
      "scale" : "1x"
    },
    {
      "idiom" : "iphone",
      "subtype" : "retina4",
      "scale" : "1x"
    },
    {
      "idiom" : "iphone",
      "filename" : "retina4640x960.png",
      "scale" : "2x"
    },
    {
      "idiom" : "iphone",
      "filename" : "retina4640x1136.png",
      "subtype" : "retina4",
      "scale" : "2x"
    },
    {
      "idiom" : "iphone",
      "filename" : "retina47750x1334.png",
      "subtype" : "667h",
      "scale" : "2x"
    },
    {
      "idiom" : "iphone",
      "filename" : "iPhoneXr828x1792.png",
      "subtype" : "1792h",
      "scale" : "2x"
    },
    {
      "idiom" : "iphone",
      "scale" : "3x"
    },
    {
      "idiom" : "iphone",
      "subtype" : "retina4",
      "scale" : "3x"
    },
    {
      "idiom" : "iphone",
      "filename" : "retina551242x2208.png",
      "subtype" : "736h",
      "scale" : "3x"
    },
    {
      "idiom" : "iphone",
      "filename" : "iPhoneX1125x2436.png",
      "subtype" : "2436h",
      "scale" : "3x"
    },
    {
      "idiom" : "iphone",
      "filename" : "iPhoneXSMax1242x2688.png",
      "subtype" : "2688h",
      "scale" : "3x"
    },
    {
      "idiom" : "ipad",
      "filename" : "ipad1024x768.png",
      "scale" : "1x"
    },
    {
      "idiom" : "ipad",
      "filename" : "ipad2048x1536.png",
      "scale" : "2x"
    }
  ],
  "info" : {
    "version" : 1,
    "author" : "xcode"
  }
}

And now in Xcode I see the following templates. I can define background image for the following devices Retina HD 4.7"(iPhone 6, iPhone 7, iPhone 8), Retina HD 5.5" (iPhone 6 Plus, iPhone 7 Plus, iPhone 8 Plus), iPhone Xr, iPhone X/iPhone Xs, iPhone Xs Max Result

@Igor had interesting answer :) even not so bad excluding one thing - then your project growing exponentially cuz of amount of images. instead you can have 3 images (or even 2 if you wanna support devices starting from 5 to XSMax). so image for 4S diagonal, then for 5, SE, 6, 7, 8 and for Xr, X, Xs, XsMax.

When you need to choose proper image you're using code below:

extension UIImage {
    static func imageWithName(_ name: String) -> UIImage? {
        var finalName = name
        switch UIDevice.current.screenType {
        case .short: finalName += "@short"
        case .normal: finalName += "@normal"
        case .tall: finalName += "@tall"
        case .unknown: finalName = ""
        }
        return UIImage(named: finalName)
    }
}

extension UIDevice {
    enum DeviceType: String {
        case iPhones_4_4S = "iPhone 4 or iPhone 4S"
        case iPhones_5_5s_5c_SE = "iPhone 5, iPhone 5s, iPhone 5c or iPhone SE"
        case iPhones_6_6s_7_8 = "iPhone 6, iPhone 6S, iPhone 7 or iPhone 8"
        case iPhones_6Plus_6sPlus_7Plus_8Plus = "iPhone 6 Plus, iPhone 6S Plus, iPhone 7 Plus or iPhone 8 Plus"
        case iPhones_X_XS = "iPhone X or iPhone XS"
        case iPhone_XR = "iPhone XR"
        case iPhone_XSMax = "iPhone XS Max"
        case unknown
    }
    var deviceType: DeviceType {
        switch UIScreen.main.nativeBounds.height {
        case 960: return .iPhones_4_4S
        case 1136: return .iPhones_5_5s_5c_SE
        case 1334: return .iPhones_6_6s_7_8
        case 1792: return .iPhone_XR
        case 1920, 2208: return .iPhones_6Plus_6sPlus_7Plus_8Plus
        case 2436: return .iPhones_X_XS
        case 2688: return .iPhone_XSMax
        default: return .unknown
        }
    }

    enum ScreenType {
        case short, normal, tall, unknown
    }
    var screenType: ScreenType {
        switch deviceType {
        case .iPhones_4_4S: return .short
        case .iPhones_5_5s_5c_SE: fallthrough
        case .iPhones_6_6s_7_8: fallthrough
        case .iPhones_6Plus_6sPlus_7Plus_8Plus: return .normal
        case .iPhone_XR: fallthrough
        case .iPhones_X_XS: fallthrough
        case .iPhone_XSMax: return .tall
        default: return .unknown
        }
    }
}

You should store your images in asset catalog like this - single scale, for universal devices and with "@short", "@normal", "@tall" suffixes

Asset Catalog

USAGE: bgImageView.image = UIImage.imageWithName("main_bg")

UPDATE: The other option is just to use normal way like @1x @2x @3x images but with content mode scale aspect fill:

bgImageView.contentMode = .scaleAspectFill

then your image will be perfectly filling a screen, and only you have to be ready that it will be cropped from a sides. If it's not ruining a view of your image then it's easiest and best solution.

Asset Catalog - normal way

P.S.: I know I'm not answering to a topic starter but to Igor's answer, BUT I got here searching for solution of managing images in asset catalog due to new sizes of screen released from Apple.

UPDATE 2: As far as I got main question in this topic and resolutions/scales explained here, I think for @3x good to use XSMax resolution and for @2x - Xr resolution, so then it will be cropped but looking good and sharp on all devices with contentMode = .scaleAspectFill as explained above. For exporting graphics I would do then like on picture below:

Full Page Resources Export Configuration

taking a width 1792w of Xr for @2x size and 2688w for @3x

For this simply create imageset with Universal devices support.

enter image description here

Add single image with latest device dimensions I used 1242 × 2208. In xib/storyboard add imageview with content-Mode AspectFit and its working fine.

You can use bigger resolution for solving this problem

1X - 375x667 + Y

2X - (375*2)x(667*2) + 2Y

3X - (375*3)x(667*3) + 3Y

The Phone automatically set the image size.

Related