重新排序 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。它的一些子视图是动画的。重新启动这些的正确方法是啥?