GuiGui23
GuiGui23

Reputation: 4075

How do you make a background image scale to screen size in swift?

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?

Upvotes: 38

Views: 101409

Answers (10)

axy
axy

Reputation: 307

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 !

Upvotes: 3

Ahmad F
Ahmad F

Reputation: 31645

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)
}

Upvotes: 17

ADoorMarkedPirate
ADoorMarkedPirate

Reputation: 400

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)
}

Upvotes: 2

Robert William Clancy
Robert William Clancy

Reputation: 47

`

CGRect screenRect = [[UIScreen mainScreen] bounds];

CGFloat screenWidth = screenRect.size.width;

CGFloat screenHeight = screenRect.size.height;

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

Upvotes: 0

Ahmad Fayyas
Ahmad Fayyas

Reputation: 441

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()
}

Upvotes: 44

Pablo
Pablo

Reputation: 391

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()
}

Upvotes: 1

MacInnis
MacInnis

Reputation: 758

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)

Upvotes: 3

Leo Dabus
Leo Dabus

Reputation: 236260

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

Upvotes: 27

wottle
wottle

Reputation: 13619

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]];

Upvotes: 0

Stephen Johnson
Stephen Johnson

Reputation: 5121

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))

Upvotes: 1

Related Questions