草庐IT

objective-c - 将渐变放在 tableview 单元格背景上

coder 2024-01-22 原文

我一直在尝试通过多种方式为我的表格 View 单元格背景添加渐变效果,但似乎都不起作用。我一直在尝试用 quarz core graphics 绘制它,将背景 socket 放在 IB 上的不同 View ,将 imageview 用代码放在后面。似乎没有人以某种方式出现在背面,我不明白哪里出了问题。如果需要我可以详细说明,谢谢!

最佳答案

我在 this question 中找到了一些代码并使其适应我的应用程序。它适用于普通表格和分组表格。

//
//  UAGradientCellBackgroundLayer.h
//

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>

#import <QuartzCore/QuartzCore.h>

@class UAGradientCellBackgroundView;

@interface UAGradientCellBackgroundLayer : CAGradientLayer {
    CGFloat     *colorComponents;
    BOOL        _override;
}

@property(nonatomic,assign) BOOL override;

- (void)setColorComponents:(CGFloat *)components;

@end

//
//  UAGradientCellBackgroundLayer.m
//

#import "UAGradientCellBackgroundLayer.h"
#import "UAGradientCellBackgroundView.h"

#define TABLE_CELL_BACKGROUND                                   {1, 1, 1, 1, 204/255.0, 204/255.0, 204/255.0, 1}        // #FFFFFF and #DDDDDD

@implementation UAGradientCellBackgroundLayer

@synthesize override = _override;

///////////////////////////////////////////////////////////////////////////////////////////////////
- (id)init { 
    if ((self = [super init])) {
        colorComponents = NSZoneMalloc(NSDefaultMallocZone(), 8*sizeof(CGFloat));
        CGFloat c[8] = TABLE_CELL_BACKGROUND;
        for (int i = 0; i < 8; i++) {
            colorComponents[i] = c[i];
        }
        // self.cornerRadius = 10;
        // self.backgroundColor = [UIColor clearColor].CGColor;
    }
    return self;
}

- (void) dealloc {
    NSZoneFree(NSDefaultMallocZone(), colorComponents);
    [super dealloc];
}
- (void)display {
    if (_override) {
        self.colors =
        [NSArray arrayWithObjects:
         (id)[UIColor colorWithRed:colorComponents[0] green:colorComponents[1] blue:colorComponents[2] alpha:colorComponents[3]].CGColor,
         (id)[UIColor colorWithRed:colorComponents[4] green:colorComponents[5] blue:colorComponents[6] alpha:colorComponents[7]].CGColor,
         nil];
    } else {
        self.colors =
        [NSArray arrayWithObjects:
         (id)[UIColor clearColor].CGColor,
         (id)[UIColor clearColor].CGColor,
         nil];
    }
    [super display];
}

- (void)setColorComponents:(CGFloat *)components {
    for (int i = 0; i < 8; i++) {
        colorComponents[i] = components[i];
    }
}

@end 

//
//  UAGradientCellBackgroundView.h
//

#import <Foundation/Foundation.h>

#import <UIKit/UIKit.h>

typedef enum  {
    UAGradientCellBackgroundViewPositionMiddle = 0,
    UAGradientCellBackgroundViewPositionTop,
    UAGradientCellBackgroundViewPositionBottom,
    UAGradientCellBackgroundViewPositionSingle,
    UAGradientCellBackgroundViewPositionPlain
} UAGradientCellBackgroundViewPosition;

@interface UAGradientCellBackgroundView : UIView {
    UAGradientCellBackgroundViewPosition position;
    CGFloat colors[8];
}

@property(nonatomic, assign) UAGradientCellBackgroundViewPosition position;

- (void)setColors:(CGFloat[8])comps;

@end

//
//  UAGradientCellBackgroundView.m
//

#import "UAGradientCellBackgroundView.h"
#import "UAGradientCellBackgroundLayer.h"
#import <QuartzCore/QuartzCore.h>

#define kDefaultMargin                                          10
#define TABLE_CELL_BACKGROUND                                   {1, 1, 1, 1, 204/255.0, 204/255.0, 204/255.0, 1}        // #FFFFFF and #DDDDDD

