0
votes

I have a background image @2x 7360x828px and @3x 11040x1242px used inside ScrollView, looks nice on all iPhones (full screen), but on iPad background image takes only half of the screen height.

I have tried many variations, with auto layout and without, with different contentMode, but I can't achieve my goal, either background image is very stretched, or image with correct aspect ratio is smaller than ScrollView.

My last code:

var imageView = UIImageView(image: UIImage(named: "map.png"))
lazy var scrollView = UIScrollView(frame: view.bounds)

override func viewDidLoad() {
    super.viewDidLoad()

    makeScrollView()
}

func makeScrollView() {

    // For iPad
    scrollView.backgroundColor = UIColor.black
    scrollView.contentSize = imageView.bounds.size
    scrollView.clipsToBounds = true
    scrollView.contentMode = .scaleAspectFit

    print("Scroll size: == ")
    print(scrollView.contentSize)

    scrollView.autoresizingMask = UIViewAutoresizing.flexibleWidth
    scrollView.autoresizingMask = UIViewAutoresizing.flexibleHeight

    scrollView.translatesAutoresizingMaskIntoConstraints = false
    view.addSubview(scrollView)
    scrollView.contentInsetAdjustmentBehavior = .never

    scrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
    scrollView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
    scrollView.widthAnchor.constraint(equalTo: view.widthAnchor).isActive = true
    scrollView.heightAnchor.constraint(equalTo: view.heightAnchor).isActive = true

    imageView.translatesAutoresizingMaskIntoConstraints = false
    scrollView.addSubview(imageView)

    imageView.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor).isActive = true
    imageView.topAnchor.constraint(equalTo: scrollView.topAnchor).isActive = true
    imageView.heightAnchor.constraint(equalTo: view.heightAnchor).isActive = true
    imageView.widthAnchor.constraint(equalToConstant: 7360 / 2).isActive = true
    imageView.contentMode = .scaleAspectFit
}

How can I make full screen background image for iPad and keep aspect ratio?

The application is used only in landscape mode.

Screenshots:

1) contentMode = .scaleAspectFit enter image description here

2) contentMode = .scaleAspectFill enter image description here

3) .contentMode = .scaleToFill enter image description here

4) enter image description here

5) The result I want to achieve. Full-screen image, with correct aspect ratio. enter image description here

1

1 Answers

1
votes

I've prepared a sample project to demonstrate how to achieve this using only a Storyboard for positioning everything. When your setup is done properly, iOS will take care of scaling and positioning everything for you. You can also do this in code, just have to follow the tip throughout this guide about using aspect ratios.

Here's the GitHub project: https://github.com/ekscrypto/Scaled-Scroller-Demo

Using a reference image: enter image description here

Start with a UIScrollView taking the entire screen: Xcode Interface Builder layout of UIScrollView

Next, setup the container view that will act as the holder for all the different parts of the UI, this one will hold the entire image, fully scaled and matching the image aspect ratio. Simply drop a regular UIView within the scrollview, set its leading/trailing/top/bottom layout constraints to the superview container to 0. It will complaint about being unable to position it until you add the image on the next step..

Now here's where most of the magic happens. Insert a UIImageView within the UIView you just dropped in. Start by making this UIImageView leading/trailing/top/bottom layout constraints to the UIView container 0.

Xcode Interface Builder - Setting up UIImageView constraints

Then, setup an aspect ratio constraint on the UIView between its width and height, and making sure to set the multiplier value to the width:height of the image you want to use. In my case, this was 1600 by 330.

Xcode Interface Builder - UIImageView Aspect Ratio

The aspect ratio is extremely important as this will what will make sure the image is not distorted, and this is what will force the parent view to stretch and maintain that aspect ratio too. Another very important constraint, is to make sure the height of this UIImageView is equal to the Root View of the view controller. This ensure that the image goes from bottom to top of the screen, regardless if you are on an iPad or iPhone.

Notice how there was no Width or Height set to specific values, only an aspect ratio. That's how everything scales.

While this is enough to answer your question, I've also added a couple examples of UI element positioning so they are always the same scale and always positioned properly relative to the image, regardless of the device. Essentially for each UI element you want positioned relative to the image, you setup a hidden UIView with aspect ratio equal to the X and Y distance of where the you want them. Using Preview to calculate UI element positions

Then you keep that "Positioning" UIView hidden, and place your actual UI element (button, etc) in relation to that view bottom right corner. The end result is an interface properly scaled on iPhone and iPad. iPhone final product enter image description here

Although your image already had the "buttons" already baked in the images, you would probably still want to position a transparent button on top of each "level marker" on your map so user can tap on it.