2

I am trying to add the vibrancy effect to the text label of my table view cell and it sort of works, but not exactly right.

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"UITableViewCell"];
    NSDictionary *jobDictionary = [self.jobs objectAtIndex:[indexPath row]];

    if (cell == nil) {
        cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"UITableViewCell"];
    }

    if (cell) {
        cell.backgroundColor = [UIColor clearColor];
        cell.textLabel.textColor = [UIColor whiteColor];

        cell.textLabel.text = [jobDictionary objectForKey:@"job"];

        UIBlurEffect *blur = [UIBlurEffect effectWithStyle:UIBlurEffectStyleDark];
        UIVisualEffectView *blurView = [[UIVisualEffectView alloc]initWithEffect:blur];
        blurView.frame = cell.bounds;
        [cell addSubview:blurView];
        UIVisualEffectView *vibrantView = [[UIVisualEffectView alloc]initWithEffect:[UIVibrancyEffect effectForBlurEffect:blur]];
        vibrantView.frame = blurView.bounds;
        [vibrantView.contentView addSubview:cell.textLabel];

        [blurView.contentView addSubview:vibrantView];
    }

    return cell;
}

enter image description here

Isuru
  • 30,617
  • 60
  • 187
  • 303
raginggoat
  • 3,570
  • 10
  • 48
  • 108

1 Answers1

0

I think I see two major issues with your code. The first issue seems to be the fact that cells in cellForRowAtIndexPath assume a width of 320 when dequeued for display on an iPhone 4 or 5 screen size. If that screen shot is taken from a 6 or 6+, this would explain the weird gap. Somewhere after this method, the cell resizes to accommodate the full width of the table. That means that when you set blurView.frame = cell.bounds, the bounds at this point are actually too narrow. Hypothetically you could fix this by moving that code into the following method with one major caveat.

-(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath

While adding your blur view here should get you the proper frame, adding a subview in either of these methods will lead to major problems as the cell is recycled. Every time that cell is dequeued, a new subview will get added to it and they will continue to stack up over time. This will cause visual issues if they aren't totally opaque and it will also leave the potential for your cell to require a HUGE amount of memory because you could in theory be stacking hundreds of subviews on a cell as the table scrolls.

I think the best solution to your problem would be to subclass UITableViewCell and add the view on -initWithStyle:reuseIdentifier:. There you can also constrain that view to top, bottom, leading, and trailing of the superview to ensure it will always resize correctly. An alternative is setting the frame of the subview in -layoutSubviews of your cell subclass.

Doing this ensures the view is added only once and the frame will be what you expect.

Dare
  • 2,497
  • 1
  • 12
  • 20
  • Your assumption about screen size is correct. I just looked at it on an iPhone 5 and it looks like I want it to. – raginggoat May 12 '15 at 17:51
  • Yeah, it is an issue I run into all the time. -willDisplayCell could work fine for you if you figure out how to make sure the view is only added once. An alternative to subclassing, if you are really trying to avoid it for some reason, might be to give the view you're adding a tag and only adding it if the cell doesn't contain a subview with that tag. The problem then is that you will be iterating over that cell's subviews in a method that really needs to get its work done as quickly as possible to avoid making the table sluggish. – Dare May 12 '15 at 17:56