38

I'm trying to make a UIView image for my background in swift using pattern image. The code I have works well except for the fact that I want the image to take the whole screen. My code looks like this: self.view.backgroundColor = UIColor(patternImage: UIImage(named: "backgroundImage")!)

Does anyone know how to make the background an image that will take up the whole screen, and would scale when appearing on different iPhone screen sizes?

Ahmad F
  • 30,560
  • 17
  • 97
  • 143
GuiGui23
  • 4,035
  • 4
  • 19
  • 17

10 Answers10

44

Note That:

I posted this answer from my old account (which is deprecated for me and I can't access it anymore), this is my improved answer.


You can do it programmatically instead of creating an IBOutlet in each view. just create a UIView extension (File -> New -> File -> Swift File -> name it whatever you want) and add:

extension UIView {
func addBackground() {
    // screen width and height:
    let width = UIScreen.mainScreen().bounds.size.width
    let height = UIScreen.mainScreen().bounds.size.height

    let imageViewBackground = UIImageView(frame: CGRectMake(0, 0, width, height))
    imageViewBackground.image = UIImage(named: "YOUR IMAGE NAME GOES HERE")

    // you can change the content mode:
    imageViewBackground.contentMode = UIViewContentMode.ScaleAspectFill

    self.addSubview(imageViewBackground)
    self.sendSubviewToBack(imageViewBackground)
}}

Now, you can use this method with your views, for example:

override func viewDidLoad() {
    super.viewDidLoad()

    self.view.addBackground()
}
Community
  • 1
  • 1
Ahmad Fayyas
  • 441
  • 4
  • 3
  • 2
    let imageViewBackground = UIImageView(frame: UIScreen.mainScreen().bounds) – Leo Dabus Dec 31 '15 at 02:12
  • great piece of code , but I have small question what is the size of background should be to fit all screens at different scales – Mina Fawzy Apr 24 '16 at 14:50
  • @MinaFawzy Thank you for asking, you might want to check my improved answer, it should contains an answer for you :) – Ahmad F Mar 15 '17 at 06:44
27

Just add your UIImageView positioned centered and with all edges snapping to the edges. Leave it there and click on the right bottom corner as shown below and now go ahead and add 4 constrains to Top, Bottom, Left and Right Edges.

enter image description here

Now just select your image view and using the IB inspector select how you would like your image: fill or fit as you can see as follow:

enter image description here

Leo Dabus
  • 229,809
  • 59
  • 489
  • 571
17

This is the updated answer of my previous one.

As the same approach of my previous answer, You can create an extension of UIView and add addBackground() method to it, as follows:

Remember: if you are adding it in a new .swift file, remember to add import UIKit

extension UIView {
    func addBackground(imageName: String = "YOUR DEFAULT IMAGE NAME", contentMode: UIView.ContentMode = .scaleToFill) {
        // setup the UIImageView
        let backgroundImageView = UIImageView(frame: UIScreen.main.bounds)
        backgroundImageView.image = UIImage(named: imageName)
        backgroundImageView.contentMode = contentMode
        backgroundImageView.translatesAutoresizingMaskIntoConstraints = false

        addSubview(backgroundImageView)
        sendSubviewToBack(backgroundImageView)

        // adding NSLayoutConstraints
        let leadingConstraint = NSLayoutConstraint(item: backgroundImageView, attribute: .leading, relatedBy: .equal, toItem: self, attribute: .leading, multiplier: 1.0, constant: 0.0)
        let trailingConstraint = NSLayoutConstraint(item: backgroundImageView, attribute: .trailing, relatedBy: .equal, toItem: self, attribute: .trailing, multiplier: 1.0, constant: 0.0)
        let topConstraint = NSLayoutConstraint(item: backgroundImageView, attribute: .top, relatedBy: .equal, toItem: self, attribute: .top, multiplier: 1.0, constant: 0.0)
        let bottomConstraint = NSLayoutConstraint(item: backgroundImageView, attribute: .bottom, relatedBy: .equal, toItem: self, attribute: .bottom, multiplier: 1.0, constant: 0.0)

        NSLayoutConstraint.activate([leadingConstraint, trailingConstraint, topConstraint, bottomConstraint])
    }
}

Note that the updates for this answer are:

  • Swift 4 code
  • Adding -programatically- NSLayoutConstraints: that's because when applying what's mentioned in my previous answer, it works fine for the current device orientation, but not when the application does support both portrait/landscape modes, if the device orientation has been changed, the background imageView size will be the same (same size) and not adapts the new width/height of the device screen, so adding constraints should solve this issue.
  • Adding default parameters: for more flexibility, you might -sometimes- want to change the default image or even the context mode for you background:

