6

I have searched this forum, Google and other forums and have not found an the answer to my particular issue.

Basically, I have a UIView which contains UITableView. I followed this tutorial and it was partially successful. The problem is the gradient. I have a background image behind the UITableView. So as the cell nears the gradient, I want the background to be showing, instead of the white.

I also found this post which which is where I found the tutorial, but I didn't want to hijack that post with my own questions for matt.

Any help in the right direction would be great!

EDIT1: I know I can use another image with the background image and the middle cut out, but I'm looking for a solution which AVOIDS using PNGs, if possible.

EDIT2: Here's an image of what I get now:

enter image description here

EDIT3:

Here is my code:

Header:

@interface MyView : UIViewController  {
    CAGradientLayer *_maskLayer;
    UITableView *_tableView;
}

@property (nonatomic, retain) CAGradientLayer *maskLayer;
@property (nonatomic, retain) IBOutlet UITableView *tableView;

Implementation:

@implementation HighScoresView_iPhone

@synthesize tableView = _tableView;
@synthesize maskLayer = _maskLayer;

- (void)viewWillAppear:(BOOL)animated {

    [super viewWillAppear:animated];

    if (![self maskLayer]) {
        [self setMaskLayer:[CAGradientLayer layer]];
        CGColorRef outerColor = [UIColor colorWithWhite:1.0 alpha:1.0].CGColor;
        CGColorRef innerColor = [UIColor colorWithWhite:1.0 alpha:0.0].CGColor;

        [[self maskLayer] setColors:[NSArray arrayWithObjects:
                                     (id)outerColor, 
                                     (id)innerColor, 
                                     (id)innerColor, 
                                     (id)outerColor, 
                                     nil
                                     ]
         ];
        [[self maskLayer] setLocations:[NSArray arrayWithObjects:
                                       [NSNumber numberWithFloat:0.0], 
                                       [NSNumber numberWithFloat:0.2], 
                                       [NSNumber numberWithFloat:0.8], 
                                       [NSNumber numberWithFloat:1.0], 
                                       nil
                                       ]
        ];
        [[self maskLayer] setBounds:CGRectMake(0, 0, [[self scoreTableView] frame].size.width, [[self scoreTableView] frame].size.height)];
        [[self maskLayer] setAnchorPoint:CGPointZero];
        [[[self scoreTableView] layer] addSublayer:[self maskLayer]];
    }
}
Community
  • 1
  • 1
