Search code examples
iosuiimageviewuiimagecalayersubview

add UIImage in CALayer


I must add a UIImageView as subview of MapView. To do this I created a layer above the MapView. In this layer I want to put my image, but I get a white rectangle and nothing else. My image is not visible.

This is the code:

- (void)viewDidLoad
{
    //......

    CALayer *layer = [CALayer layer];
    layer.backgroundColor = [[UIColor whiteColor] CGColor];

    if(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone)
    {
        layer.bounds = CGRectMake(self.mapView.bounds.origin.x,
                                  self.mapView.bounds.origin.y, 80, 300);
    }
    else
    {
        layer.bounds = CGRectMake(self.mapView.frame.origin.x,
                                  self.mapView.frame.origin.y, 150, 700);
    }

    layer.contents = (id)[UIImage imageNamed:@"myImage.png"];
    //the name is correct but  in the output the image is not visible

    [[self.mapView layer] addSublayer:layer];
    [layer setNeedsDisplay];
}

Solution

  • This is a general answer for the sake of future viewers. It is based on the question title rather than the details of the original question.

    How to add a UIImage to a CALayer

    You can add an image to a view's layer simply by using its contents property:

    myView.layer.contents = UIImage(named: "star")?.cgImage
    
    • Note that the UIImage needs to be converted to a CGImage.

    If you wish to add the image in its own layer, you can do it like this:

    let myLayer = CALayer()
    let myImage = UIImage(named: "star")?.cgImage
    myLayer.frame = myView.bounds
    myLayer.contents = myImage
    myView.layer.addSublayer(myLayer)
    

    Modifying the appearance

    The above code produces a view like this. The light blue is the UIView and the dark blue star is the UIImage.

    enter image description here

    As you can see, though, it looks pixelated. This is because the UIImage is smaller than the UIView so it is being scaled to fill the view, which is the default it you don't specify anything else.

    The examples below show variations on the layer's contentsGravity property. The code looks like this:

    myView.layer.contents = UIImage(named: "star")?.cgImage
    myView.layer.contentsGravity = kCAGravityTop
    myView.layer.isGeometryFlipped = true
    

    In iOS, you may want to set the isGeometryFlipped property to true if you are doing anything with top or bottom gravity, otherwise it will be the opposite of what you expect. (Only the gravity is flipped vertically, not the content rendering. If you are having trouble with the content being flipped, see this answer.)

    There are two UIView examples below for every contentsGravity setting, one view is larger than the UIImage and the other is smaller. This way you can see the effects of the scaling and gravity.

    kCAGravityResize

    This is the default.

    enter image description here

    kCAGravityResizeAspect

    enter image description here

    kCAGravityResizeAspectFill

    enter image description here

    kCAGravityCenter

    enter image description here

    kCAGravityTop

    enter image description here

    kCAGravityBottom

    enter image description here

    kCAGravityLeft

    enter image description here

    kCAGravityRight

    enter image description here

    kCAGravityTopLeft

    enter image description here

    kCAGravityTopRight

    enter image description here

    kCAGravityBottomLeft

    enter image description here

    kCAGravityBottomRight

    enter image description here

    Related