Subview sublayers overlap higher subviews

I have a problem: I am creating UIView

which is returned from the method and this part is fine, but I noticed that when I add sublayers to one of the subzones, these layers overlap the subviews that are higher in the hierarchy (textView and imageView), the subwords added in testViewCopy

, appear on top of these subzones, and they shouldn't. I don't know what's going on here to cause this.

code:

- (void)makeShareImages
{
    UIView *shareView = [self shareView];

    UIView *testViewCopy = [shareView viewWithTag:0];

    NSUInteger currentIndex = 1;

    for (NSDictionary *sub in self.array)
    {
        NSArray *lastArray = [sub objectForKey:@"LastArray"];

        for (NSDictionary *dict in lastArray)
        {
            @autoreleasepool
            {
                currentIndex ++;

                CircleLayer *layer = [[CircleLayer alloc]init];
                layer.portrait = [[dict objectForKey:@"Portrait"]boolValue];

                layer.frame = testViewCopy.bounds;

                [testViewCopy.layer addSublayer:layer];

                NSData *frameData = [self getSnapshotDataFromView:shareView];

                NSString *savePath = [NSString stringWithFormat:@"%@/%lu.png",somePath,(unsigned long)currentIndex];

                [frameData writeToFile:savePath options:0 error:nil];
            }
        }
    }
}

- (UIView *)shareView
{
    UIColor *bgColor = self.containerView.backgroundColor;

    CGSize size = self.containerView.bounds.size;

    UIView *viewToShare = [[UIView alloc]init];
    viewToShare.backgroundColor = bgColor;
    viewToShare.layer.cornerRadius = 6.0;
    viewToShare.layer.masksToBounds = YES;

    UIView *testViewCopy = [[UIView alloc]init];
    testViewCopy.backgroundColor = [UIColor clearColor];
    testViewCopy.contentMode = UIViewContentModeScaleAspectFit;
    testViewCopy.layer.masksToBounds = YES;
    testViewCopy.tag = 0;

    UITextView *textViewCopy = [[UITextView alloc]init];
    textViewCopy.backgroundColor = [UIColor clearColor];
    textViewCopy.tag = 1;
    textViewCopy.textContainerInset = self.textView.textContainerInset;

    UIImageView *profileImageViewCopy = [[UIImageView alloc]initWithFrame:CGRectMake(2, 2, 32, 32)];
    profileImageViewCopy.contentMode = UIViewContentModeScaleAspectFit;
    profileImageViewCopy.layer.masksToBounds = YES;
    profileImageViewCopy.image = [self profileImage];
    profileImageViewCopy.tag = 2;
    profileImageViewCopy.layer.cornerRadius = profileImageViewCopy.frame.size.width / 2.0;

    viewToShare.frame = CGRectMake(0, 0, size.width, size.height);
    testViewCopy.frame = CGRectMake(0, 0, size.width, size.width);
    textViewCopy.frame = CGRectMake(0, 0, size.width, size.height);

    NSAttributedString *attributedStringCopy = [[NSAttributedString alloc]initWithAttributedString:self.textView.attributedText];

    textViewCopy.attributedText = attributedStringCopy;

    [viewToShare addSubview:testViewCopy];
    [viewToShare addSubview:textViewCopy];
    [viewToShare addSubview:profileImageViewCopy];

    return viewToShare;
}

- (NSData *)getSnapshotDataFromView:(UIView *)view
{
    UIGraphicsBeginImageContextWithOptions(view.bounds.size, NO, 0.0);
    [view.layer renderInContext:UIGraphicsGetCurrentContext()];
    UIImage *snapShot = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return UIImagePNGRepresentation(snapShot);
}

      

+3


source to share


1 answer


Your code is behaving correctly. All the views of brothers and sisters - forgeries of general supervision - have a certain order of superposition, from front to back. addSubview:

adds subview as the last among its siblings; thus, it overlaps in front of all existing areas of the same supervisor. If that's not what you want, paste the subview on another layer backwards or add it (in front) and then move it even further in the ordering order.

Also (and here I think we're getting closer to a specific phenomenon that you noticed), the views themselves are just layers. So the display order of the layers is actually a subset of the layers of the layers. The same thing I just said about views applies equally to layers, since views are layers: if you add a sublevel to a super layer, it is added before all other sub layers of that super layer, including any sub layers if that super layer is actually view.

As I write in the current edition of my book:

The subview layer is a sub-layer of this subclass layer, just like any other sub-layers of this layer. Therefore, it can be positioned anywhere in between in the drawing order. The fact that a species can be interspersed among sub-layers of its surveillance level is surprising to novices.

enter image description here



It looks like you just discovered this and was pleasantly surprised.

It might help to think about it in terms of drawing the render tree in active expressions. In other words, instead of thinking about what things look like, think about what iOS does. A layer can have a super layer in addition to the final super layer, and a layer can have a previous sibling except for the first sub layer of the super layer. Conversely, a layer can have sublayers and it can have the following siblings. Let's start by drawing the final super layer (window). Then, for each layer we just painted, follow these two rules:

  • Draw your first sublevel, if any.

  • Draw your next brother, if any.

Every time we draw a layer, it sits in front of everything we drew earlier. Thus, all sublayers of the superlayer appear before the superlayer, and all subsequent siblings (and their sublayers) appear in front of all previous siblings (and their sublayers). This results in what you see on the screen.

(However, note that you have even more flexibility, because among siblings, you can control the drawing order without re-setting the siblings by setting a property zPosition

on the layer.)

+6


source







All Articles