Добавление градиентного слоя в элемент ячейки табличного представления в зависимости от пути индекса ячейки - PullRequest
1 голос
/ 30 сентября 2019

Мне трудно добавить слой градиента в качестве фона для элемента внутри ячейки табличного представления. Уровень градиента зависит от пути индекса ячейки. У меня есть enum цветов, который использует indexPath в качестве rawValue. Требуемый результат выглядит просто: this

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

func setGradientBackground(colorOne: UIColor, colorTwo: UIColor, name: String) {
    let gradient = CAGradientLayer()
    gradient.frame = bounds
    gradient.colors = [colorOne.cgColor, colorTwo.cgColor]
    gradient.locations = [0, 1]
    gradient.startPoint = CGPoint(x: 1, y: 1)
    gradient.endPoint = CGPoint(x: 0, y: 0)
    gradient.name = name
    layer.insertSublayer(gradient, at: 0)
}

Чтобы добавить градиент к элементу в ячейке табличного представления, попытались несколько вещей. В настоящее время я перебираю видимые ячейки, чтобы добавить слой. Я пытался позвонить с viewWillLayoutSubviews. Это единственный раз, когда я видел применение градиентов.

Я видел две проблемы. Приложение становится непригодным для использования, потому что я думаю, что эта функция вызывается более или менее непрерывно, когда что-то в представлении изменяется. А также слои рисуются поверх всего остального в ячейках.

func configTableCells() {
    guard let cells = self.tableView.visibleCells as? [GroupTableCell] else {return}
    for (i, cell) in cells.enumerated() {
        if shouldAddSubLayer(cell) {
            guard let colorOne = Colors(rawValue: i)?.classicColor,
                let colorTwo = Colors(rawValue: i)?.alternativeColor else {continue}
            cell.taskInfoCollectionView.setGradientBackground(colorOne: colorOne,
                                                              colorTwo: colorTwo,
                                                              name: cellLayerName)
        }
    }
}

Я пытался добавить слой в cellForRowAt, а также willDisplay Cell, но это не сработало. Я считаю, что это потому, что ячейка еще не «существует», поэтому добавление слоя не имеет значения.

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: groupCellId, for: indexPath) as! GroupTableCell
    cell.groupNameLabel.text = "Group Name"
    cell.setCollectionViewDataSourceDelegate(self, forRow: indexPath.row)
    if shouldAddSubLayer(cell) {
        if let colorOne = Colors(rawValue: indexPath.row)?.classicColor,
            let colorTwo = Colors(rawValue: indexPath.row)?.alternativeColor {
        cell.taskInfoCollectionView.setGradientBackground(colorOne: colorOne,
                                                          colorTwo: colorTwo,
                                                          name: cellLayerName)
        }
    }
    return cell
} 

Также я включил эту функцию, потому что я читаю на другой вопрос stackOverflow, я должен проверить, если ячейка ужеимеет слой, чтобы избежать его непрерывного добавления. (Я не могу связать вопрос, поскольку не могу найти его сейчас)

func shouldAddSubLayer(_ cell: GroupTableCell) -> Bool {
    guard let sublayers = cell.layer.sublayers else {return true}
    return sublayers.filter({ $0.name == cellLayerName }).count == 0
}

Любые предложения о том, как получить этот рабочий прием, спасибо.

Ответы [ 2 ]

0 голосов
/ 30 сентября 2019

Для тех, кто может найти это полезным, изменения, необходимые для его работы ..

Используя визуальный эффект, Бен предложил мне, чтобы я смог заставить это работать. Я никогда не использовал визуальные эффекты, поэтому точно не знаю, почему это работает. Снова, вероятно, есть некоторые улучшения, которые мне нужны

В пользовательском классе ячеек таблицы я добавил UIVisualEffectView. В его представлении содержимого я добавил элемент, фон которого я хотел изменить.

Добавьте любые подпредставления в свойство contentView представления визуального эффекта. Не добавляйте подпредставления непосредственно в само представление визуальных эффектов

lazy var visualEffectView: UIVisualEffectView = {
    let v = UIVisualEffectView()
    v.translatesAutoresizingMaskIntoConstraints = false
    v.contentView.addSubview(taskInfoCollectionView)
    NSLayoutConstraint.activate([
        taskInfoCollectionView.topAnchor.constraint(equalTo: v.topAnchor),
        taskInfoCollectionView.leadingAnchor.constraint(equalTo: v.leadingAnchor),
        taskInfoCollectionView.trailingAnchor.constraint(equalTo: v.trailingAnchor),
        taskInfoCollectionView.bottomAnchor.constraint(equalTo: v.bottomAnchor),
    ])
    return v
}()

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

func addGradient(_ i: Int, _ cell: GroupTableCell) {
    guard let colorOne = Colors(rawValue: i)?.classicColor,
        let colorTwo = Colors(rawValue: i)?.alternativeColor else {return}
    cell.visualEffectView.contentView.setGradientBackground(colorOne: colorOne,
                                                      colorTwo: colorTwo,
                                                      name: cellLayerName)
}

Мне все еще нужно было добавить функцию к viewWillLayoutSubviews. Это для настройки ячеек, которые cellForRowAt не делает. Свойство setGradients изначально имеет значение true, но затем сразу устанавливается на false, поэтому оно не вызывается непрерывно, как раньше.

var setGradients = true    

override func viewWillLayoutSubviews() {
    super.viewWillLayoutSubviews()
    if setGradients {
        configTableCells()
        setGradients = false
    }
}

func configTableCells() {
    guard let cells = self.tableView.visibleCells as? [GroupTableCell] else {return}
    for (i, cell) in cells.enumerated() {
        if shouldAddSubLayer(cell) {
            addGradient(i, cell)
        }
    }
}

Затем, наконец, в cellForRowAt это, кажется, заботится обо всем остальном и обо всемКажется, работает без задержек.

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: GROUP_CELL_ID, for: indexPath) as! GroupTableCell
    cell.groupNameLabel.text = "Group Name"
    cell.setCollectionViewDataSourceDelegate(self, forRow: indexPath.row)
    addGradient(indexPath.row, cell)
    return cell
}

Я пробовал это с использованием UIView, а не UIVisualEffectView. но градиенты снова перекрывают содержимое ячейки. поэтому UIVisualEffectView требуется

0 голосов
/ 30 сентября 2019

Попробуйте с помощью VisualEffect

добавить следующий код в ViewDidLoad()

if (!UIAccessibilityIsReduceTransparencyEnabled()) {
tableView.backgroundColor = UIColor.clear
let blurEffect = UIBlurEffect(style: .light)
let blurEffectView = UIVisualEffectView(effect: blurEffect)
tableView.backgroundView = blurEffectView

//if inside a popover
if let popover = navigationController?.popoverPresentationController {
    popover.backgroundColor = UIColor.clear
}

//if you want translucent vibrant table view separator lines
tableView.separatorEffect = UIVibrancyEffect(blurEffect: blurEffect)}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...