renderInContext does not work correctly when changing layer Z position

My application allow user to switch UIImageView back and front and then user can capture that screen. Here is my code to capture the screen into UIImage

-(UIImage *)imageWithView:(UIView *)view
{
   UIGraphicsBeginImageContextWithOptions(view.bounds.size, view.opaque, 2.0f);

// I even tried view.layer.presentationLayer but still not working
[view.layer renderInContext:UIGraphicsGetCurrentContext()];

UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();


return image;

}

I do not use [view drawViewHierarchyInRect:view.bounds afterScreenUpdates:YES] because it is slower and sometimes (when view is not visible) drawn the screenshot in black.

But problem with renderInContext is the Z position that change between UIImageView ( imageView.layer.zPosition = 0.01;etc ). In my iPhone screen this work correctly when I assigned value to zPosition but in the capture screen it turns out wrong.

Are there anyway I can resolve this problem ? Thanks in advance

Edited: Here is what I tried to do before capture the screenshot. I use this code to make one ImageView display in front of another one.

-(void)bringOneLevelUp:(UIImageView*)imageView
{
//_imgArray is sorted by Z position order (small to big)
    NSUInteger currentObjectIndex = [_imgArray indexOfObject:imageView];


if(currentObjectIndex+1< _imgArray.count){

UIImageView *upperImageView = [_imgArray objectAtIndex:currentObjectIndex+1];


    CGFloat currentZIndex = imageView.layer.zPosition;
    CGFloat upperZIndex= upperImageView.layer.zPosition;

    imageView.layer.zPosition = upperZIndex;
    upperImageView.layer.zPosition = currentZIndex;


// swap position in array 
[_imgArray exchangeObjectAtIndex:currentObjectIndex withObjectAtIndex:currentObjectIndex+1];

}

}

And liked I explained earlier the result of this code in the phone screen is correct. The newImageView is in front of lastImageView. But when I captured screenshot by renderInContext. They are not.

I had this issue as well. I wanted text to draw on top of an image after using renderInContext(). I solved this by positioning my views when adding them to the window rather than using the layer to set the z-position.

I used to have a text field that would set its z-position upward:

layer?.zPosition = 1

I removed this code and instead, when adding my image to the window, I used:

addSubview(image, positioned: .Below, relativeTo: nil)

This solved the problem.

ios, But problem with renderInContext is the Z position that change between UIImageView ( imageView.layer.zPosition = 0.01;etc ) . In my iPhone  The OS X v10.5 implementation of this method does not support the entire Core Animation composition model. QCComposition Layer, CAOpen GLLayer, and QTMovie Layer layers are not rendered. Additionally, layers that use 3D transforms are not rendered, nor are layers that specify background Filters, filters, compositing Filter, or a mask values. Future versions of macOS may add support for rendering these layers and properties.

I faced the same issue and its a bummer.

I know this question was asked about 2 years ago, so heres the answer anyway if it helps anyone incase

So changing subviews zPosition renders perfectly fine in the app but in fact affects the renderByContext when used to create a screenshot. I don't know why, I assume it's a bug.

So in order to get the screenshot to appear correctly as it renders in the app, we need to manually call the renderByContext on all subviews in the correct order as specified by zPosition.

    UIGraphicsBeginImageContext(self.view.frame.size);
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    [self renderInContext:ctx];

    UIImage *screenShotImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

and

-(void) renderInContext:(CGContextRef)ctx {
    CGContextBeginTransparencyLayer(ctx, NULL);
    //self.layers is a desc ordered list of views based on its zPosition
    for(UIView *view in self.layers){ 
        [view.layer renderInContext:ctx];
    }
    CGContextEndTransparencyLayer(ctx);
}

Improve z-index implementation on iOS · Issue #14011 · facebook , But problem with renderInContext is the Z position that change between UIImageView ( imageView.layer.zPosition = 0.01;etc ). In my iPhone screen this work  renderInContext does not work correctly when changing layer Z position. My application allow user to switch UIImageView back and front and then user can capture that screen. I do not use [view drawViewHierarchyInRect:view.bounds afterScreenUpdates:YES] because it is slower and sometimes (when view is not visible) drawn the screenshot in black.

Swift 4.2

The answer of @RameshVel worked for me translating it to Swift, maybe someone needs this:

 UIGraphicsBeginImageContext(drawingCanvas.frame.size)
 self.renderInContext(ct: UIGraphicsGetCurrentContext()!)

 guard let image = UIGraphicsGetImageFromCurrentImageContext() else {return}
 UIGraphicsEndImageContext()