static void addRoundedRectToPath(CGContextRef context, CGRect rect,
                                 float ovalWidth,float ovalHeight);

@implementation UAGradientCellBackgroundView

@synthesize position;

//////////////////////////////////////////////////////////////////////
// PLAIN CELL
//
// layerClass
//
// returns a CAGradientLayer class as the default layer class for this view
//
+ (Class)layerClass {
    return [UAGradientCellBackgroundLayer class];
}

//////////////////////////////////////////////////////////////////////
- (void)updateLayer {
    UAGradientCellBackgroundLayer* layer = (UAGradientCellBackgroundLayer*)self.layer;
        // This is dramatically faster than calling drawRect.
    [layer setColorComponents:colors];
    layer.override = (self.position == UAGradientCellBackgroundViewPositionPlain);
    [layer setNeedsDisplay];
}

////////////////////////////////////////////////////////////////////
// GROUPED CELL
- (void)setColors:(CGFloat[8])comps {
    for (int i = 0; i < 8; i++) {
        colors[i] = comps[i];
    }
}

- (BOOL)isOpaque {
    return YES;
}

- (id)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if (self != nil) {
        CGFloat comps[8] = TABLE_CELL_BACKGROUND;
        [self setColors:comps];
    }
    return self;
}

- (void)debugView:(UIView *)view {
    NSLog(@"%@ - %@", view.backgroundColor, [[view class] description]);
    for (UIView* child in view.subviews) {
        [self debugView:child];
    }
}