Usage:

Assuming that you want to call it in viewDidLoad():

override func viewDidLoad() {
    //...

    // you can call 4 versions of addBackground() method

    // 1- this will add it with the default imageName and default contextMode
    view.addBackground()

    // 2- this will add it with the edited imageName and default contextMode
    view.addBackground(imageName: "NEW IMAGE NAME")

    // 3- this will add it with the default imageName and edited contextMode
    view.addBackground(contentMode: .scaleAspectFit)

    // 4- this will add it with the default imageName and edited contextMode
    view.addBackground(imageName: "NEW IMAGE NAME", contextMode: .scaleAspectFit)
}
Ahmad F
  • 30,560
  • 17
  • 97
  • 143
  • Great contribution! However, there is one bug: the internal name should be contentMode not ContextMode. So the function should be this: `func addBackground(imageName: String = "YOUR DEFAULT IMAGE NAME", contentMode: UIViewContentMode = .scaleToFill)` whereas before you had this: `func addBackground(imageName: String = "YOUR DEFAULT IMAGE NAME", contextMode: UIViewContentMode = .scaleToFill)` – Adam Mar 03 '18 at 02:09
3

Here are your options for scaling!

For the .contentMode property:

ScaleToFill This will scale the image inside the image view to fill the entire boundaries of the image view.

ScaleAspectFit This will make sure the image inside the image view will have the right aspect ratio and fit inside the image view’s boundaries.

ScaleAspectFill This will make sure the image inside the image view will have the right aspect ratio and fill the entire boundaries of the image view. For this value to work properly, make sure that you have set the clipsToBounds property of the imageview to true.

class SecondViewController : UIViewController {

    let backgroundImage = UIImage(named: "centralPark")
    var imageView: UIImageView!

