June 10, 2024
71. Хитрость с тенями в SwiftUI
В статье 47 показывал как гибко можно настраивать тени. В этой статье покажу как можно настроить тени в горизонтальной коллекции, чтобы они не обрезались фреймом.
Макет
Предположим, что дизайнер принес нам такой макет и наша задача сверстать такую коллекцию.
Для простоты: высота коллекции всегда равна 140, радиус тени - 8.
Верстаем
На первый взгляд ничего сложного, напишем код:
ScrollView(.horizontal) {
LazyHStack(spacing: 16) {
ForEach(1..<10, id: \.self) { item in
RoundedRectangle(cornerRadius: 16)
.fill(.white)
.frame(width: 140, height: 140) // габариты ячейки по макету
.overlay {
Text("Text # \(item)")
}
.shadow(color: .blue, radius: 8)
}
}
.padding(.horizontal) // отступы по макету
}
.frame(height: 140) // высота коллекции по макету
Проблемы
- Тень накладывается на все объекты в ячейке, т.е. и на текст, и на прямоугольник
- Тени обрезаются фреймом с настройкой высоты коллекции
Исправляем тень у текста
Воспользуемся знаниями из статьи 62 про drawingGroup и добавим 1 строку, чтобы убрать тени у текста:
ScrollView(.horizontal) {
LazyHStack(spacing: 16) {
ForEach(1..<10, id: \.self) { item in
RoundedRectangle(cornerRadius: 16)
.fill(.white)
.frame(width: 140, height: 140) // габариты ячейки по макету
.overlay {
Text("Text # \(item)")
}
.drawingGroup() // <- убрали тени у текста
.shadow(color: .blue, radius: 8)
}
}
.padding(.horizontal) // отступы по макету
}
.frame(height: 140) // высота коллекции по макету
Исправляем обрезку теней
Чтобы тени не обрезались, как вариант, можно воспользоваться паддингами (добавляем две строки):
ScrollView(.horizontal) {
LazyHStack(spacing: 16) {
ForEach(1..<10, id: \.self) { item in
RoundedRectangle(cornerRadius: 16)
.fill(.white)
.frame(width: 140, height: 140) // габариты ячейки по макету
.overlay {
Text("Text # \(item)")
}
.drawingGroup() // <- убирает тень у текста
.shadow(color: .blue, radius: 8)
}
}
.padding(.horizontal) // отступы по макету
.padding(.vertical, 20) // <- балансируем для теней
}
.padding(.vertical, -20) // <- балансируем для теней
.frame(height: 140) // высота коллекции по макету
Заключение
Если у вас появятся интересные варианты решения задачи - пишите в комментариях 👍
Код для этой статьи можно посмотреть тут, а другие статьи - тут.