-(void)drawRect:(CGRect)aRect {
    [super drawRect:aRect];
    // Drawing code
    if (position == UAGradientCellBackgroundViewPositionPlain) {
        return;
    }

    CGContextRef c = UIGraphicsGetCurrentContext(); 

    // TODO - Dirty, Dirty hack to fix the background black corners on pop issue. doesnt handle rotation.
//  CGContextSetFillColorWithColor(c, [UAColor offsetPinstripesColor].CGColor);
//  CGContextFillRect(c, aRect);

    int lineWidth = 1;

    CGRect rect = [self bounds];
    rect.size.width -= lineWidth;
    rect.size.height -= lineWidth;
    rect.origin.x += lineWidth / 2.0;
    rect.origin.y += lineWidth / 2.0;

    CGFloat minx = CGRectGetMinX(rect), midx = CGRectGetMidX(rect), maxx = CGRectGetMaxX(rect);
    CGFloat miny = CGRectGetMinY(rect), midy = CGRectGetMidY(rect), maxy = CGRectGetMaxY(rect);
    miny -= 1;

    CGFloat locations[2] = { 0.0, 1.0 };    
    CGColorSpaceRef myColorspace = CGColorSpaceCreateDeviceRGB();
    CGGradientRef myGradient = nil;

    CGContextSetStrokeColorWithColor(c, [UIColor darkGrayColor].CGColor);
    CGContextSetLineWidth(c, lineWidth);
    CGContextSetAllowsAntialiasing(c, YES);
    CGContextSetShouldAntialias(c, YES);

    if (position == UAGradientCellBackgroundViewPositionTop) {
        miny += 1;

        CGMutablePathRef path = CGPathCreateMutable();
        CGPathMoveToPoint(path, NULL, minx, maxy);
        CGPathAddArcToPoint(path, NULL, minx, miny, midx, miny, kDefaultMargin);
        CGPathAddArcToPoint(path, NULL, maxx, miny, maxx, maxy, kDefaultMargin);
        CGPathAddLineToPoint(path, NULL, maxx, maxy);
        CGPathAddLineToPoint(path, NULL, minx, maxy);
        CGPathCloseSubpath(path);

        // Fill and stroke the path
        CGContextSaveGState(c);
        CGContextAddPath(c, path);
        CGContextClip(c);

        myGradient = CGGradientCreateWithColorComponents(myColorspace, colors, locations, 2);
        CGContextDrawLinearGradient(c, myGradient, CGPointMake(minx,miny), CGPointMake(minx,maxy), 0);

        CGContextAddPath(c, path);
        CGPathRelease(path);
        CGContextStrokePath(c);
        CGContextRestoreGState(c);

    } else if (position == UAGradientCellBackgroundViewPositionBottom) {
        //maxy -= 1; // -1 for the shadow 

        CGMutablePathRef path = CGPathCreateMutable();
        CGPathMoveToPoint(path, NULL, minx, miny);
        CGPathAddArcToPoint(path, NULL, minx, maxy, midx, maxy, kDefaultMargin);
        CGPathAddArcToPoint(path, NULL, maxx, maxy, maxx, miny, kDefaultMargin);
        CGPathAddLineToPoint(path, NULL, maxx, miny);
        CGPathAddLineToPoint(path, NULL, minx, miny);
        CGPathCloseSubpath(path);

        // Fill and stroke the path
        CGContextSaveGState(c);
        CGContextAddPath(c, path);
        CGContextClip(c);

        myGradient = CGGradientCreateWithColorComponents(myColorspace, colors, locations, 2);
        CGContextDrawLinearGradient(c, myGradient, CGPointMake(minx,miny), CGPointMake(minx,maxy), 0);

        CGContextAddPath(c, path);
        CGPathRelease(path);
        CGContextStrokePath(c);
        CGContextRestoreGState(c);


    } else if (position == UAGradientCellBackgroundViewPositionMiddle) {

        CGMutablePathRef path = CGPathCreateMutable();
        CGPathMoveToPoint(path, NULL, minx, miny);
        CGPathAddLineToPoint(path, NULL, maxx, miny);
        CGPathAddLineToPoint(path, NULL, maxx, maxy);
        CGPathAddLineToPoint(path, NULL, minx, maxy);
        CGPathAddLineToPoint(path, NULL, minx, miny);
        CGPathCloseSubpath(path);

        // Fill and stroke the path
        CGContextSaveGState(c);
        CGContextAddPath(c, path);
        CGContextClip(c);

        myGradient = CGGradientCreateWithColorComponents(myColorspace, colors, locations, 2);
        CGContextDrawLinearGradient(c, myGradient, CGPointMake(minx,miny), CGPointMake(minx,maxy), 0);

        CGContextAddPath(c, path);
        CGPathRelease(path);
        CGContextStrokePath(c);
        CGContextRestoreGState(c);

    } else if (position == UAGradientCellBackgroundViewPositionSingle) {
        miny += 1;
        //maxy -= 1; // -1 for the shadow 

        CGMutablePathRef path = CGPathCreateMutable();
        CGPathMoveToPoint(path, NULL, minx, midy);
        CGPathAddArcToPoint(path, NULL, minx, miny, midx, miny, kDefaultMargin);
        CGPathAddArcToPoint(path, NULL, maxx, miny, maxx, midy, kDefaultMargin);
        CGPathAddArcToPoint(path, NULL, maxx, maxy, midx, maxy, kDefaultMargin);
        CGPathAddArcToPoint(path, NULL, minx, maxy, minx, midy, kDefaultMargin);
        CGPathCloseSubpath(path);

        // Shadow
//      CGContextAddPath(c, path);
//      CGContextSaveGState(c);
//      CGContextSetShadow(c, CGSizeMake(0, -1), 1);
//      CGContextFillPath(c);

        // Fill and stroke the path
        CGContextSaveGState(c);
        CGContextAddPath(c, path);
        CGContextClip(c);


        myGradient = CGGradientCreateWithColorComponents(myColorspace, colors, locations, 2);
        CGContextDrawLinearGradient(c, myGradient, CGPointMake(minx,miny), CGPointMake(minx,maxy), 0);

        CGContextAddPath(c, path);
        CGPathRelease(path);
        CGContextStrokePath(c);
        CGContextRestoreGState(c);

    }
    CGColorSpaceRelease(myColorspace);
    CGGradientRelease(myGradient);
    return;
}

- (void)setPosition:(UAGradientCellBackgroundViewPosition)newPosition {
    if (position != newPosition) {
        position = newPosition;
        [self updateLayer];
    }
}

@end

