Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Customizing tableView: Corner radius, decreased width and shadow

This is what I want to do:

enter image description here

As you can see i want to:

  1. Decrease the width of the tableView (I want more margin on the sides than the grouped tableView provides)

  2. Corner radius (bigger radius than the default for grouped tableView)

  3. Drop shadow around the table and a special shadow beneath the last cell

like image 892
Michael Avatar asked Oct 07 '22 11:10

Michael


1 Answers

You can do this by "drawing" the backgroundView of the cells yourself.

I'd recommend getting an image to use as the background (if the cells are all the same height).

You'll need three images.

A "top" image with the top corners rounded. A "bottom" image with the bottom corners rounded and the drop shadow how you want it. And a "middle" image with no rounded corners.

If the cells don't have any texture or gradient within them then you can use stretchable images to reduce the memory footprint of them.

Then I would subclass the UITableViewCell and override the backgroundView to add a UIImageView. I'd also provide an accessor method to change the type (top, middle, bottom) of the cell.

Each cell can then have three placeHolder properties of a UIImage (topImage, bottomImage and middleImage). When the type of the cell is changed these can be accessed (use lazy instantiation to make sure they are only loaded once and only when needed) and then set the backgroundVIew image to be the required image.

Something like this...

In the UITableViewCell subclass define a type enum...

typedef enum {
    CellTypeTop,
    CellTypeMiddle,
    CellTypeBottom
} cellType;

Then a property for the type...

@property (nonatomic) cellType cellType

Then in the .m ...

Define some more internal properties...

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

Then add the imageView (only once)...

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

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

Now when the type is changed...

- (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;
    }
}

Finally a lazy instantiation of the images...

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

    return _topImage;
}

Now repeat these for the other images.

This will be more performant (by a long way) than using a CALayer alternative and, especially if using the stretchable images, will have a very small memory footprint.

Several other users have said that this is not good for performance, memory, design, whatever, but it really is the best way to get the best performance for UserExperience than CALayers. Yes, it will use more memory than CALayers but only marginally and it will get to a limit as there are only a few dequeueable cells created.

A couple of links explaining performance issues when using CALayers in scrollViews...

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

::EDIT:: Edit to answer Michael's question.

  1. In the storyboard create a UITableViewController (rename the Class in the inspector so that it matches your subclass UITableViewController - I'll call it MyTableViewController).

  2. Create a subclass of UITableViewCell (I'll call mine MyTableViewCell) in the code (i.e. the .h and .m).

  3. Add the above code to do with properties and types and imageViews to your MyTableViewCell.h file.

  4. In the storyboard select the cell in the TableViewController and rename the class to MyTableViewCell. Also set the reuse identifier on it.

  5. In the MyTableViewController code you will need a function like this...

    -(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;
    }
    

Oh, another thing, in the storyboard you will be able to layout your cell how you want it to look and link up all the labels and imageviews etc... Make sure you add IBOutlet to the UIImageView so that you can link it up in the storyboard.

like image 124
Fogmeister Avatar answered Oct 10 '22 04:10

Fogmeister