如何优化 iPhone 上的 UIColor?

Posted

技术标签:

【中文标题】如何优化 iPhone 上的 UIColor?【英文标题】:How do you optimize UIColor on the iPhone? 【发布时间】:2009-04-15 02:50:33 【问题描述】:

我正在创建一个由自定义滑块类型控件控制的简单颜色选择器。

我将一个浮点值从我的滑块传递给 UIColor 构造方法,并随着值的变化更新 CALayer 的背景颜色。

它在模拟器中运行非常流畅,但在设备上运行时会出现很多闪烁。

这仅仅是因为 GPU 负担过重吗?奇怪的是,当穿过蓝色时,这是最糟糕的。并且改变 alpha 值和亮度比改变饱和度和色调更容易闪烁。

我不应该在滑块值更改时传递任意浮点值吗?如果没有,我如何将其限制为更少的颜色以进行优化?

我想过禁用 CALayer 的 backgroundColor 属性的隐式动画,但我不知道该怎么做。

有没有优化 UIColor 变化的技巧。

更新

我没有使用 drawRect: 或 drawInRect:

我只是在更改 CALayer 的 backgroundColor 属性。每次调用 touchesMoved: 时,我都会抓取位置,创建一个 0.0 到 1.0 的浮点值,并向我的委托传递一条消息,告知该值已更改,然后调用 -(void)updateCurrentColor 方法。

这是我的实现示例:

@implementation MyCustomSliderView


- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event 

    hueLocation = [[touches anyObject] locationInView:self];

    //Smoothing
    if ((hueLocation.x > previousHueLocation.x) && ((hueLocation.x - previousHueLocation.x) > 1.0) && (hueLocation.x - previousHueLocation.x) < 10.0) 
        hueLocation.x = previousHueLocation.x + 1.0;
       

    if ((hueLocation.x < previousHueLocation.x) && ((previousHueLocation.x - hueLocation.x) > 1.0) && (previousHueLocation.x - hueLocation.x) < 10.0) 
        hueLocation.x = previousHueLocation.x - 1.0;
       

    //Percentage of screen.
    hueValue = hueLocation.x/self.bounds.size.width;

    //Clip to 1.0 & 0.0
    if (hueValue > 1.0) 
        hueValue = 1.0;
    
    if (hueValue < 0.0) 
        hueValue = 0.0;
    

    NSLog(@"Value is: %f", hueValue);
    NSLog(@"Location %f", hueLocation.x);   

    previousHueLocation = hueLocation;

    if([delegate respondsToSelector:@selector(updateCurrentColor)]) 
        [delegate updateCurrentColor];
    




@implementation MyViewController

- (void)updateCurrentColor 

    currentColor = [UIColor colorWithHue:hueSliderView.hueValue
                              saturation:saturationSliderView.saturationValue
                              brightness:brightnessSliderView.brightnessValue
                                   alpha:alphaSliderView.alphaValue];

    colorLayer.backgroundColor = currentColor.CGColor;  


起初我以为是因为触摸界面的不精确导致的跳跃值。平滑功能有所帮助,但它仍然会闪烁一些,尤其是在使用 alpha 值时,即使我的位置仅改变 1 个像素。我应该将其限制为有限数量的颜色/值,而不是仅仅传入任意浮点数吗?同样,在模拟器中运行良好,似乎只是性能问题。

【问题讨论】:

描述你得到的效果。是否有可见的垂直/水平“条”变化可见?元素会暂时消失吗?您是否获得了可见但不需要的过渡颜色? 没有酒吧。当我更改值(色相、饱和度、亮度、alpha)时,颜色会忽明忽暗。如果我走得很慢,那就更好了,但有时还是会闪烁。我将 touchesMoved 方法调整为一次只移动一个像素,除非移动超过 15 个像素。这很有帮助。但仍然闪烁。 【参考方案1】:

禁用隐式动画消除了闪烁。

我更新了颜色更改方法,以便在从 touchesBegan: 调用时背景颜色可以动画,但在从 touchesMoved: 调用时不会隐式动画:

- (void)updateCurrentColorAnimated:(BOOL)animated 

    currentColor = [UIColor colorWithHue:hueSliderView.hueValue
                              saturation:colorView.saturationValue
                              brightness:colorView.brightnessValue
                                   alpha:alphaSlider.alphaValue];
    if (animated) 

        colorLayer.backgroundColor = currentColor.CGColor;

       

    if (!animated) 

        [CATransaction begin];

        [CATransaction setValue:(id)kCFBooleanTrue
                         forKey:kCATransactionDisableActions];


        colorLayer.backgroundColor = currentColor.CGColor;

        [CATransaction commit];

    


我滚动自己的滑块的原因是我可以跳转到新的值,而不必完美地捕捉小滑块控件,我发现它的交互不是很好。

【讨论】:

【参考方案2】:

iPhone 上的绘图是双缓冲的。如果你开始闪烁,那是因为你在画一个东西然后另一个 - 这不是因为速度问题。

我猜你犯了以下错误之一:

更新颜色值和绘制颜色方块不同步(因此在 drawInRect 时颜色设置不正确:) 未能正确初始化/计算颜色(因此您显示的颜色无效) 不该删除或重绘矩形

要检查的另一件事... Cocoa 中的颜色是从 0 到 1 的浮点数。将整数值设置为 0 到 255(在 web 或 Windows 上使用)会导致严重的奇怪问题。 如果您的颜色计算超过 0 到 255,则在设置 UIColor 之前除以 255.0。

【讨论】:

在这种情况下“双缓冲”是什么意思? @Matt Gallagher,谢谢,刚刚更新了我的实施问题。 @erikprice “双缓冲”表示所有绘图都发生在屏幕外,然后在绘图完成后复制到屏幕上。这意味着擦除为白色,然后绘制黑色不会导致屏幕闪烁,因为从未显示白色状态。

以上是关于如何优化 iPhone 上的 UIColor?的主要内容,如果未能解决你的问题,请参考以下文章

来自 UIColor 的纹理?

iPhone UI 测试 - 如何访问键盘上的删除键

如何在 UI 中添加渐变角度?

iPhone 上的流畅 UI 布局

iPhone导航栏的默认UIColor

iPhone上的UIView和UILabels上的渐变[重复]