static void addRoundedRectToPath(CGContextRef context, CGRect rect, float ovalWidth,float ovalHeight) {
    float fw, fh;

    if (ovalWidth == 0 || ovalHeight == 0) {// 1
        CGContextAddRect(context, rect);
        return;
    }

    CGContextSaveGState(context);// 2

    CGContextTranslateCTM (context, CGRectGetMinX(rect),// 3
                           CGRectGetMinY(rect));
    CGContextScaleCTM (context, ovalWidth, ovalHeight);// 4
    fw = CGRectGetWidth (rect) / ovalWidth;// 5
    fh = CGRectGetHeight (rect) / ovalHeight;// 6

    CGContextMoveToPoint(context, fw, fh/2); // 7
    CGContextAddArcToPoint(context, fw, fh, fw/2, fh, 1);// 8
    CGContextAddArcToPoint(context, 0, fh, 0, fh/2, 1);// 9
    CGContextAddArcToPoint(context, 0, 0, fw/2, 0, 1);// 10
    CGContextAddArcToPoint(context, fw, 0, fw, fh/2, 1); // 11
    CGContextClosePath(context);// 12

    CGContextRestoreGState(context);// 13
} 

使用示例(普通表格):

#import "UAGradientCellBackgroundView.h" 
CGFloat COLORS[8] = { 0.0/255, 0.0/255, 255.0/255, 1.0, 0.0/255, 0.0/255, 0.0/255, 1.0 }
...

- (UITableViewCell *)tableView:(UITableView *)table cellForRowAtIndexPath:(NSIndexPath *)indexPath { 
    NSString *cellID = @"CellID";

    // create cell
    UITableViewCell *cell = (UITableViewCell *)[table dequeueReusableCellWithIdentifier:cellID];
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellID] autorelease];

        UAGradientCellBackgroundView *bgView = [[[UAGradientCellBackgroundView alloc] initWithFrame:CGRectZero] autorelease];
        [bgView setBackgroundColor:[UIColor clearColor]];
        [bgView setColors:COLORS];
        [bgView setPosition:UAGradientCellBackgroundViewPositionPlain];
        cell.selectedBackgroundView = bgView;
        cell.textLabel.backgroundColor = [UIColor clearColor];

        cell.imageView.image = [UIImage imageNamed:@"cellimg.png"];
    }

    cell.textLabel.text = @"Text";
    return cell; 
}

关于objective-c - 将渐变放在 tableview 单元格背景上,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4228343/

