Странное поведение тени UITableViewCell

#ios #swift #uitableview #calayer #shadow

#iOS #swift #uitableview #calayer #тень

Вопрос:

Я пытаюсь добавить тень к одной UITableViewCell. Я использую этот код в своем пользовательском подклассе cell:

 override func layoutSubviews() {
    super.layoutSubviews()

    layer.masksToBounds = false
    layer.shadowOffset = CGSize(width: 0, height: 1)
    layer.shadowColor = UIColor.black.cgColor
    layer.shadowOpacity = 0.9
    layer.shadowRadius = 10
    layer.shadowPath = CGPath(rect: bounds, transform: nil)
}
  

Но тень обычно появляется только на нижнем / верхнем краю ячейки и меняется во время прокрутки.

Это то, что он делает

Кто-нибудь может мне помочь?

Комментарии:

1. Ваш теневой путь должен находиться в пределах вашей ячейки. Вы устанавливаете shadowRadius значение 10, но путь тени — это ваша cell.bounds, тогда тень выходит за пределы вашей ячейки, следовательно, вы получаете такое поведение.

Ответ №1:

Вы не видите тень, потому что ячейка выше / ниже находится выше в иерархии представлений в зависимости от того, была ли она удалена из очереди до или после вашей пользовательской ячейки. Проверьте View-Hierarchy-Debugger в Xcode, чтобы определить проблему.

У вас есть несколько возможных решений, но я изложу 2 из них здесь:

  1. Вы можете использовать bringSubviewToFront в своем tableView , чтобы убедиться, что ваша пользовательская ячейка всегда находится сверху.
 override func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
    if cell.isKind(of: MyCustomShadowCell.self) {
        tableView.bringSubviewToFront(cell)
    }
}
  
  1. Другим решением было бы установить layer.zPosition значение ячейки на что-то высокое, чтобы оно всегда было сверху. Имо, это немного халтурно, но если вы хотите попробовать : layer.zPosition = CGFloat.greatestFiniteMagnitude .

Комментарии:

1. Большое вам спасибо :), bringSubviewToFront решил мою проблему. Я боролся с этим в течение нескольких часов.

Ответ №2:

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

Комментарии:

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

Ответ №3:

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

Попробуйте изменить эту строку кода

 layer.shadowPath = CGPath(rect: bounds, transform: nil)
  

к этому

 layer.shadowPath = CGPath(rect: .init(x: 0,
                                  y: 10,
                                  width: contentView.bounds.width,
                                  height: contentView.bounds.height - 20),
                      transform: nil)
  

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

Мое второе предложение для вас — создать другое родительское представление для хранения вложенных представлений ячеек. Затем добавьте это в качестве подвида вашей ячейки contentView и примените тень к слою родительского представления вместо ячейки contentView . Убедитесь, что родительский вид имеет отступ 10 сверху и снизу, и вы добьетесь того, чего хотите.