SwiftUI: ViewModifier, где контент - это форма
Следующий код работает нормально. Так что, действительно, у меня все хорошо... Но я хотел узнать о ViewModifiers ... поэтому моя цель - отделить неизменяемый материал от динамического, чтобы создать настраиваемый модификатор .cardify() для вызова представлений форм.
struct SetCard: View {
let pips: Int
let shape: SetCardShape
let color: Color
let shading: Double
let isSelected: Bool
var body: some View {
ZStack {
VStack {
ForEach( 0..<pips ) { _ in
ZStack {
getShape(self.shape).opacity(self.shading).foregroundColor(self.color)
getShape(self.shape).stroke().foregroundColor(self.color)
}
}
}
.padding() // for shape in RoundedRect
RoundedRectangle(cornerRadius: 10).stroke(lineWidth: isSelected ? 3.0 : 1.0).foregroundColor(.orange)
}
.scaleEffect(isSelected ? 0.60 : 1.0 )
.padding() // for spacing between cards
}
}
Опять же, по академическим / учебным причинам я хотел упростить эту структуру и использовать настраиваемый модификатор для преобразования основного содержимого в стандартную карточку.
Приведенный ниже блок кода работает только тогда, когда я закомментирую второйcontent
линия в Cardify
Структура ViewModifier. Все карты, которые использовали закрашенные фигуры для точек, отображаются нормально. Карточки, которые требуют обводки (т. Е. Не заполнения) фигуры, нуждаются в этой секунде.content
в моем Cardify
ViewModifer для работы.
Вторая строка содержимого выдает ошибку:
Значение типа Cardify.Content (также известное как _ViewModifier_Content) не имеет члена foregroundColor.
комментирование.foregroundColor() генерирует ошибку: значение типа Cardify.Content (также известное как _ViewModifier_Content) не имеет обводки элемента
struct SetCardWithCardify: View {
let pips: Int
let shape: SetCardShape
let color: Color
let shading: Double
let isSelected: Bool
var body: some View {
ZStack {
getShape(shape)
.modifier(Cardify(pips: pips, shape: shape, color: color, shading: shading, isSelected: isSelected))
}
.scaleEffect(isSelected ? 0.60 : 1.0 )
.padding() // for spacing between cards
}
}
struct Cardify: ViewModifier {
var pips: Int
var shape: SetCardShape
var color: Color
var shading: Double
var isSelected: Bool
func body(content: Content) -> some View {
ZStack {
VStack {
ForEach( 0..<pips ) { _ in
ZStack {
content.opacity(self.shading).foregroundColor(self.color)
content.stroke().foregroundColor(self.color)
}
}
}
.padding() // for shape in RoundedRect
RoundedRectangle(cornerRadius: 10).stroke(lineWidth: isSelected ? 3.0 : 1.0).foregroundColor(.orange)
}
}
}
На всякий случай, если это важно, следующий код является источником getShape()
что является источником content
в Cardify
ViewModifier.
func getShape(_ shape: SetCardShape ) -> some Shape {
switch shape {
case .circle:
return AnyShape( Circle() )
case .diamond:
return AnyShape( SetDiamond() )
case .squiggle:
return AnyShape( SetSquiggle() )
}
}
struct AnyShape: Shape {
func path(in rect: CGRect) -> Path {
return _path(rect)
}
init<S: Shape>(_ wrapped: S) {
_path = { rect in
let path = wrapped.path(in: rect)
return path
}
}
private let _path: (CGRect) -> Path
}
Diamond () и Squiggle() - это структуры, которые соответствуют протоколу Shape, правильно возвращая путь из `func path(в rect: CGRect) -> Path в этих структурах.
Я попытался снизить вторую строку контента с помощью:
(content as! Shape).blah blah blah
что генерирует ошибку:
Форму протокола можно использовать только в качестве общего ограничения, потому что у нее есть требования типа Self или связанные с ним.
Я также пробовал:
(content as! Path)
Это не генерирует никаких ошибок времени компиляции, но при его выполнении происходит сбой с ошибкой:
Во время работы возникла проблема, проверьте свой код на наличие ошибок в этой строке. (указывая вторую строку содержимого).
Что я могу сделать, чтобы компилятор узнал, какой это тип содержимого, и что stroke() и foregroundColor () будут работать?
0 ответов
Я не уверен, что вы можете, но вы можете приблизиться к этому, используя расширение Shape:
extension Shape {
func modified() -> some View {
self
.foregroundColor(Color.secondary.opacity(0.5))
}
}
// Usage example
struct ContentView: View {
var body: some View {
VStack {
Rectangle().modified()
Capsule().modified()
}
}
}
Однако, в отличие от модификатора представления, вы не можете получить доступ к среде, поэтому она несколько ограничена.