Подтвердить что ты не робот

Как маскировать UITableViewCells под прозрачным заголовком UITableView

Я хочу, чтобы заголовок маскировал ячейки, но не фон.

У меня есть UITableView с прозрачными заголовками и ячейками, подобными Центру уведомлений Apple (при прокрутке строки состояния на вашем iPhone). Я не могу понять, как маскировать ячейки, чтобы они не отображались под заголовком при прокрутке.

Я пробовал изменить contentInsets таблицы, и я попытался изменить фрейм заголовка View на отрицательное начало.

4b9b3361

Ответ 1

Попробуйте создать подкласс 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] является высотой HeaderView. и используйте #import <QuartzCore/QuartzCore.h> для пользовательской ячейки.

Ответ 2

Немного отредактируйте ответ Alex Markman, где вы можете пропустить создание подкласса для 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;
}

Ответ 3

@Alex Markman - ваш ответ велик и очень полезен для меня, но я обнаружил, что когда вы прокручиваете устройства сетчатки, ячейки не прокручиваются плавно. Я обнаружил, что это вызвано параметром layer 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;
}

Ответ 4

Быстрая версия

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

Ответ 5

Версия 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
    }
}

Я просто использовал это, и он работает как шарм. Я хочу поблагодарить всех на этом посту! Все голоса вокруг!

Ответ 6

У меня есть два возможных решения, без кода - просто идея:

  • не общий, должен работать с яблоком установки/дизайна, используемым в Центре уведомлений.

Сделайте заголовок секции непрозрачным, "клонируйте" фоновый рисунок таблицы в качестве фона раздела-заголовка. Поместите фоновый рисунок в зависимости от смещения заголовка раздела.


  • genereic, но, вероятно, больше проблем с производительностью. Должно работать нормально с несколькими ячейками.

Добавьте альфа-маску ко всем ячейкам. Переместите альфа-маску в зависимости от положения ячейки.


(используйте метод делегата scrollViewDidScroll для поддержания фонового рисунка/смещения альфа-маски).

Ответ 7

В итоге я установил высоту заголовка раздела до минимума и переопределил UITableView layoutSubviews, чтобы поместить заголовок в представление tableView, отрегулировав начало кадра вверх по его высоте.

Ответ 8

Версия Swift 3 не работала для меня, потому что я добавил UITableViewController в качестве подзаголовка. Поэтому мне пришлось внести некоторые изменения в расширение прокрутки.

Это также должно работать с UITableViewController, который был нажат из другого ViewController (Примечание: не проверено)

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 ячейки и отвлекаю содержимое scollViewsOffsetY.

Высота моего настраиваемого раздела - 44. Поэтому я определяю значение hideAmount для маски.

Функции ячейки нетронуты:

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
}

Ответ 9

Это не сработало бы, если бы вы хотели показывать контент за табличным представлением, но, поскольку я только пытаюсь создать закругленные заголовки с простым однотонным фоном позади них, для меня это решило имитацию прозрачности путем установки цвета фона. фонового представления заголовка к цвету фона табличного представления (или первого родительского представления с непрозрачным фоном).

Ответ 10

Или, если вам нужно только для вашего интерфейса, вы могли

измените вид таблицы, чтобы не иметь заголовков плавающих разделов

В двух быстрых и простых шагах (iOS 6):

  • Измените стиль UITableView на UITableViewStyleGrouped. (Вы можете сделать это из Storyboard/NIB или с помощью кода.)

  • Затем установите для вашего представления в виде таблицы вид на пустой вид, подобный этому [в любом методе, таком как viewDidAppear или даже в методе cellForRow (хотя я бы предпочел первый)].

yourTableView.backgroundView = [[UIView alloc] initWithFrame:listTableView.bounds];

Voila, теперь у вас есть вид в таблице, но без заголовков плавающего раздела. Заголовки разделов теперь прокручиваются вместе с ячейками, и ваши беспорядочные проблемы пользовательского интерфейса решаются!

Попробуйте это и дайте мне знать, как это происходит. Счастливое кодирование:)

EDIT: для iOS 7 просто измените стиль представления таблицы на "UITableViewStyleGrouped" и измените цвет оттенка представления на "очистить цвет".