Castafiore
Castafiore

Reputation: 41

iPhone : changing background image when rotating device using size classes

I placed a background image that needs to fill the iPhone screen. It is fine in portait view but when I rotate the device the top is cropped which I don't want. The best seems to be an image for the portrait view and one for the landscape view. I tried to use the size classes, assigning 1 image for compact W and any H and 1 for any W and compact H. I can't make it work. I am using Xcode 6.3 and swift 1.2. I made another app using the instructions in the book iOS 8 essentials (Neil Smyth) chapter 24 but it does not work. I downloaded the file "universal_images", thinking I was doing something wrong but it does not work neither.

Upvotes: 2

Views: 4816

Answers (4)

Georgie Flood
Georgie Flood

Reputation: 1

I wanted to do this and it took me forever to find an ios 11/swift 4 version of the solution so I thought I would offer it here. You follow all the steps given in the answer above but the code is:

 func changeBackground() {
     //iPads etc
   if traitCollection.horizontalSizeClass == .regular{
    background.image = UIImage(named: "beethovenV.png")
   }
    else {  
            //compact width - most iPhones in portrait
           background.image = UIImage(named: "beethovenV.png")
            //iphone in landscape
           if traitCollection.verticalSizeClass == .compact{
             background.image = UIImage(named: "beethovenH.png")
            }
            }
}


override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
super.traitCollectionDidChange(previousTraitCollection)
changeBackground()
}

Upvotes: 0

Castafiore
Castafiore

Reputation: 41

This is the answer to my question.

1 - I added my two background pictures (one landscape version and one portrait version) in Supporting files , in a group that I named "images" (not necessary but tidier).

2 - In Main.storyboard, I added a View (via object library on the right inside bottom) that appears inside the already present view in the view controller scene.

3 - Inside that view I put an image view and in the editor -> image view ->image selected the portrait image file. View-> mode-> Aspect to fill

4 - I add constraints to the container view and image view through the pin menu 0 bottom, top, left , right.

5 - In ViewController.swift inside the class ViewController: UIViewController {…… I added the following code:

 override func willRotateToInterfaceOrientation(toInterfaceOrientation: UIInterfaceOrientation, duration: NSTimeInterval) {
    if (toInterfaceOrientation.isLandscape) {
        println("Landscape");
        background.image = UIImage (named: "BeethovenH.png")
    }
    else {
        println("Portrait");
        background.image = UIImage (named: "BeethovenV.png")
    }
}

It worked perfectly. Thanks for your help.

Upvotes: 2

Rory McKinnel
Rory McKinnel

Reputation: 8014

I always use two images: one for portrait and one for landscape and have different resolutions for different targets. This is the best way to guarantee your background looks right on different devices with different aspect ratios.

I always make the background a UIImageView contained in a separate UIView. Add constraints to all sides to pin the container view and image view to the edges. This ensures the image fills the screen for portrait and landscape automatically.

I have the following method to set the background for a given orientation. It relies on a factory class to load the appropriate image. Loading backgrounds requires more effort than normal images as size class does not tell you anything about the aspect ratio. Replace the MyImageFactory with whatever code you use to load the appropriate image.

- (void) setBackgroundImage:(UIInterfaceOrientation) orientation{
    if (orientation == UIInterfaceOrientationLandscapeLeft ||
        orientation == UIInterfaceOrientationLandscapeRight)
    {
        NSLog(@"Setting background to landscape");
        [self.backgroundImageView setImage:[MyImageFactory backgroundImageLandscape]];
    }
    else{
        NSLog(@"Setting background to Portrait");
        [self.backgroundImageView setImage:[MyImageFactory backgroundImage]];
    }
}

Call the background setting method in viewWillAppear to initialise the background to the startup orientation as follows:

- (void) viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];

    // Set the background image
    [self setBackgroundImage:self.interfaceOrientation];
}

Finally to deal with rotation, override the rotation method as follows:

- (void) willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration{
    [self setBackgroundImage:toInterfaceOrientation];

    // Do anything else which is rotation specific.
}

Works well on iOS7 to iOS9.

Upvotes: 0

baydi
baydi

Reputation: 1003

You need to do simple 2 steps 1.) Choose size class any,any it will run on both portrait and landscape mode for all devices both for ipad and iphone.

2.) Use autolayout and set constraint as shown in screenshotenter image description here

It will work fine.Thanks

Upvotes: -1

Related Questions