RoLYroLLs
  • 3,113
  • 4
  • 38
  • 57
  • It's not suggested for optimization reasons, but have you tried `cell.backgroundView.backgroundColor = [UIColor clearColor]` or the same for `contentView` or for `cell` itself, or some combination thereof? – bshirley Feb 02 '12 at 01:12
  • yes, my cells have a clear background. I can see the background when they are in the center. But when they are near the top or bottom, the gradient I created following the tutorial i mentioned, I see white, instead of the content fading out. – RoLYroLLs Feb 02 '12 at 01:16
  • I added an image to show what it currently looks like. – RoLYroLLs Feb 02 '12 at 01:25
  • 1
    (image helped) it seems apparent that the white gradient is above the cells, not behind, how are you placing it there? – bshirley Feb 02 '12 at 02:21
  • The tutorial you followed's intent was to hide the cells behind the white when it scrolled to the top/bottom. They have a white background. If you want it to not appear white, you need to use the same image as the background with the alpha 1.0 at the edge, fading to 0.0 away from the edge (one cell height would likely be good). – bshirley Feb 02 '12 at 02:30
  • I didn't think of that!. Tell me if my logic is wrong here: apply the gradient above to the image and then apply that image as a mask to the tableview? – RoLYroLLs Feb 02 '12 at 02:55
  • not really sure, you might need to add a view to the scrollview's content view, then change it's location in the content every time the view scrolls (this is how you float something above a table view) - it would take some experimentation – bshirley Feb 02 '12 at 15:08
  • @bshirley: You can just place the obscuring views in front the scroll view in the scroll view's parent view--then you never have to do any repositioning – nielsbot Feb 02 '12 at 20:32
  • 1
    @RoLYroLLs you want your content to fade to the background at the top and bottom of the scroll view? Sounds like your best bet it to cut out part of your background view (in the area where you want your cells to fade out), apply a transparency gradient, then position the cut out bits in front of your scroll view (in the scroll view's superview) – nielsbot Feb 02 '12 at 20:34
  • @nielsbot - yes, that's how i would have thought to do it - but saw a WWDC video with the scrollview trick (and that was in my head) - don't recall if they had a justification – bshirley Feb 02 '12 at 21:10
  • @nielsbot Yes I was trying to get away from the image cut out, so if i decide to move it around a bit I don't have to redo the image cut-out. Oh wells. It would have been nice to do it purely by code, this way it's dynamic to the size of the object. So basically for now, if it was a single color background it will work fine by code. otherwise cut out the image. Also, I didn't think about adding it to the scrollview's parent. I currently have the maskLayer on the scrollView and using it's delegate to reposition it where it is, like bshirley says. Thanks for that. – RoLYroLLs Feb 04 '12 at 00:21
  • You could do it entirely in code if you wanted to. You can draw the background image into a bitmap context to which you have applied a mask--now you will have a context containing your "fadeout image" – nielsbot Feb 06 '12 at 21:59
  • Interesting. I'll have to look this up, but if you give me some simple code to work with as a new answer and I'll give you the check. Thanks again – RoLYroLLs Feb 07 '12 at 00:29

4 Answers4

24

You can do this with the CALayer mask property. But you can't set the mask on the table view's own layer because that mask will scroll with the rows of the table. Instead, put your table view inside a new superview (of class UIView) that you create just for this. Call it tableMaskView.

The new superview should have its backgroundColor property set to UIColor.clearColor and its opaque property set to NO. Then you can set its mask like this:

CAGradientLayer *gradient = [CAGradientLayer layer];
gradient.frame = self.tableMaskView.bounds;
gradient.colors = [NSArray arrayWithObjects:
    (__bridge id)UIColor.clearColor.CGColor,
    UIColor.whiteColor.CGColor,
    UIColor.whiteColor.CGColor,
    UIColor.clearColor.CGColor,
    nil];
gradient.locations = [NSArray arrayWithObjects:
    [NSNumber numberWithFloat:0],
    [NSNumber numberWithFloat:1.0/16],
    [NSNumber numberWithFloat:15.0/16],
    [NSNumber numberWithFloat:1],
    nil];
self.tableMaskView.layer.mask = gradient;

Using a layer mask is not the most efficient way, but it's the easiest to program. Test whether it's fast enough.

rob mayoff
  • 375,296
  • 67
  • 796
  • 848
  • Hi Rob, thanks for your code, but what it is doing is putting a white block in the middle and the outsides (top and bottom) are gradient into clear. This hides the content in the middle. – RoLYroLLs Feb 04 '12 at 00:36
  • You need to set tableMaskView.opaque to NO and tableMaskView.backgroundColor to clearColor. – rob mayoff Feb 04 '12 at 02:41
  • yup, did that. Anything else? – RoLYroLLs Feb 07 '12 at 00:30
  • Brilliant - thanks. I've been messing about with this for a day - if I'd found this earlier it would have been 5 minutes. Works a treat. – SomaMan Feb 05 '13 at 09:04
2

Swift 3 version of rob mayoff's answer:

let gradient = CAGradientLayer()
gradient.frame = tableMaskView.bounds
gradient.colors = [UIColor.clear.cgColor, UIColor.white.cgColor, 
                   UIColor.white.cgColor, UIColor.clear.cgColor]
gradient.locations = [0 as NSNumber, 1.0/16.0 as NSNumber, 
                      15.0/16.0 as NSNumber, 1 as NSNumber]
tableMaskView.layer.mask = gradient
boraski
  • 31
  • 5
0

Replace this line:

[[[self scoreTableView] layer] addSublayer:[self maskLayer]];

With this one:

self.scoreTableView.layer.mask = self.maskLayer;

(Or if you insist on your syntax-styling even thought I can't see why) :

[[[self scoreTableView] layer] setMask:[self maskLayer]];

Also this answer might help you.

Community
  • 1
  • 1
Aviel Gross
  • 9,770
  • 3
  • 52
  • 62
0

Sounds like the background color of your table view is set to white. Try setting the background of your table view to transparent:

tableView.backgroundColor = [ UIColor clearColor ] ;
tableView.opaque = NO ;
nielsbot
  • 15,922
  • 4
  • 48
  • 73
  • (you can do this in interface builder) – nielsbot Feb 02 '12 at 01:51
  • yeah I have the background of the 'UITableView' clear. You can tell because in the image you see the black and teal background discs. However I did have opaque set to 'YES'. Although when set to 'NO' same result. – RoLYroLLs Feb 02 '12 at 02:21