使UIView的背景呈渐变色而不需要子类化

27

有没有一种方法可以使UIView的背景呈现渐变效果,而不需要通过子类化实现?我也不想使用图像文件来完成这个功能。似乎只是为了绘制背景渐变就必须子类化UIView,这种做法看上去很愚蠢。

4个回答

33

您可以使用+[UIColor colorWithPatternImage:]来创建一个图案背景。例如(您需要自己提供CGGradient):

// Allocate color space
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
// Allocate bitmap context
CGContextRef bitmapContext = CGBitmapContextCreate(NULL, 320, 480, 8, 4 * 320, colorSpace, kCGImageAlphaNoneSkipFirst);
//allocate myGradient
CGFloat locationList[]  = {0.0f, 1.0f};
CGFloat colorList[]     = {0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f};
CGGradientRef myGradient   = CGGradientCreateWithColorComponents(colorSpace, colorList, locationList, 2);
// Draw Gradient Here
CGContextDrawLinearGradient(bitmapContext, myGradient, CGPointMake(0.0f, 0.0f), CGPointMake(320.0f, 480.0f), 0);
// Create a CGImage from context
CGImageRef cgImage = CGBitmapContextCreateImage(bitmapContext);
// Create a UIImage from CGImage
UIImage *uiImage = [UIImage imageWithCGImage:cgImage];
// Release the CGImage
CGImageRelease(cgImage);
// Release the bitmap context
CGContextRelease(bitmapContext);
// Release the color space
CGColorSpaceRelease(colorSpace);
// Create the patterned UIColor and set as background color
[targetView setBackgroundColor:[UIColor colorWithPatternImage:image]];

不过,简单地创建一个UIView子类可能会更简单。它也将使用更少的内存。


第2行存在内存泄漏,没有机会释放 CGColorSpaceCreateDeviceRGB() 的结果。 - wangii
好的实现。不过,这个能在新的Retina显示设备上工作吗?(我看到那里硬编码了320x480) - chakrit
@chakrit,它仍然可以在视网膜设备上工作,但只会以1x分辨率渲染渐变;根据渐变的情况,这可能足够了。320x480是硬编码的,以使示例更简单-最好使用实际视图大小。 - rpetrich
@AlexanderPerechnev 这是一个 CGGradientRef,你可以使用 CGGradientCreateWithColors/CGGradientCreateWithColorComponents 来创建它。 - rpetrich

29

您可以这样做:

Swift >= 4.0:

let gradient = CAGradientLayer()
gradient.frame = view.bounds
gradient.colors = [UIColor.red.cgColor, UIColor.white.cgColor]
view.layer.insertSublayer(gradient, at: 0)

Swift 3.0:

let gradient = CAGradientLayer()
gradient.frame = view.bounds
gradient.colors = [UIColor.red().cgColor, UIColor.white().cgColor]
view.layer.insertSublayer(gradient, at: 0)

Swift <= 2.3:

let gradient = CAGradientLayer()
gradient.frame = view.bounds
gradient.colors = [UIColor.redColor().CGColor, UIColor.whiteColor().CGColor]
view.layer.insertSublayer(gradient, atIndex: 0)

Objective-C:

CAGradientLayer *gradient = [CAGradientLayer layer];
gradient.frame = self.view.bounds;
gradient.colors = [NSArray arrayWithObjects:(id)[[UIColor redColor] CGColor], (id)[[UIColor whiteColor] CGColor], nil];
[self.view.layer insertSublayer:gradient atIndex:0];

请确保将QuartzCore框架也添加到您的项目中(至少对于Objective-C)...

#import <QuartzCore/QuartzCore.h>

谢谢。顺畅如丝。 - Oleg Popov
当我使用这段代码时,我会收到错误信息:Undefined symbols for architecture i386: "OBJC_CLASS$_CAGradientLayer",引用自: - Vinoth Kumar
@VinothKumar 添加 #import <QuartzCore/QuartzCore.h> - keji
我写了这个“cellForRowAtIndexPath”,以便在每个单元格中显示渐变视图,它运行良好。现在我面临一个问题,当我向上或向下滚动时,渐变颜色会变得越来越暗。如何解决这个问题? - jithin
@jithin 我建议你发布一个带有你正在使用的代码的问题。我认为你每次都在添加图层,而且它被tableView重复使用,因此每次都会变得更暗。 - keji
显示剩余6条评论

1

我同意rpetrich的观点,只需创建UIView子类即可更加简洁。关于如何实现,请参考我在这个问题中的回答。如果你愿意,你可以创建一个通用的渐变UIView子类,并将其放置在你想要具有渐变背景的视图后面。


0

我将采纳的答案更改为我的版本

+(void) setBlackGradientToView:(UIView*)targetView
{
    CGRect frame = targetView.frame;
    // Allocate color space
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    //allocate myGradient
    CGFloat locationList[]  = {0.0f, 1.0f};
    CGFloat colorList[]     = {0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f};
    CGGradientRef myGradient   = CGGradientCreateWithColorComponents(colorSpace, colorList, locationList, 2);
    // Allocate bitmap context
    CGContextRef bitmapContext = CGBitmapContextCreate(NULL, frame.size.width, frame.size.height, 8, 4 * frame.size.width, colorSpace, kCGImageAlphaPremultipliedLast);
    //Draw Gradient Here
    CGContextDrawLinearGradient(bitmapContext, myGradient, CGPointMake(0.0f, 0.0f), CGPointMake(0, frame.size.height), 0);
    // Create a CGImage from context
    CGImageRef cgImage = CGBitmapContextCreateImage(bitmapContext);
    // Create a UIImage from CGImage
    UIImage *uiImage = [UIImage imageWithCGImage:cgImage];
    // Release the CGImage
    CGImageRelease(cgImage);
    // Release the bitmap context
    CGContextRelease(bitmapContext);
    // Release the color space
    CGColorSpaceRelease(colorSpace);

    //Create the patterned UIColor and set as background color
    [targetView setBackgroundColor:[UIColor colorWithPatternImage:uiImage]];
    //return uiImage;
}

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