Fade Edges of Uitableview

ios uitableview fade bottom cell and top cell as you scroll

The issue is that the scroll event will not always happen frequently enough that a cell that scrolls into view will go from the faded alpha to an alpha of 1.0 as it scrolls from the top/bottom to the middle. But when you scroll really quickly, the scrollViewDidScroll isn't called frequently enough to ensure that this is the case. And your loop that apparently is attempting to reset the alpha is updating the alpha of the wrong view (contentView rather than the cell itself).

You can remedy this by replacing your existing for loop:

for (UITableViewCell *cell in visibleCells) {
cell.contentView.alpha = 1.0;
}

With

for (UITableViewCell *cell in visibleCells) {
cell.alpha = 1.0;
}

Or, alternatively, eliminate that loop from there and then replace the lines that set the alpha of the top and bottom cells:

if (topCell) {
topCell.alpha = topCellOpacity;
}
if (bottomCell) {
bottomCell.alpha = bottomCellOpacity;
}

With:

for (UITableViewCell *cell in self.tableView.visibleCells) {
if (cell == topCell) {
cell.alpha = topCellOpacity;
} else if (cell == bottomCell) {
cell.alpha = bottomCellOpacity;
} else {
cell.alpha = 1.0;
}
}

By the way, another way to achieve a similar effect is to apply a gradient mask to the whole tableview and retire the scrollViewDidScroll method. The only trick here is that you cannot apply the gradient mask to the table view, itself (or else the gradient will scroll with the table view), but rather put the tableview inside some container UIView, and then apply the mask to that:

- (void)viewDidAppear:(BOOL)animated
{
CAGradientLayer *gradient = [CAGradientLayer layer];
gradient.frame = self.containerView.bounds;
gradient.colors = @[(id)[UIColor clearColor].CGColor,
(id)[UIColor whiteColor].CGColor,
(id)[UIColor whiteColor].CGColor,
(id)[UIColor clearColor].CGColor];
gradient.locations = @[@0.0, @0.1, @0.9, @1.0];
self.containerView.layer.mask = gradient;
}

This is admittedly a slightly different effect, but sometimes it's desirable. It just depends upon what you're shooting for.

How to fade the content of cell of table view which reaches at the top while scrolling?

For anyone who wants it, here's some ready-to-go copy/paste-able code that is fully working:

Best Part: This code is only reliant on ONE outside property: self.tableView, so just make sure that's set up and you're good to go!

Just stick this method in your view controller somewhere:

#pragma mark - Scroll View Delegate Methods

- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
// Fades out top and bottom cells in table view as they leave the screen
NSArray *visibleCells = [self.tableView visibleCells];

if (visibleCells != nil && [visibleCells count] != 0) { // Don't do anything for empty table view

/* Get top and bottom cells */
UITableViewCell *topCell = [visibleCells objectAtIndex:0];
UITableViewCell *bottomCell = [visibleCells lastObject];

/* Make sure other cells stay opaque */
// Avoids issues with skipped method calls during rapid scrolling
for (UITableViewCell *cell in visibleCells) {
cell.contentView.alpha = 1.0;
}

/* Set necessary constants */
NSInteger cellHeight = topCell.frame.size.height - 1; // -1 To allow for typical separator line height
NSInteger tableViewTopPosition = self.tableView.frame.origin.y;
NSInteger tableViewBottomPosition = self.tableView.frame.origin.y + self.tableView.frame.size.height;

/* Get content offset to set opacity */
CGRect topCellPositionInTableView = [self.tableView rectForRowAtIndexPath:[self.tableView indexPathForCell:topCell]];
CGRect bottomCellPositionInTableView = [self.tableView rectForRowAtIndexPath:[self.tableView indexPathForCell:bottomCell]];
CGFloat topCellPosition = [self.tableView convertRect:topCellPositionInTableView toView:[self.tableView superview]].origin.y;
CGFloat bottomCellPosition = ([self.tableView convertRect:bottomCellPositionInTableView toView:[self.tableView superview]].origin.y + cellHeight);

/* Set opacity based on amount of cell that is outside of view */
CGFloat modifier = 2.5; /* Increases the speed of fading (1.0 for fully transparent when the cell is entirely off the screen,
2.0 for fully transparent when the cell is half off the screen, etc) */
CGFloat topCellOpacity = (1.0f - ((tableViewTopPosition - topCellPosition) / cellHeight) * modifier);
CGFloat bottomCellOpacity = (1.0f - ((bottomCellPosition - tableViewBottomPosition) / cellHeight) * modifier);

/* Set cell opacity */
if (topCell) {
topCell.contentView.alpha = topCellOpacity;
}
if (bottomCell) {
bottomCell.contentView.alpha = bottomCellOpacity;
}
}
}

