我有一个30 UIButtons的网格,可能还有更多的子类要使用层来呈现:一个基本CALayer、一个CAShapeLayer、一个CAGradientLayer和一个CATextLayer。我试图在加载相应的xib文件时尽量减少呈现/显示按钮所需的全部时间。如果我只是在viewDidLoad中依次设置每个按钮,则视图出现所需的时间大约是5-6秒,这显然是太多了。
为了加快按钮的设置速度,我使用的是大中央调度,如下所示。在viewDidLoad中,我在全局队列上使用dispatch_async设置每个按钮层(将形状和渐变层添加到基本层),这样按钮就可以在不同的线程中呈现。A块的末端,CATextLayer被添加到梯度层。
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
CGRect base_bounds = CGRectMake(0, 0, self.layer.bounds.size.width, self.layer.bounds.size.height - self.layer.bounds.size.height * 0.10f);
CGPoint move_point = CGPointMake(0.0f, base_bounds.size.height * 0.10f);
self.layer.masksToBounds = NO;
baseLayer = [CALayer layer];
baseLayer.cornerRadius = 10.0;
baseLayer.shadowOffset = CGSizeMake(0.0f, 2.0f);
baseLayer.shadowOpacity = 1.5f;
baseLayer.shadowColor = [UIColor blackColor].CGColor;
baseLayer.shadowRadius = 2.5f;
baseLayer.anchorPoint = CGPointMake(0.5f, 0.5f);
baseLayer.position = move_point;
CAShapeLayer *shape = [CALayer layer];
shape.bounds = base_bounds;
shape.cornerRadius = 10.0;
shape.anchorPoint = CGPointMake(0.0f, 0.0f);
shape.position = move_point;
shape.backgroundColor = [UIColor darkGrayColor].CGColor;
gradient = [CAGradientLayer layer];
gradient.anchorPoint = CGPointMake(0.0f, 0.0f);
gradient.position = CGPointMake(0.0f, 0.0f);
gradient.bounds = base_bounds;
gradient.cornerRadius = 10.0;
gradient.borderColor = [UIColor colorWithRed:0.72f
green:0.72f
blue:0.72f
alpha:1.0].CGColor;
gradient.borderWidth = 0.73;
gradient.colors = [NSArray arrayWithObjects:
(id)[UIColor whiteColor].CGColor,
(id)[UIColor whiteColor].CGColor,
nil];
[baseLayer addSublayer:shape];
[baseLayer addSublayer:gradient];
[self.layer addSublayer:baseLayer];
[textLayer setBounds:gradient.bounds];
[textLayer setPosition:CGPointMake(CGRectGetMidX(textLayer.bounds), CGRectGetMaxY(textLayer.bounds) - 6)];
[textLayer setString:self.titleLabel.text];
[textLayer setForegroundColor:[UIColor blackColor].CGColor];
[gradient addSublayer:textLayer];
});这种方法将整个时间缩短到大约2-3秒.我想知道是否有人能提出一个更快的方法来渲染按钮。请注意,我对任何放弃使用图层的解决方案都不感兴趣。
提前谢谢你。
发布于 2011-10-03 15:19:23
也许我忽略了这一点,但您是否可以更好地重写UIButton drawRect:方法和使用CoreGraphics ( CG )进行绘图将比秒快得多,您可以轻松地使用CG API进行渐变、文本和图像绘制。如果我正确理解,每个按钮有4层,30+按钮在同一个视图中(120+层)?如果是这样的话,我不认为您应该绘制这么多层(单独呈现/混合所有这些层将解释巨大的呈现时间)。另一种可能是有4个大的层,所有的按钮。
发布于 2011-09-30 20:09:36
这是我的主意
将您的CALayers与UIButton分开-- UIKit不允许任何背景线程上的任何内容。
当在按钮网格之前的屏幕上有机会时,请使用buttonGridViewController performSelectorInBackground:renderCALayers在后台呈现您的CALayers。
当您在viewDidLoad中加载按钮网格时,使用UIButtonTypeCustom类型覆盖UIButtons,并在“按钮”CALayers顶部添加backgroundColor = UIColor clearColor (确保在UIButtons上调用bringSubviewToFront,以便他们获得触摸事件)。
如果您不知道要呈现多少个按钮,则可能需要预渲染可能显示的最大数目。
如果您有任何问题,请评论。
编辑:
一些相关的东西,
What to replace a UIButton to improve frame rate?
UI design - Best way to deal with many UIButtons
How to get touch event on a CALayer?
我相信,从这一点开始,获得更快加载的唯一方法是替换或删除UIButtons,并使用另一种方法拦截触摸事件。这样,在视图出现之前,所有呈现都可以在后台线程中完成。
发布于 2011-10-03 22:01:14
您考虑过使用NSOperation生成按钮的层吗?在代码中,您将实例化一个操作队列,然后遍历每个按钮,在每个按钮启动时触发一个操作(传递生成该按钮层所需的相应参数)。
在您的NSOperation中,使用CoreGraphics生成您的层,然后通过您的完成处理程序(确保在主线程上调用它)将该层传回启动操作的按钮(在本例中是目标按钮)。这将为您提供相当好的性能,因为您的按钮层的按钮层将使用CoreGraphics从主线程上呈现,然后只有在该层被呈现后才会传递回UIKit以供表示。
NSOperation位于GCD之上,具有少量的开销,但在您的情况下提供了一些好处,例如设置依赖的先决条件和优先级的能力。
而且,我很确定您不应该在您共享的GCD块中调用UIColor。
希望这能帮上忙!
https://stackoverflow.com/questions/7579630
复制相似问题