有关objective-c - 将渐变放在 tableview 单元格背景上的更多相关文章

  1. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

    类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

  2. ruby - 主要 :Object when running build from sublime 的未定义方法 `require_relative' - 2

    我已经从我的命令行中获得了一切,所以我可以运行rubymyfile并且它可以正常工作。但是当我尝试从sublime中运行它时,我得到了undefinedmethod`require_relative'formain:Object有人知道我的sublime设置中缺少什么吗?我正在使用OSX并安装了rvm。 最佳答案 或者,您可以只使用“require”,它应该可以正常工作。我认为“require_relative”仅适用于ruby​​1.9+ 关于ruby-主要:Objectwhenrun

  3. ruby-on-rails - 如果 Object::try 被发送到一个 nil 对象,为什么它会起作用? - 2

    如果您尝试在Ruby中的nil对象上调用方法,则会出现NoMethodError异常并显示消息:"undefinedmethod‘...’fornil:NilClass"然而,有一个tryRails中的方法,如果它被发送到一个nil对象,它只返回nil:require'rubygems'require'active_support/all'nil.try(:nonexisting_method)#noNoMethodErrorexceptionanymore那么try如何在内部工作以防止该异常? 最佳答案 像Ruby中的所有其他对象

  4. ruby-on-rails - 使用 Sublime Text 3 突出显示 HTML 背景语法中的 ERB? - 2

    所以我在关注Railscast,我注意到在html.erb文件中,ruby代码有一个微弱的背景高亮效果,以区别于其他代码HTML文档。我知道Ryan使用TextMate。我正在使用SublimeText3。我怎样才能达到同样的效果?谢谢! 最佳答案 为SublimeText安装ERB包。假设您安装了SublimeText包管理器*,只需点击cmd+shift+P即可获得命令菜单,然后键入installpackage并选择PackageControl:InstallPackage获取包管理器菜单。在该菜单中,键入ERB并在看到包时选择

  5. ruby-on-rails - 使用 Rmagick 或 ImageMagick 在背景上放置标题 - 2

    我有一张背景图片,我想在其中添加一个文本框。我想弄清楚如何将标题放置在其顶部的正确位置。(我使用标题是因为我需要自动换行功能)。现在,我只能让文本显示在左上角,但我需要能够手动定位它的开始位置。require'RMagick'require'Pry'includeMagicktext="Loremipsumdolorsitamet"img=ImageList.new('template001.jpg')img 最佳答案 这是使用convert的ImageMagick命令行的答案。如果你想在Rmagick中使用这个方法,你必须自己移植

  6. ruby-on-rails - Prawn - 表格单元格内的链接 - 2

    我正在尝试用Prawn生成PDF。在我的PDF模板中,我有带单元格的表格。在其中一个单元格中,我有一个电子邮件地址:cell_email=pdf.make_cell(:content=>booking.user_email,:border_width=>0)我想让电子邮件链接到“mailto”链接。我知道我可以这样链接:pdf.formatted_text([{:text=>booking.user_email,:link=>"mailto:#{booking.user_email}"}])但是将这两行组合起来(将格式化文本作为内容)不起作用:cell_email=pdf.make_c

  7. objective-c - 在设置 Cocoa Pods 和安装 Ruby 更新时出错 - 2

    我正在尝试为我的iOS应用程序设置cocoapods但是当我执行命令时:sudogemupdate--system我收到错误消息:当前已安装最新版本。中止。当我进入cocoapods的下一步时:sudogeminstallcocoapods我在MacOS10.8.5上遇到错误:ERROR:Errorinstallingcocoapods:cocoapods-trunkrequiresRubyversion>=2.0.0.我在MacOS10.9.4上尝试了同样的操作,但出现错误:ERROR:Couldnotfindavalidgem'cocoapods'(>=0),hereiswhy:U

  8. ruby - 单元测试文件 I/O 方法 - 2

    我对单元测试还是比较陌生。我用Ruby编写了一个类,它接受一个文件,在该文件中搜索给定的Regex模式,替换它,然后将更改保存回文件。我希望能够为此方法编写单元测试,但我不知道我将如何去做。有人能告诉我我们如何对处理文件i/o的方法进行单元测试吗? 最佳答案 看看这个HowdoIunit-testsavingfiletothedisk?基本上这个想法是一样的,文件系统是你的类的依赖。所以引入一个可以在你的单元测试中模拟的角色/接口(interface)(这样你在单元测试时就没有依赖性);角色中的方法应该是您从文件系统中需要的所有东西

  9. ruby - 你会如何在 Ruby 中表达成语 "with this object, if it exists, do this"? - 2

    在Ruby(尤其是Rails)中,您经常需要检查某物是否存在,然后对其执行操作,例如:if@objects.any?puts"Wehavetheseobjects:"@objects.each{|o|puts"hello:#{o}"end这是最短的,一切都很好,但是如果你有@objects.some_association.something.hit_database.process而不是@objects呢?我将不得不在if表达式中重复两次,如果我不知道实现细节并且方法调用很昂贵怎么办?显而易见的选择是创建一个变量,然后测试它,然后处理它,但是你必须想出一个变量名(呃),它也会在内存中

  10. ruby - 在 Ruby 中,为什么 Array.new(size, object) 创建一个由对同一对象的多个引用组成的数组? - 2

    如thisanswer中所述,Array.new(size,object)创建一个数组,其中size引用相同的object。hash=Hash.newa=Array.new(2,hash)a[0]['cat']='feline'a#=>[{"cat"=>"feline"},{"cat"=>"feline"}]a[1]['cat']='Felix'a#=>[{"cat"=>"Felix"},{"cat"=>"Felix"}]为什么Ruby会这样做,而不是对object进行dup或clone? 最佳答案 因为那是thedocumenta

随机推荐