在我的应用中,我有一些小的子视图。当用户点击子视图时,我会在点击的子视图(相同大小)的顶部放置一个单独的视图,然后将此单独视图设置为全屏大小。
放大视图是自定义绘制的,这会产生这种方法的一个大问题。如果我在主视图的viewDidLoad
方法中创建放大视图并将其框架设置为全屏大小,则会立即调用视图的drawRect
方法,并且视图会正确呈现为全尺寸。如果我在动画中使用此视图,一切都按预期工作。
但是,我需要根据点击的子视图来扩大视图,因此我需要每次重新创建/重新绘制它。问题在于,当我执行此操作以响应触摸事件时,视图的drawRect
方法在动画开始之前不会被调用,此时视图的帧很小而不是全屏,因此一切都是错误的。
在我的触摸事件代码中,我明确地将视图的帧设置为全屏并在开始动画之前调用setNeedsDisplay
,但这没有效果 - drawRect
直到动画开始了。
有没有办法强制重绘,以便在框架是我想要的尺寸时绘制视图?
答案 0 :(得分:25)
正如我在上面评论过的那样,Joe问了一些类似的问题(作为一个更普遍的问题)here,Tom Swift provided an answer操纵当前的运行循环。
他的建议是在使用以下代码调用-setNeedsDisplay
后立即强制执行一次迭代:
[[NSRunLoop currentRunLoop] runMode: NSDefaultRunLoopMode beforeDate: [NSDate date]];
这种方法有一些注意事项,在那里的评论中讨论过。
此外,有人指出
[CATransaction flush];
也可以达到强制立即重绘视图的效果。
答案 1 :(得分:4)
这样做的正确方法是简单地划分你的方法。
只需致电setNeedsDisplay
,然后在没有动画的情况下返回。等到正确设置所有内容的drawRect
完成重绘,然后让它排队另一个启动所需动画的方法(通过排队操作或通知)。然后开始动画。这一切都可以相当快地(以帧速率)发生,并且不涉及额外的(危险的)递归运行循环调用或CATransaction
调用(这可能会导致额外的GPU设置)。
答案 2 :(得分:0)
调用setNeedsDisplay
后,可能需要一段时间才能调用drawRect。以短(0.1f)延迟开始动画。您也可以从[self performSelector:withObject:afterDelay:]调用动画方法,以便在更容易的情况下添加延迟。
答案 3 :(得分:0)
Apple工程师提供了另一种推荐的解决方案。使用2个UIViews,一个小的,一个大的,较大的一个,alpha为0.渲染两者,设置大的框架小,并使动画交叉淡入淡出以及缩小从小到大的两种尺寸。