自定义tableView:角半径,减小宽度和阴影

时间:2012-10-03 13:33:16

标签: objective-c ios cocoa-touch uitableview

这就是我想要做的事情:

enter image description here

如你所见,我想:

  1. 减少tableView的宽度(我希望边缘上的边距比分组tableView提供的更多)

  2. 转角半径(半径大于分组tableView的默认值)

  3. 在桌子周围投下阴影,在最后一个单元格下面留下一个特殊的阴影

2 个答案:

答案 0 :(得分:4)

您可以通过自己“绘制”单元格的backgroundView来实现此目的。

我建议将图像用作背景(如果单元格的高度相同)。

你需要三张照片。

“顶部”图像,顶角为圆角。 一个“底部”图像,底角为圆角,投影如图所示。 还有一个没有圆角的“中间”图像。

如果单元格中没有任何纹理或渐变,则可以使用可伸缩图像来减少它们的内存占用。

然后我将子类化UITableViewCell并覆盖backgroundView以添加UIImageView。我还提供了一个访问器方法来更改单元格的类型(顶部,中间,底部)。

然后每个单元格可以具有UIImage的三个placeHolder属性(topImage,bottomImage和middleImage)。当更改单元格的类型时,可以访问它们(使用延迟实例化以确保它们仅在需要时加载一次)然后将backgroundVIew图像设置为所需图像。

像这样......

在UITableViewCell子类中定义一个类型枚举...

typedef enum {
    CellTypeTop,
    CellTypeMiddle,
    CellTypeBottom
} cellType;

然后是类型的属性......

@property (nonatomic) cellType cellType

然后在.m ...

定义更多内部属性......

@property UIImageView *bgImageView;
@property UIImage *topImage;
@property UIImage *middleImage;
@property UIImage *bottomImage;

然后添加imageView(仅一次)......

- (void)awakeFromNib //or in the init depends how you are initialising the cell
{
    self.bgImageView = [[UIImageView alloc] initWithFrame:blah];

    [self.backgroundView addSubView:self.bgImageView];
}

现在当类型改变了......

- (void)setCellType:(cellType)cellType
{
    switch(cellType) {
        case CellTypeTop:
            self.bgImageView.image = self.topImage;
            break;
        case CellTypeMiddle:
            self.bgImageView.image = self.middleImage;
            break;
        case CellTypeBottom:
            self.bgImageView.image = self.bottomImage;
            break;
    }
}

最后是图像的懒惰实例化......

- (UIImage *)topImage
{
    if (_topImage == nil) {
        _topImage = [UIImage imageNamed:@"topImage"];
        //alternatively...
        _topImage = [[UIImage imageNamed:@"topImage"] stretchableImageWith...
    }

    return _topImage;
}

现在为其他图片重复这些。

与使用CALayer替代方案相比,这将更具性能(很长一段时间),特别是如果使用可伸缩图像,则内存占用空间非常小。

其他几位用户表示,这对性能,内存,设计等都不利,但它确实是获得UserExperience最佳性能的最佳方式,而不是CALayers。是的,它将使用比CALayers更多的内存,但只是略有增加,并且它将达到极限,因为只创建了几个可出列的单元格。

一些链接解释了在scrollViews中使用CALayers时的性能问题...

http://www.quora.com/iOS-Development/What-is-the-best-way-to-optimize-the-performance-of-a-non-paging-but-view-recycling-UIScrollView-involving-loading-potentially-caching-and-displaying-bundled-images

Bad performance on scroll view loaded with 3 view controllers, drawn with CALayer

::编辑::编辑回答迈克尔的问题。

  1. 在storyboard中创建一个UITableViewController(在检查器中重命名Class,使其与您的子类UITableViewController匹配 - 我将其称为MyTableViewController)。

  2. 在代码中创建一个UITableViewCell的子类(我称之为我的MyTableViewCell)。

  3. 将以上代码添加到MyTableViewCell.h文件中的属性和类型以及imageViews。

  4. 在故事板中选择TableViewController中的单元格,并将该类重命名为MyTableViewCell。还要在其上设置重用标识符。

  5. 在MyTableViewController代码中,您需要一个像这样的函数......

    -(UITableViewCell*)tableView:(UITabelView*)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath
    {
        MyTableViewCell *cell = [tableView dequeueCellWithReuseIdentifier:@"Cell"];
    
        cell.cellType = CellTypeTop; //or whichever it needs to be
        cell.textLabel.text = @"Blah";
    
        return cell;
    }
    
  6. 哦,另外一件事,在故事板中你将能够布局你的单元格你想要它看起来和链接所有标签和图像视图等...确保你将IBOutlet添加到UIImageView,以便你可以链接它在故事板中。

答案 1 :(得分:0)

确保您已导入#import <QuartzCore/QuartzCore.h>,然后您就可以开始访问UITableView的图层了。

  UITableView *yourTable =  [[UITableView alloc] initWithStyle:UITableViewStyleGrouped];

  [[yourTable layer] setCornerRadius:10.0f];
  [[yourTable layer] setShadowColor:[[UIColor blackColor] CGColor]];
  [[yourTable layer] setShadowOffset:CGSizeMake([CALayer ShadowOffSetWidthWithFloat:10.0f], [CALayer ShadowOffSetWidthWithFloat:10.0f])];
  [[yourTable layer] setShadowOpacity:[CALayer ShadowOpacity:1]];
  [[yourTable layer] setMasksToBounds:NO];
  UIBezierPath *path = [UIBezierPAth bezierPathWithRect:yourTable.bounds];
  [[yourTable layer] setShadowPath:[path CGPath]];

这将为您的表格视图添加阴影效果,阴影未被遮盖到UITableView的边界,在setCornerRadius您可以将表格的角设置为您想要的任何角落。您也可以通过

设置frame的{​​{1}}
UITableView

修改

正如另一位用户试图指出 [yourTable setFrame:CGRectMake(CGFloat x, CGFloat y, CGFloat width, CGFloat height)]; 非常慢,情况并非如此

引入了

CALayer来帮助解决动画方面的性能问题。请阅读文档。直接加载图像似乎是个好主意,但从长远来看会占用更多内存。请注意图片的内存分配question。正如您所看到的那样,它可能看起来更快,但每张图片需要CALayer,因此在加载每张图片后,您的应用将开始变慢。