子视图的子层与更高的子视图重叠 [英] Subview's sublayers overlapping higher subviews

查看:22
本文介绍了子视图的子层与更高的子视图重叠的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个问题:我正在创建一个从方法返回的 UIView,这部分很好,但我注意到当我向其中一个添加子层时子视图,这些层与层次结构中较高的子视图(textView 和 imageView)重叠,添加到 testViewCopy 的子层出现在这些子视图的顶部,它们不应该出现.我不知道是什么原因导致了这种情况.

I have an issue: I'm creating a UIView that is returned from a method, and that part is fine, but what I've noticed is that when I add sublayers to one of the subviews, those layers overlap subviews that are higher up in the hierarchy (textView and imageView) the sublayers added to testViewCopy are appearing over top of these subviews, and they aren't supposed to. I have no idea what's going on here to cause this.

代码:

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

推荐答案

您的代码运行正常.所有兄弟视图 - 一个公共超级视图的子视图 - 都有一个明确的分层顺序,从后到前.addSubview: 添加子视图作为其兄弟视图中的最后;因此,它位于同一父视图的所有现有子视图之前.如果这不是您想要的,请将子视图插入到从前面向后的另一层,或添加它(在前面),然后按分层顺序向后移动.

Your code is behaving correctly. All sibling views - subviews of a common superview - have a definite layering order, back to front. addSubview: adds the subview as the last among its siblings; thus, it is layered in front of all existing subviews of the same superview. If that isn't what you want, insert the subview at a further layer back from the front, or add it (at the front) and then move it further back in the layering order.

此外(在这里我认为我们越来越接近您注意到的特定现象),视图本身只是层.因此,视图的分层顺序实际上是层的分层顺序的子集.我刚才说的关于视图的同样的事情对于层也同样适用,因为视图层:如果你将一个子层添加到一个超级层,它会被添加到该超级层的所有其他子层之前,包括任何子视图,如果该超级层实际上是一个视图.

Moreover (and here I think we are getting closer to the particular phenomenon you have noticed), views are themselves just layers. Thus, the layering order of views is actually a subset of the layering order of layers. The same thing I just said about views is equally true of layers, because views are layers: if you add a sublayer to a superlayer, it is added in front of all other sublayers of that superlayer, including any subviews if that superlayer is actually a view.

正如我在当前版本的书中所写:

As I write in the current edition of my book:

视图的子视图的底层是该视图的底层的子层,就像该视图底层的任何其他子层一样.因此,它可以按绘制顺序放置在它们之间的任何位置.视图可以散布在其父视图底层的子层之间这一事实令初学者感到惊讶.

A view's subview's underlying layer is a sublayer of that view's underlaying layer, just like any other sublayers of that view's underlying layer. Therefore, it can be positioned anywhere among them in the drawing order. The fact that a view can be interspersed among the sublayers of its superview's underlying layer is surprising to beginners.

听起来您刚刚发现了这一点,并且感到很惊讶.

It sounds like you've just discovered this, and are appropriately surprised.

从活跃的术语中渲染树的绘制来考虑它可能会有所帮助.换句话说,与其考虑事物的外观,不如考虑 iOS 做什么.一个层可以有一个超层,除了最终的超层,一个层可以有一个以前的兄弟,除了超层的第一个子层.相反,一个层可以有子层,也可以有下一个兄弟层.我们首先绘制最终的超级层(窗口).然后,对于我们刚刚绘制的每一层,依次遵循以下两条规则:

It may help to think of it in terms of the drawing of the render tree, in active terms. In other words, instead of thinking about how things look, think about what iOS does. A layer can have a superlayer, except for the ultimate superlayer, and a layer can have a previous sibling, except for the first sublayer of a superlayer. Conversely, a layer can have sublayers and it can have next siblings. We start by drawing the ultimate superlayer (the window). Then, for every layer we have just drawn, follow these two rules in order:

  • 绘制它的第一个子层,如果有的话.

  • Draw its first sublayer, if any.

绘制它的下一个兄弟,如果有的话.

Draw its next sibling, if any.

每次我们绘制一个图层时,它都位于我们之前绘制的一切的前面.因此,一个超层的所有子层都出现在该超层的前面,所有较晚的兄弟(及其子层)出现在所有先前的兄弟(及其子层)之前.这将导致您在屏幕上看到的内容.

Every time we draw a layer, it is in front of everything we have previously drawn. Thus all sublayers of a superlayer appear in front of the superlayer, and all later siblings (and their sublayers) appear in front of all previous siblings (and their sublayers). This results in what you see on the screen.

(但是,请注意,您具有更大的灵活性,因为在兄弟姐妹中,您可以通过设置图层的 zPosition 属性来操纵绘制顺序,而无需重新排列兄弟姐妹.)

(However, note that you have even more flexibility, because among siblings you can manipulate the drawing order without rearranging the siblings, by setting the zPosition property of a layer.)

这篇关于子视图的子层与更高的子视图重叠的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