如何设置渐变的UITableViewCell背景?

7

我想创建一个渐变的UITableViewCell背景,就像iPhone上自带的默认时钟应用程序一样。我不确定如何实现这个目标。我是需要创建一张图片并将其设置为背景吗:

cell.contentView.backgroundColor = [UIColor alloc] initWithPatternImage:[UIImage imageNamed:@"background.png"]];

还有其他更好的方法吗?是否有更好的解决方案?

1
如果我的高度不是相等的怎么办?我如何创建我的背景图形? - Sheehan Alam
2个回答

14
我发现了这个问题的现有答案,但并不满意。这里提供一种替代方案,它需要更少的代码,不需要覆盖任何方法,并且可以应用于任何视图。 思路是将 CAGradientLayer 作为 UIView 的子层添加到其层中。我无法在任何地方找到这种方法的文档,所以想和大家分享。
按照以下步骤将 CAGradientLayer 添加到任何 UIView 中:
UIView 标头上创建一个类别 - UIView+Gradient.h:
#import <UIKit/UIKit.h>

@interface UIView (Gradient)
-(void) addLinearUniformGradient:(NSArray *)stopColors;
@end

UIView的分类实现,名称为UIView+Gradient.m:

#import "UIView+Gradient.h"
#import <QuartzCore/QuartzCore.h>

@implementation UIView (Gradient)

-(void) addLinearUniformGradient:(NSArray *)stopColors
{
    CAGradientLayer *gradient = [CAGradientLayer layer];
    gradient.frame = self.bounds;
    gradient.colors = stopColors;
    gradient.startPoint = CGPointMake(0.5f, 0.0f);
    gradient.endPoint = CGPointMake(0.5f, 1.0f);    
    [self.layer addSublayer:gradient];
}

@end

如何在创建UITableViewCell后设置其backgroundView的渐变效果:

// Set the gradient for the cell's background
CGRect backgroundViewFrame = cell.contentView.frame;
backgroundViewFrame.size.height = yourCellHeight;
cell.backgroundView = [[UIView alloc] initWithFrame:backgroundViewFrame];
[cell.backgroundView addLinearUniformGradient:[NSArray arrayWithObjects:
                                               (id)[[UIColor redColor] CGColor],
                                               (id)[[UIColor greenColor] CGColor], nil]];

这个例子只展示了如何设置一个简单的两段渐变(等间距)。查看 CAGradientLayer 文档可以了解如何设置更复杂的渐变。

(* 为附加重要信息编辑 *)

需要注意的另一件事是,如果你在像tableView:cellForRowAtIndexPath这样的方法中添加渐变层,UITableViewCells通常会被重用(即 [tableView dequeueReusableCellWithIdentifier:@"foo"])。因为单元格正在被重新使用,如果每次出列时都向表视图单元格添加渐变层,您可能会在单元格的生命周期内添加几个渐变层。这可能是性能降低的原因。这个问题可能在没有任何可见结果改变的情况下发生,因此很难检测/观察到。有几种解决方法,但你可以考虑修改上面的原始代码,除了添加CAGradientLayer之外,还将创建的CAGradientLayer返回给调用者。然后很容易编写另一个类别方法,允许在实际包含在视图中时删除渐变层:

-(BOOL) removeGradient:(CAGradientLayer *)gradientLayer
{
    // Search for gradient layer and remove it
    NSArray *layers = [self.layer sublayers];
    for ( id layer in layers ) {
        if ( layer == gradientLayer ) {
            [gradientLayer removeFromSuperlayer];
            return YES;
        }
    }

    // Failed to find the gradient layer in this view
    return NO;
}

不是所有的使用情况都需要移除渐变效果,但如果你的使用情况会导致单元格重新使用,那么你可能想要考虑移除渐变效果。可以考虑从UITableViewCell的prepareForReuse方法中调用此方法。

抱歉我的原始解决方案没有解决这个问题。但由于这是一个非常微妙的问题,我想更新我的答案并提供额外的信息。


我尝试将其应用于分组单元格,但渐变填充是一个没有圆角的方框。我错过了什么吗? - Claus
嗯,你可能需要设置图层半径/蒙版。请阅读以下两种方法的文档: [self.layer setCornerRadius: 10.0]; [self.layer setMasksToBounds:YES];希望这能让你朝着正确的方向前进。 - Chris

7

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接