Рассмотрим этот простой CardView в SwiftUI:
struct CardView: View {
let cardNumber: Int
var body: some View {
VStack {
Image("bg1")
.resizable()
.aspectRatio(contentMode: .fill)
.frame(height: 100)
.clipped()
Spacer()
Text("Card: \(cardNumber.description)")
.font(.title.bold())
Button("Test") { print("Tapped") }
.buttonStyle(.bordered)
}
.background(.green)
.frame(height: 260)
.border(.blue)
}
}
Для VStack
установлена высота 260, а для Image
— высота 100 и модель контента .fill
. Я понимаю, что нам нужно установить .clipped()
, чтобы изображение не выходило за пределы представления.
Если я визуализирую это представление отдельно, все работает нормально, т. е. нажимаю кнопку и печатаю «Нажато».
Однако, если бы я отобразил несколько CardView
, например, поместил бы это CardView
внутри VStack
или ScrollView
. Обрезанное изображение начнет перекрываться, и кнопка «Тест» больше не будет работать.
В отладчике пользовательского интерфейса я вижу, как он отображается, как показано ниже, внутри VStack
.
Может кто-нибудь объяснить, почему это происходит и как это исправить?
Я понял, что семья .clipped
не будет препятствовать действию самого изображения по касанию, вам нужно добавить .contentShape
, чтобы изображение не перегружало окружающий контекст:
Image("bg1")
...
.contentShape(Rectangle()) //<- here
ИМХО, я думаю, это из-за приоритета макета: у вас было два представления в VStack, и второе будет перекрывать первое. Тем не менее, раньше я пробовал использовать одно представление с изображением большего размера, и это все еще происходило до тех пор, пока не был добавлен .contentShape
, в случае, если у вас есть действия, то есть жест касания по всему CardView, нажатие за пределами представления (визуально) также будет запускать жест.
Спасибо @sonle, это работает! могу я продолжить: почему это работает без
.contentShape
, когда рендерится только одинCardView
?