重新排序 UIView 子视图

Posted

技术标签:

【中文标题】重新排序 UIView 子视图【英文标题】:Reordering UIView subviews 【发布时间】:2012-07-18 00:10:03 【问题描述】:

在我的应用程序中,我尝试将子视图放在前面,然后稍后将其放回其原始图层位置。代码应该很简单:

将子视图放在前面(在我的自定义 UIView 类中):

[self.superview bringSubviewToFront:self];

简单。我将原始 z 位置存储在一个名为 zPosition 的实例变量中。所以,-bringSubviewToFront: 之前的行是:

zPosition = [self.superview.subviews indexOfObject:self];

所以,我用来将子视图置于前面的所有代码是:

zPosition = [self.superview.subviews indexOfObject:self];
[self.superview bringSubviewToFront:self];

这可以正常工作。问题是当我尝试将子视图放回原处时。我只是这样做:

[self.superview exchangeSubviewAtIndex:zPosition withSubviewAtIndex:
    [self.superview.subviews indexOfObject:self]];

使用这段代码,如果我有两个子视图,会发生这种情况:

假设我有视图 A 和视图 B。视图 A 在视图 B 上方。我点击视图 B,它位于前面。我再次点击视图 B(它应该回到原来的位置),没有任何反应,所以它现在在视图 A 上。如果我现在点击视图 A,它会出现在前面,但是当我再次点击它时(所以它应该回到原来的z位置:在视图B)下面,它的所有兄弟视图都消失了!

有谁知道是什么导致了这个问题?

【问题讨论】:

也许您可以从顶部的虚拟空子视图开始。然后你用那个子视图来回交换。不是最优雅的,我知道... 【参考方案1】:

[快速解决方案]

正如其他人所说,没有必要删除并重新添加您的子视图。

相反,我发现最方便的方法是:

superView.insertSubview(subviewYouWantToReorder, aboveSubview: subviewWhichShouldBeBelow)

【讨论】:

【参考方案2】:

这个问题和答案对我很有帮助。

我需要在视图堆栈之间放置一个叠加层,这些视图位于叠加层的上方和下方,并且我希望保持动态。 也就是说,视图可以判断它是否隐藏。

我使用以下算法对视图重新排序。 感谢下面的 AW101 “无需删除视图”。

这是我的算法:

- (void) insertOverlay 

    // Remember above- and belowcounter
    int belowpos = 0, abovepos = 0;

    // Controller mainview
    UIView *mainview = [self currentMainView];

    // Iterate all direct mainview subviews
    for (UIView* view in mainview.subviews) 
        if ([self isAboveOverlay:view]) 
            // Re-insert as aboveview
            [mainview insertSubview:view atIndex:belowpos + (abovepos++)];
        
        else 
            // Re-insert as belowview
            [mainview insertSubview:view atIndex:belowpos++];
        
    

    // Put overlay in between above and below.
    [mainview insertSubview:_overlay atIndex:belowpos];

【讨论】:

【参考方案3】:

无需从superview中移除:

[self.superview insertSubview:self atIndex:zPosition];

【讨论】:

【参考方案4】:

exchangeSubviewAtIndex 可能会将视图放回正确的位置,但它也会在顶部交换另一个视图,这不是您开始时使用的。您可能需要做这样的事情而不是 exchangeSubviewAtIndex :

[self retain];
UIView *superview = self.superview;
[self removeFromSuperview];
[superview insertSubview:self atIndex:zPosition];
[self release];

【讨论】:

调用 [self removeFromSuperview] 会导致 self 被释放,因为一旦它从其超级视图中删除,就不再拥有它。 也许您可以将其委托给超级视图(和/或负责此层次结构的视图控制器)? @Rickay 如何在主线程在对象方法之一内运行期间释放self?直到他在树顶上,ios 才会剪掉这棵树。 :) 这将是 iOS 的非常不一致和危险的行为,你不觉得吗?这将导致数百次不必要的崩溃......线程的运行循环在进程期间保持当前对象处于活动状态! 你是对的:在多任务处理时不应该响应编程答案! 您能否针对启用 ARC 的情况提供另一种解决方案?我尝试从这里 (***.com/questions/7792622/manual-retain-with-arc) 定义“AntiARCRetain”,但没有成功。

以上是关于重新排序 UIView 子视图的主要内容,如果未能解决你的问题,请参考以下文章

如果在自动布局中删除子视图,则重新排列 UIView 子视图

旋转后重新初始化 UIView 视图和子视图

我继承了 UIView。它的一些子视图是动画的。重新启动这些的正确方法是啥?

如何在 UIView swift 中重新加载特定的子视图?

使用自动布局调整同级视图的大小时,使用子视图重新定位 UIView 不起作用

UIView的属性方法大全