Don't forget to add <UIScrollViewDelegate> to your class's '.h' file!

You may also want to put a call to this method somewhere in your viewDidLoad method like this: [self scrollViewDidScroll:self.tableView]; so that the bottom cell will start out faded (since it's normally cut off by the table view edge).

TIP: Set your table view separator style to none (self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;), or create your own separators as images and add them as a subview to your cells, so that you don't get the unpleasant effect of the separators disappearing without fading.

Works just as well with smaller than full-screen table views.

Fading out any content which approaches edges of UIScollView

Similar to what was done in the Cocoanetics post you link to, you can create a CAGradientLayer to cover your scroll view. Make it fade out to the left, right, top and bottom edges, using the background color of your scroll view (in my example, white):

   CGColorRef innerColor = [UIColor colorWithWhite:1.0 alpha:0.0].CGColor;
CGColorRef outerColor = [UIColor colorWithWhite:1.0 alpha:1.0].CGColor;

// first, define a horizontal gradient (left/right edges)
CAGradientLayer* hMaskLayer = [CAGradientLayer layer];
hMaskLayer.opacity = .7;
hMaskLayer.colors = [NSArray arrayWithObjects:(id)outerColor,
(id)innerColor, (id)innerColor, (id)outerColor, nil];
hMaskLayer.locations = [NSArray arrayWithObjects:[NSNumber numberWithFloat:0.0],
[NSNumber numberWithFloat:0.15],
[NSNumber numberWithFloat:0.85],
[NSNumber numberWithFloat:1.0], nil];
hMaskLayer.startPoint = CGPointMake(0, 0.5);
hMaskLayer.endPoint = CGPointMake(1.0, 0.5);
hMaskLayer.bounds = self.scrollView.bounds;
hMaskLayer.anchorPoint = CGPointZero;

CAGradientLayer* vMaskLayer = [CAGradientLayer layer];
// without specifying startPoint and endPoint, we get a vertical gradient
vMaskLayer.opacity = hMaskLayer.opacity;
vMaskLayer.colors = hMaskLayer.colors;
vMaskLayer.locations = hMaskLayer.locations;
vMaskLayer.bounds = self.scrollView.bounds;
vMaskLayer.anchorPoint = CGPointZero;

// you must add the masks to the root view, not the scrollView, otherwise
// the masks will move as the user scrolls!
[self.view.layer addSublayer: hMaskLayer];
[self.view.layer addSublayer: vMaskLayer];

Disclaimer: this does sort of double-up the gradient/fade at the four corners. You can take a look at the results and decide whether they're good enough for you. If not, you could also try drawing a transparent image in something like Photoshop, and adding a UIImageView subview on top as the mask, using the image you drew.

Sample Image

Youtube screen capture

Fade UIImageView as it approaches the edges of a UIScrollView

You can definitely implement something along the lines of #2. It'd be something similar to what the tutorial describes. The alpha transition however won't be as smooth as using the gradient layer mentioned in the tutorial or using an image since the entire icon would have the same alpha. How much discernible the difference is depends on the size of your icons. Smaller icons, very few will be able to tell the difference. Larger icons the difference would be quite clear.

You'd have to implement the

  • (void)scrollViewDidScroll:(UIScrollView *)scrollView

method in your scroll view's delegate class. This method will get called every time the scroll view changes the location of its content. In this method you can call its subviews and adjust their alphas as required. To optimize it a bit instead of calling the alpha adjustments on all the elements you can just update the subviews which are still partially/completely visible.

EDIT: to figure out which views to adjust you'll use the contentOffset property of the scrollView that gets passed as a parameter in the above method.



Related Topics



Leave a reply



Submit