Зачем нужны нестандартные фигуры (Shapes) в самых обычных SwiftUI View?
Всем привет! Давайте сразу к делу.
Есть такой макет.
Не буду подробно останавливаться на верстке, весьма обычный элемент.
Высота верхней половины динамическая, зависит от наполнения и, в частности, от рисунка внутри.
Верхнюю и нижнюю половины поместим в VStack, цвет у верхней выкрасим через ZStack, серую рамку вокруг сделаем через .background:
VStack {
ZStack {
Rectangle()
.fill(.indigo.opacity(0.4))
…
}
VStack {
…
}
…
}.background(
RoundedRectangle(cornerRadius: 16)
.stroke(.gray, lineWidth: 1)
)
Выход цветной подложки сверху за пределы рамки классически исправляем через .cornerRadius(16):
VStack {
…
}.background(
RoundedRectangle(cornerRadius: 16)
.stroke(.gray, lineWidth: 1)
)
.cornerRadius(16) // <= здесь
Итоговый результат действительно совпадает с макетом:
И, казалось бы, все хорошо, но позже дизайнер предложил смещать вертикально рисунок, чтобы картинка специально выходила за пределы рамки. Ну что ж, добавим .offset(y: …) к изображению рисунка:
И вот сталкиваемся с сайд-эффектом модификатора .cornerRadius(): он обрезает вью, к которому он применяется.
Ок, ситуацию исправило бы применение .cornerRadius не ко всему вью, а только к ZStack с цветом:
ZStack {
Rectangle()
.fill(.indigo.opacity(0.4))
.cornerRadius(16) // <= здесь
…
}
Но тогда закругляются и нижние углы у прямоугольника:
Значит нужен прямоугольник, у которого можно было бы настроить, какие углы закруглять. Из коробки такого нет. Отрисуем сами! Библиотеку с новой и другими фигурами можно найти здесь.
Применим расширение для View, построенного вокруг нового shape, для этого импортируем библиотеку:
import Shapes
…
ZStack {
Rectangle()
.fill(.indigo.opacity(0.4))
.cornerRadius(16, corners: .tops) // <= здесь
…
}
И вот теперь все хорошо:
А если нужен кроп, то применим модификатор .clipped ко всей вью:
VStack {
ZStack {
Rectangle()
.fill(.indigo.opacity(0.4))
.cornerRadius(16, corners: .tops) // Здесь
…
}
VStack {
…
}
…
}.background(
RoundedRectangle(cornerRadius: 16)
.stroke(.gray, lineWidth: 1)
)
.clipped() // <= здесь
Результат будет тот же:
На этом все!✌🏻
Не забывайте подписываться на github и на канал в телеграмме, посвященный мобильной разработке.