如何屏蔽UITableView透明页眉下的UITableViewCells
我想要标题来掩盖单元格,但不是背景。
我有一个UITableView的透明标题和单元格类似于苹果的通知中心(当你向下滑动你的iPhone上的状态栏)。 我不知道如何掩盖单元格,以便它们在滚动时不显示在标题下方。
我试着改变tableview的contentInsets,并试着将标题View的框架改为负的原点。
尝试做一个UITableviewCell
的子类并添加这些方法
- (void)maskCellFromTop:(CGFloat)margin { self.layer.mask = [self visibilityMaskWithLocation:margin/self.frame.size.height]; self.layer.masksToBounds = YES; } - (CAGradientLayer *)visibilityMaskWithLocation:(CGFloat)location { CAGradientLayer *mask = [CAGradientLayer layer]; mask.frame = self.bounds; mask.colors = [NSArray arrayWithObjects:(id)[[UIColor colorWithWhite:1 alpha:0] CGColor], (id)[[UIColor colorWithWhite:1 alpha:1] CGColor], nil]; mask.locations = [NSArray arrayWithObjects:[NSNumber numberWithFloat:location], [NSNumber numberWithFloat:location], nil]; return mask; }
并在UITableView
添加这个委托方法
#pragma mark - UIScrollViewDelegate - (void)scrollViewDidScroll:(UIScrollView *)scrollView { for (iNotifyTableViewCell *cell in self.visibleCells) { CGFloat hiddenFrameHeight = scrollView.contentOffset.y + [iNotifyHeaderView height] - cell.frame.origin.y; if (hiddenFrameHeight >= 0 || hiddenFrameHeight <= cell.frame.size.height) { [cell maskCellFromTop:hiddenFrameHeight]; } } }
*请注意, [iNotifyHeaderView height]
是[iNotifyHeaderView height]
。 并为自定义单元使用#import <QuartzCore/QuartzCore.h>
。
在Alex Markman的答案上稍微编辑一下,你可以跳过创build一个UITableViewCell的子类。 这种方法的好处是你可以将它用于多个不同的UITableViewCells。
- (void)scrollViewDidScroll:(UIScrollView *)scrollView { for (UITableViewCell *cell in self.tableView.visibleCells) { CGFloat hiddenFrameHeight = scrollView.contentOffset.y + self.navigationController.navigationBar.frame.size.height - cell.frame.origin.y; if (hiddenFrameHeight >= 0 || hiddenFrameHeight <= cell.frame.size.height) { [self maskCell:cell fromTopWithMargin:hiddenFrameHeight]; } } } - (void)maskCell:(UITableViewCell *)cell fromTopWithMargin:(CGFloat)margin { cell.layer.mask = [self visibilityMaskForCell:cell withLocation:margin/cell.frame.size.height]; cell.layer.masksToBounds = YES; } - (CAGradientLayer *)visibilityMaskForCell:(UITableViewCell *)cell withLocation:(CGFloat)location { CAGradientLayer *mask = [CAGradientLayer layer]; mask.frame = cell.bounds; mask.colors = [NSArray arrayWithObjects:(id)[[UIColor colorWithWhite:1 alpha:0] CGColor], (id)[[UIColor colorWithWhite:1 alpha:1] CGColor], nil]; mask.locations = [NSArray arrayWithObjects:[NSNumber numberWithFloat:location], [NSNumber numberWithFloat:location], nil]; return mask; }
@Alex Markman – 您的回答非常好,对我来说非常有用,但是我发现当您在视网膜设备上滚动时,单元格不会平滑滚动。 我发现它是在渲染过程中由图层的locations
参数引起的:
mask.locations = [NSArray arrayWithObjects:[NSNumber numberWithFloat:location];
我稍微修改了你的代码。 也许有人会觉得它有用:
- (void)maskCellFromTop:(CGFloat)margin { self.layer.mask = [self visibilityMaskFromLocation:margin]; self.layer.masksToBounds = YES; } - (CAGradientLayer *)visibilityMaskFromLocation:(CGFloat)location { CAGradientLayer *mask = [CAGradientLayer layer]; mask.frame = CGRectMake( self.bounds.origin.x, location+self.bounds.origin.y, self.bounds.size.width, self.bounds.size.height-location); mask.colors = @[ (id)[[UIColor colorWithWhite:1 alpha:1] CGColor], (id)[[UIColor colorWithWhite:1 alpha:1] CGColor] ]; return mask; }
Swift版本
func scrollViewDidScroll(_ scrollView: UIScrollView) { for cell in tableView.visibleCells { let hiddenFrameHeight = scrollView.contentOffset.y + navigationController!.navigationBar.frame.size.height - cell.frame.origin.y if (hiddenFrameHeight >= 0 || hiddenFrameHeight <= cell.frame.size.height) { maskCell(cell: cell, margin: Float(hiddenFrameHeight)) } } } func maskCell(cell: UITableViewCell, margin: Float) { cell.layer.mask = visibilityMaskForCell(cell: cell, location: (margin / Float(cell.frame.size.height) )) cell.layer.masksToBounds = true } func visibilityMaskForCell(cell: UITableViewCell, location: Float) -> CAGradientLayer { let mask = CAGradientLayer() mask.frame = cell.bounds mask.colors = [UIColor(white: 1, alpha: 0).cgColor, UIColor(white: 1, alpha: 1).cgColor] mask.locations = [NSNumber(value: location), NSNumber(value: location)] return mask; }
Clean Swift 3版本:
extension YourViewController: UIScrollViewDelegate { func scrollViewDidScroll(_ scrollView: UIScrollView) { for cell in tableView.visibleCells { let hiddenFrameHeight = scrollView.contentOffset.y + navigationController!.navigationBar.frame.size.height - cell.frame.origin.y if (hiddenFrameHeight >= 0 || hiddenFrameHeight <= cell.frame.size.height) { if let customCell = cell as? CustomCell { customCell.maskCell(fromTop: hiddenFrameHeight) } } } } } class CustomCell: UITableViewCell { public func maskCell(fromTop margin: CGFloat) { layer.mask = visibilityMask(withLocation: margin / frame.size.height) layer.masksToBounds = true } private func visibilityMask(withLocation location: CGFloat) -> CAGradientLayer { let mask = CAGradientLayer() mask.frame = bounds mask.colors = [UIColor.white.withAlphaComponent(0).cgColor, UIColor.white.cgColor] let num = location as NSNumber mask.locations = [num, num] return mask } }
我只是用这个,它就像一个魅力。 我想感谢每个人的post! 四处投票!
我有两个可能的解决scheme,没有代码 – 只是想法:
- 不是通用的,应该与通知中心使用的设置/devise苹果一起使用。
使Section-Header不透明,将表格的背景模式克隆为Section-Header的背景。 根据节标题偏移量来定位背景图案。
- 一般,但可能更多的性能问题。 应该与less数细胞工作正常。
将Alpha蒙版添加到所有单元图层。 根据细胞位置移动Alpha Mask。
(使用scrollViewDidScroll委托方法来保持背景图案/ Alpha-Mask偏移量)。
我最终将节头的高度设置为最小,并覆盖UITableView的layoutSubviews,将标题放置在tableView的超级视图上,将框架的原点向上调整其高度。
Swift 3版本不适合我,因为我添加了UITableViewController作为子视图。 所以我不得不在scrollview的扩展中做一些改变。
这应该也适用于从另一个ViewController推送的UITableViewController(注:未经testing)
extension NavNotitionTableViewController { override func scrollViewDidScroll(_ scrollView: UIScrollView) { for cell in tableView.visibleCells { let calculatedY = cell.frame.origin.y - scrollView.contentOffset.y; if let customCell = cell as? NavNotitionTableViewCell { if(calculatedY < 44 && calculatedY > 0){ let hideAmount = 44 - calculatedY; if let customCell = cell as? NavNotitionTableViewCell { customCell.maskCell(fromTop: hideAmount) } }else if (calculatedY > 0){ //All other cells customCell.maskCell(fromTop: 0) }else if (calculatedY < 0){ customCell.maskCell(fromTop: cell.frame.height); } } } } }
在这个例子中,我首先获取单元格的Y原点,并分散scollViews contentOffsetY。
我的自定义部分的高度是44.所以我定义掩码的hideAmount值。
单元格function是不变的:
public func maskCell(fromTop margin: CGFloat) { layer.mask = visibilityMask(withLocation: margin / frame.size.height) layer.masksToBounds = true } private func visibilityMask(withLocation location: CGFloat) -> CAGradientLayer { let mask = CAGradientLayer() mask.frame = bounds mask.colors = [UIColor.white.withAlphaComponent(0).cgColor, UIColor.white.cgColor] let num = location as NSNumber mask.locations = [num, num] return mask }
或者,如果你所需要的只是让你的界面看起来不错,你可以
更改您的表格视图不具有浮动部分标题
通过两个快速简单的步骤(iOS 6):
-
将您的UITableView样式更改为UITableViewStyleGrouped。 (您可以通过Storyboard / NIB或通过代码来完成此操作。)
-
接下来,将你的tableview的背景视图设置为一个空的视图,就像[ viewDidAppear或者cellForRow方法(尽pipe我更喜欢前者)]。
yourTableView.backgroundView = [[UIView alloc] initWithFrame:listTableView.bounds];
瞧,现在你有你的表格视图 – 但没有浮动部分标题。 您的部分标题现在滚动单元格和您杂乱的UI问题解决了!
请尝试一下,让我知道如何去。 快乐编码:)
编辑:对于iOS 7,只需将表视图样式更改为“ UITableViewStyleGrouped ”,并将视图的色调更改为“清除颜色”。