Tiled Background Image: Can I do that easily with UIImageView?
Asked Answered
S

7

65

I have a fullscreen background image that is tiled, i.e. it has to be reproduced a few times horizontally and vertically in order to make a big one. Like in the browsers on ugly home pages ;)

Is UIImageView my friend for this?

Stannwood answered 14/7, 2009 at 13:1 Comment(0)
M
104

If I understand your question correctly you can use colorWithPatternImage: on UIColor then set the background color on a UIView.

If you must use a UIImageView you can do the same but whatever image you place in the image view will draw in front of the tiled image.

Milissa answered 14/7, 2009 at 13:4 Comment(7)
Thanks! Well what I want to do is: I have an image file with a pattern, that can be repeated vertically and horizontally. I want to repeat this image pattern on my screen. Maybe it saves some memory.Stannwood
If you use the UIColor method outlined you will get your screen filled with the pattern image. There are more complex ways but from your description this should work.Milissa
Hi, this works, but the Alpha of the Image doesn't work. :( Any solutionsBargeman
[[UIColor colorWithPatternImage:...] colorWithAlphaComponent:...]Sasser
Can we set the colorWithPatternImage through xib rather than through coding?Undertrump
@JimThio Nope, you have to do it with code. If I'm wrong someone please comment.Pileate
For years I was doing it this way (colorWithPatternImage:) but Apple has fixed this in iOS6 to add the missing feature. And there's a way to make it work on iOS5 etc - c.f. answer belowLaceylach
H
30

To get alpha to work with pattern image, make sure you have the following set:

view.backgroundColor = [UIColor colorWithPatternImage:aImage];
view.layer.opaque = NO;
Hudspeth answered 3/1, 2011 at 22:30 Comment(2)
The last two lines of this snippet the same thing.Sasser
view.layer.opaque = NO; prevailsCladoceran
O
21

In WWDC 2018 video session 219 - Image and Graphics Best Practices, Apple engineer explicitly recommends not to use the pattern color for tiling backgrounds:

I recommend not using patterned colors with a background color property on UIView. Instead, create a UIImageView. Assign your image to that image view. And use the functions on UIImageView to set your tiling parameters appropriately.

So the best and simplest way to create a tiled background would be like this:

imageView.image = image.resizableImage(withCapInsets: .zero, resizingMode: .tile)

Or even simpler, if you use asset catalog – select your pattern image asset and, in the Attributes inspector, enable Slicing (Horizontal/Vertical or both), set the insets to zero, and width/height to the dimensions of your image:

then simply assign this image to your image view (Interface Builder works, too), just don't forget to set the UIImageView's contentMode to .scaleToFill.

Optative answered 1/4, 2019 at 16:3 Comment(3)
This one didn't work for me when I used vertical slicing with a top inset of 0. Xcode 11.3.1 (11C505). I submitted a bug report for that.Burtburta
Hmm, strange, it shows correctly in IB but on the device is shows default scaleToFill :/Coccyx
Update: This was because devices and simulators apparently cache the launch screen/images (even after reinstalling). It worked on another device.Coccyx
L
17

For years I used Bill Dudney's approach, but iOS 6 has a much better solution. And ... today I found a way to make this work on old versions of iOS too.

  1. create the new class "UIImage+Tileable" (copy/paste source below)
  2. import this in any class where you want a UIImageView with tileable image. It's a category, so it "upgrades" all your UIImage's into tileable ones, using standard Apple calls
  3. when you want a "tiling" version of an image, call: "image = [image imageResizingModeTile]"

UIImage+Tileable.h

#import <UIKit/UIKit.h>

@interface UIImage (Tileable)

-(UIImage*) imageResizingModeTile;

@end

UIImage+Tileable.m

#import "UIImage+Tileable.h"

@implementation UIImage (Tileable)

-(UIImage*) imageResizingModeTile
{
    float iOSVersion = [[[UIDevice currentDevice] systemVersion] floatValue];

    if( iOSVersion >= 6.0f )
    {
        return [self resizableImageWithCapInsets:UIEdgeInsetsZero resizingMode:UIImageResizingModeTile];
    }
    else
    {
        return [self resizableImageWithCapInsets:UIEdgeInsetsZero];
    }
}
@end
Laceylach answered 10/5, 2013 at 10:38 Comment(3)
Nice solution, any idea to use this for iOS 4?Amphora
I thought this worked on iOS 4+, sorry. It definitely works on 5+. Test with 5 and make sure it's not something else that's wrong (I had a few subtle bugs first time I did this). If it works on 5 but not 4, you'll have to write your own tiling code (this takes about 15 minutes to write and debug: make a custom UIView that draws a grid of UIImageViews ... or even better, make a custom CALayer that implements the drawInContext call and splats a raw CGImage multiple times)Laceylach
Well, it does not work on <5.0. Nice solution, but I did go for [UIColor colorWithPatternImage:...] then.Amphora
F
8

I use a variation of @Rivera's solution:

Put the following in a UIView extension:

- (void)setColorPattern:(NSString *)imageName
{
    [self setBackgroundColor:[UIColor colorWithPatternImage:[UIImage imageNamed:imageName]]];
}

Then you can set the background pattern in the storyboard/xib file: Image showing how to set the colorPattern in the storyboard/xib

Frawley answered 29/4, 2015 at 19:58 Comment(1)
This is a great solution but note that it will not work in a Launch Screen xib file. "error: Launch screens may not use user defined runtime attributes.".Jari
C
4

As I really like Interface Builder I created this UIImageView subclass to apply tiled backgrounds:

@interface PETiledImageView : UIImageView

@end

@implementation PETiledImageView

- (void)awakeFromNib
{
    [super awakeFromNib];

    UIImage * imageToTile = self.image;
    self.image = nil;
    UIColor * tiledColor = [UIColor colorWithPatternImage:imageToTile];
    self.backgroundColor = tiledColor;
}

@end

I tried overriding setImage: but it seems IB doesn't call it when decoding a Nib file.

Castello answered 10/6, 2014 at 2:28 Comment(0)
S
0

Swift version of Daniel T's solution. You still need to set the keyPath value in IB. Of course you could be more careful unwrapping the Optional UIImage.

extension UIView {
    var colorPattern:String {
        get {
            return ""  // Not useful here.
        }
        set {
            self.backgroundColor = UIColor(patternImage: UIImage(named:newValue)!)
        }
    }
}
Superdreadnought answered 23/11, 2016 at 21:7 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.