У меня хорошо работает макет, но градиенты немного разочаровывают. При создании RadialGradient вам необходимо указать beginradius и endradius в фактических точках экрана, а не на единичных точках (от 0,0 до 1,0). /p>
нравится это: < /p>
Код: Выделить всё
RadialGradient(gradient: item.isBlue ? self.blue : self.red,
center: .center,
startRadius: 0.0,
endRadius: 100.0)
Пример 2 - 2x3 Grid:
< /p>
Вот весь код в примере Project contentView.swift < /strong>, который четко демонстрирует, что я имею в виду: < /p>
import SwiftUI
struct MyDataItem: Identifiable {
let id: UUID = UUID()
let text: String
let isBlue: Bool
}
struct MyDataRow: Identifiable {
let id: UUID = UUID()
let items: [MyDataItem]
}
struct ContentView: View {
@State private var datasetIndex: Int = 0
@State private var sets = [
// First data set
[
MyDataRow(items: [
MyDataItem(text: "A", isBlue: false),
MyDataItem(text: "B", isBlue: true),
MyDataItem(text: "C", isBlue: true),
]),
MyDataRow(items: [
MyDataItem(text: "D", isBlue: false),
MyDataItem(text: "E", isBlue: false),
MyDataItem(text: "F", isBlue: false),
]),
],
// Second data set
[
MyDataRow(items: [
MyDataItem(text: "A", isBlue: false),
MyDataItem(text: "B", isBlue: true),
]),
MyDataRow(items: [
MyDataItem(text: "C", isBlue: true),
MyDataItem(text: "D", isBlue: false),
]),
MyDataRow(items: [
MyDataItem(text: "E", isBlue: false),
MyDataItem(text: "F", isBlue: false),
]),
]
]
var body: some View {
VStack {
Picker(selection: $datasetIndex, label: Text("Pick a data set")) {
Text("Set 1").tag(0)
Text("Set 2").tag(1)
}.pickerStyle(SegmentedPickerStyle())
GridThing(rows: self.$sets[self.datasetIndex])
Spacer()
}
}
}
struct GridThing: View {
@Binding var rows: [MyDataRow]
private let spacing: CGFloat = 20.0
let blue = Gradient(colors: [Color.blue, Color(red: 0.85, green: 0.85, blue: 1.0)])
let red = Gradient(colors: [Color.red, Color(red: 1.0, green: 0.85, blue: 0.85)])
var body: some View {
VStack(alignment: .center, spacing: spacing) {
ForEach(self.rows) { row in
HStack(alignment: .top, spacing: self.spacing) {
ForEach(row.items) { item in
ZStack {
Rectangle()
.fill(RadialGradient(gradient: item.isBlue ? self.blue : self.red,
center: .center,
startRadius: 0.0,
endRadius: 100.0))
.aspectRatio(1.0, contentMode: .fit)
Text(item.text)
.foregroundColor(.black)
}
}
}
}
}
}
}
< /code>
Я хочу, чтобы радиалграграда < /strong> использует эндрадий, который соответствует высоте и ширине квадрата. < /p>
< Br /> Я бы хотел, чтобы он мог сделать это автоматически. LinearGradient , например, принимает UnitPoint для StartPoint и Endpoint , что было бы идеальным, но для RadialGradient нам нужно выполнить всю работу, я думаю. /p>
Я пытался обернуть его так, рассчитывая endradius < /strong> с помощью geometryReader < /strong>. Этот терпит неудачу, потому что «Компилятор не может проверить это выражение в разумное время; попробуйте разбить выражение на различные подэкспрессии» < /em>: < /p>
var body: some View {
VStack(alignment: .center, spacing: spacing) {
GeometryReader { geom in
ForEach(self.rows) { row in
HStack(alignment: .top, spacing: self.spacing) {
ForEach(row.items) { item in
ZStack {
Rectangle()
.fill(RadialGradient(gradient: item.isBlue ? self.blue : self.red,
center: .center,
startRadius: 0.0,
endRadius: (geom.size.width - (self.spacing * (row.items.count + 1))) / row.items.count))
.aspectRatio(1.0, contentMode: .fit)
Text(item.text)
.foregroundColor(.black)
}
}
}
}
}
}
}
< /code>
Спасибо! < /p>
Подробнее здесь: https://stackoverflow.com/questions/593 ... rfectly-us