    override func viewDidLoad() {
        super.viewDidLoad()
        self.thirdChoiceField.delegate = self
        self.datePicker.minimumDate = NSDate()
        imageView = UIImageView(frame: view.bounds)
        imageView.contentMode = .ScaleAspectFill
        imageView.clipsToBounds = true
        imageView.image = backgroundImage
        imageView.center = view.center
        view.addSubview(imageView)
        self.view.sendSubviewToBack(imageView)
Arunabh Das
  • 13,212
  • 21
  • 86
  • 109
MacInnis
  • 760
  • 9
  • 19
3

me showing my answer as which Lines of code helps me...

extension file code ....

    extension UIView {
        func addBackground() {
            let width = UIScreen.main.bounds.size.width
            let height = UIScreen.main.bounds.size.height

            let imageViewBackground = UIImageView(frame: CGRect(x: 0, y: 0, width: width, height: height))
            imageViewBackground.image = UIImage(named: "Your Background Image Name")

            imageViewBackground.contentMode = .scaleAspectFill

            self.addSubview(imageViewBackground)
            self.sendSubviewToBack(imageViewBackground)
        }
    }

and in view controller file....

    override func viewDidLoad() {
        super.viewDidLoad()
        view.addBackground()
    
    }

Thank You Guys !

axy
  • 141
  • 9
2

Ahmad Fayyas Solution in Swift 3.0:

func addBackground() {
    let width = UIScreen.main.bounds.size.width
    let height = UIScreen.main.bounds.size.height

    let imageViewBackground = UIImageView(frame: CGRect(x:0, y:0, width: width, height: height))
    imageViewBackground.image = UIImage(named: "YOUR IMAGE NAME GOES HERE")

    // you can change the content mode:
    imageViewBackground.contentMode = UIViewContentMode.scaleAspectFill

    self.view.addSubview(imageViewBackground)
    self.view.sendSubview(toBack: imageViewBackground)
}
  • 1
    Thank you for your effort! Please check my [improved answer](https://stackoverflow.com/questions/27153181/how-do-you-make-a-background-image-scale-to-screen-size-in-swift/41581146#41581146) :) – Ahmad F Nov 04 '17 at 12:18
1

This uses PureLayout. You could just use AutoLayout with a few more lines.

UIImageView* imgView = UIImageView(image: myUIImage)
imgView.setTranslatesAutoresizingMaskIntoConstraints(false)
self.view.addSubview(imgView)
self.view.addConstraints(imgView.autoPinEdgesToSuperviewEdgesWithInsets(UIEdgeInsetsMake(0,0,0,0))
Stephen Johnson
  • 5,293
  • 1
  • 23
  • 37
  • 1
    FYI - you don't need to call `addConstraints` with PureLayout -- constraints are automatically installed (activated) by default. The code above will actually double-add the constraints. – smileyborg Dec 02 '14 at 23:58
  • Thanks for the info! That makes the API a lot cleaner. – Stephen Johnson Dec 03 '14 at 16:48
1

I used constraints to make the image "autoLayout". I made a view to show an activity indicator (with full background image), while the view on segue is loading. The code is as follows.

var containerView: UIView = UIView()
var actionIndicator: UIActivityIndicatorView = UIActivityIndicatorView()

private func showActivityIndicator() {
    ///first I set the containerView and the background image
    containerView.translatesAutoresizingMaskIntoConstraints = false
    self.view.addSubview(containerView)
    adjustConstFullSize(containerView, parentView: self.view)
    let backImage = UIImageView(image: UIImage(named: "AppBackImage"))
    backImage.contentMode = UIViewContentMode.ScaleAspectFill
    backImage.translatesAutoresizingMaskIntoConstraints = false
    containerView.addSubview(backImage)
    adjustConstFullSize(backImage, parentView: containerView)

    ////setting the spinner (activity indicator)
    actionIndicator.frame = CGRectMake(0.0, 0.0, 40.0, 40.0)
    actionIndicator.center = CGPointMake(containerView.bounds.size.width / 2, containerView.bounds.size.height / 2)
    actionIndicator.hidesWhenStopped = true
    actionIndicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyle.WhiteLarge
    containerView.insertSubview(actionIndicator, aboveSubview: backImage)

    ///throw the container to the main view
    view.addSubview(containerView)
    actionIndicator.startAnimating()
}

This is the code for the "adjustConstFullSize" function.

func adjustConstFullSize(adjustedView: UIView!, parentView: UIView!) {
    let topConstraint = NSLayoutConstraint(item: adjustedView,
        attribute: .Top,
        relatedBy: .Equal,
        toItem: parentView,
        attribute: .Top,
        multiplier: 1.0,
        constant: 0.0)

    let leftConstraint = NSLayoutConstraint(item: adjustedView,
        attribute: .Leading,
        relatedBy: .Equal,
        toItem: parentView,
        attribute: .Leading,
        multiplier: 1.0,
        constant: 0.0)

    let rightConstraint = NSLayoutConstraint(item: adjustedView,
        attribute: .Trailing,
        relatedBy: .Equal,
        toItem: parentView,
        attribute: .Trailing,
        multiplier: 1.0,
        constant: 0.0)


    let bottomConstraint = NSLayoutConstraint(item: adjustedView,
        attribute: .Bottom,
        relatedBy: .Equal,
        toItem: parentView,
        attribute: .Bottom,
        multiplier: 1.0,
        constant: 0.0)

    parentView.addConstraints([topConstraint, leftConstraint, rightConstraint, bottomConstraint])
}

In the function shown above, I "tied" the containerView constraints to the main view constraints, making the view "full size". I did the same for the UIImageView and also set the contentMode to AspectFill - this is crucial, because we want the image to fill the content without stretching.

To remove the view, after the lazy loading, just use the code below.

private func hideActivityIndicator() {
    actionIndicator.stopAnimating()
    containerView.removeFromSuperview()
}
Pablo
  • 361
  • 3
  • 6
0

For this, I think you'll need to create a UIImageView that is pinned to the parent views top / bottom / left / right. This will make the UIImageView always the match the size of the display. Just make sure you set the content mode on the imageview to be AspectFit

var newImgThumb : UIImageView
newImgThumb = UIImageView(view.bounds)
newImgThumb.contentMode = .ScaleAspectFit
view.addSubview(newImgThumb)

//Don't forget this line
newImgThumb.setTranslatesAutoresizingMaskIntoConstraints(false)

NSDictionary *views =NSDictionaryOfVariableBindings(newImgThumb);


// imageview fills the width of its superview
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"|[newImgThumb]|" options:0 metrics:metrics views:views]];
// imageview fills the height of its superview
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[newImgThumb]|" options:0 metrics:metrics views:views]];
wottle
  • 13,095
  • 4
  • 27
  • 68
0

`

CGRect screenRect = [[UIScreen mainScreen] bounds];

CGFloat screenWidth = screenRect.size.width;

CGFloat screenHeight = screenRect.size.height;

_imgBackGround.frame = CGRectMake(0, 0, screenWidth, screenHeight);`