And in the renderInContext function:

 func renderInContext(ct:CGContext){

    ct.beginTransparencyLayer(auxiliaryInfo: nil)

    // descendant ordered list of views based on its z-position
    let orderedLayers = self.view.subviews.sorted(by: {
        $0.layer.zPosition < $1.layer.zPosition
    })

    for l in orderedLayers {
        l.layer.render(in: ct)
    }
    ct.endTransparencyLayer()
}

The same can be donde with CALayers if you are drawing and adding layers:

 UIGraphicsBeginImageContext(drawingCanvas.frame.size)
 //Canvas is a custom UIView for drawing
 self.renderInContext(ct: UIGraphicsGetCurrentContext()!, canvas: canvas)

 guard let image = UIGraphicsGetImageFromCurrentImageContext() else {return}
 UIGraphicsEndImageContext()

renderInContext function:

func renderInContext(ct:CGContext, canvas:CustomCanvas){

    ct.beginTransparencyLayer(auxiliaryInfo: nil)
    let layers:[CALayer] = canvas.layer.sublayers!

    let orderedLayers = layers.sorted(by: {
        $0.zPosition < $1.zPosition
    })

    for v in orderedLayers {
        v.render(in: ct)
    }
    ct.endTransparencyLayer()
}

Mask problem with renderInContext of CALayer · Issue #12 , zPosition and takes z-index in consideration when we check what /​renderincontext-does-not-work-correctly-when-changing-layer-z-position. The only thing that seems to work is to change the Z points of each line. Way to tedious. When globally selecting the line in properties the pull down only says Varies and does not seem to allow globally projecting Z points to XY. Thanks for any links on how to flatten or project onto the XY.

This is an annoying bug of Apple's, but the solution is easy, simply re-order the view you are snapshotting's subviews (and their subviews (and so on)) recursively, based on their zPositions, using a comparator.

Just call the following method, passing the view you are about to snapshot, directly before snapshotting it.

///UIGraphicsGetCurrentContext doesn't obey layer zPositions so have to adjust view heirarchy (integer index) to match zpositions (float values) for all nested subviews.
-(void)recursivelyAdjustHeirarchyOfSubviewsBasedOnZPosition:(UIView *)parentView {

    NSArray *sortedSubviews = [[parentView subviews] sortedArrayUsingComparator:
                           ^NSComparisonResult(UIView *view1, UIView *view2)
                           {
                               float zpos1 = view1.layer.zPosition;
                               float zpos2 = view2.layer.zPosition;
                               return zpos1 > zpos2;
                           }];

    for (UIView *childView in sortedSubviews) {
        [parentView bringSubviewToFront:childView];
        [self recursivelyAdjustHeirarchyOfSubviewsBasedOnZPosition:childView];
    }

}

Re: CALayer renderInContext changes zPosition of some child layers, When using renderInContext method of CALayer the mask layers are I know the real problem is that renderInContext does not support mask layer -- but is th. I am open to any ideas on how to change the way the masking  You can not only change the Z offset in the slicer or in the configuration of Marlin, but also with G-code commands. The "paper drag" method is perfect for determining the correct Z level. Once you leveled with the paper, you do not need to create an offset to account for the paper thickness, however, there are purists that do that.

CALayer renderInContext changes zPosition of some child layers, renderInContext does not work correctly when changing layer Z position. My application allow user to switch UIImageView back and front and then user can  The stacking context is a three-dimensional conceptualization of HTML elements along imaginary z-axis relative to the user, who is assumed to be facing the viewport or the webpage. HTML elements occupy this space in priority order based on element attributes. In the previous part of this article, Using z-index, the rendering order of certain

Calayer speed, Almost everything renders correctly when I do this: > > [[view layer] missing layers are not missing but somehow their zPosition got messed up so they This is probably a bug, but your best work around would be to sort the  Current Sleep Number bed models. Past Sleep Number bed models. TV Shopping Bed Assembly Guides. Warranty information.

(the context is set up correctly and produces the expected result - an layers are not missing but somehow their zPosition got messed up so  If I remember correctly, it has something to do with the OSNAP command. Basically: I need the Z-axis to have the same autolock that moving objects along the X and Y axis has. And if you could also recommend a way to make this the default setting so I could just open a new .dwg file and not have to repeat the steps, I would love you forever.

Comments
  • What does "turns out wrong" mean? What z-position values are you trying?
  • I swapped z position of UIImageView. It looks correct in the phone screen but not when I tried capturing it.
  • I don't really understand exactly what your code is doing. Why haven't you shown it in your question?
  • I have added the code you asked for. But it has nothing to do. The problem is renderInContext does not capture the zPosition of the view layer. And I tried using layer.presentationLayer. But it is still not working correctly