使用Swift 5.1 for iOS中的SwiftUI,用半径渐变填充动态大小的矩形,使其完全适合

使用Swift 5.1 for iOS中的SwiftUI,用半径渐变填充动态大小的矩形,使其完全适合,ios,swift,swiftui,gradient,radial-gradients,Ios,Swift,Swiftui,Gradient,Radial Gradients,我有一个SwiftUI屏幕,以网格格式显示数据,动态调整单元格大小,使其始终填充可用宽度,并确保它们始终为正方形 我的布局很好,但是渐变有点令人沮丧。创建半径渐变时,需要在实际屏幕点而不是单位点(从0.0到1.0)中指定beginRadius和endRadius 像这样: RadialGradient(渐变:item.isBlue?self.blue:self.red, 中心:,中心, 星系:0.0, 端半径:100.0) 在上面的示例中,我为端点半径选择了任意大小的100个点。这很好用,但是

我有一个SwiftUI屏幕,以网格格式显示数据,动态调整单元格大小,使其始终填充可用宽度,并确保它们始终为正方形

我的布局很好,但是渐变有点令人沮丧。创建半径渐变时,需要在实际屏幕点而不是单位点(从0.0到1.0)中指定beginRadiusendRadius

像这样:

RadialGradient(渐变:item.isBlue?self.blue:self.red,
中心:,中心,
星系:0.0,
端半径:100.0)
在上面的示例中,我为端点半径选择了任意大小的100个点。这很好用,但是当正方形的大小不同时,它们的外观就不同了。看看下面的两个例子

示例1--3x2网格

示例2--2x3网格:

下面是一个示例项目ContentView.swift中的所有代码,它清楚地说明了我的意思:

导入快捷界面
结构MyDataItem:可识别{
let id:UUID=UUID()
让文本:字符串
让我来看看蓝色:嘘
}
结构MyDataRow:可识别{
let id:UUID=UUID()
let items:[MyDataItem]
}
结构ContentView:View{
@国家私有var数据集索引:Int=0
@国家私有变量集=[
//第一数据集
[
MyDataRow(项目:[
MyDataItem(文本:“A”,蓝色:false),
MyDataItem(文本:“B”,蓝色:true),
MyDataItem(文本:“C”,蓝色:true),
]),
MyDataRow(项目:[
MyDataItem(文本:“D”,蓝色:false),
MyDataItem(文本:“E”,蓝色:false),
MyDataItem(文本:“F”,蓝色:false),
]),
],
//第二数据集
[
MyDataRow(项目:[
MyDataItem(文本:“A”,蓝色:false),
MyDataItem(文本:“B”,蓝色:true),
]),
MyDataRow(项目:[
MyDataItem(文本:“C”,蓝色:true),
MyDataItem(文本:“D”,蓝色:false),
]),
MyDataRow(项目:[
MyDataItem(文本:“E”,蓝色:false),
MyDataItem(文本:“F”,蓝色:false),
]),
]
]
var body:一些观点{
VStack{
选择器(选择:$datasetIndex,标签:Text(“选择数据集”)){
文本(“集合1”)。标记(0)
文本(“集合2”)。标签(1)
}.pickerStyle(SegmentedPickerStyle())
GridThing(行:self.$sets[self.datasetIndex])
垫片()
}
}
}
结构GridThing:视图{
@绑定变量行:[MyDataRow]
专用let间距:CGFloat=20.0
设蓝色=渐变色(颜色:[Color.blue,Color(红色:0.85,绿色:0.85,蓝色:1.0)])
设红色=渐变(颜色:[颜色。红色,颜色(红色:1.0,绿色:0.85,蓝色:0.85)])
var body:一些观点{
VStack(对齐:。中心,间距:间距){
ForEach(self.rows){row in
HStack(对齐:。顶部,间距:自间距){
ForEach(row.items){item in
ZStack{
矩形()
.填充(径向梯度(梯度:item.isBlue?self.blue:self.red),
中心:,中心,
星系:0.0,
端半径:100.0)
.aspectRatio(1.0,contentMode:.fit)
文本(item.Text)
.foregroundColor(.黑色)
}
}
}
}
}
}
}
我想让RadialGradient使用与正方形高度和宽度匹配的endRadius

我希望它能够自动完成这项工作<例如,strong>LinearGradient
单位点用于起始点端点,这将是完美的,但对于径向梯度,我们需要做我猜想的所有工作

我的主要想法是以某种方式合并一个GeometryReader

我试着这样包装它,用GeometryReader计算endRadius。此操作失败,因为“编译器无法在合理的时间内对此表达式进行类型检查;请尝试将该表达式拆分为不同的子表达式”:

var主体:一些视图{
VStack(对齐:。中心,间距:间距){
GeometryReader{geom in
ForEach(self.rows){row in
HStack(对齐:。顶部,间距:自间距){
ForEach(row.items){item in
ZStack{
矩形()
.填充(径向梯度(梯度:item.isBlue?self.blue:self.red),
中心:,中心,
星系:0.0,
endRadius:(geom.size.width-(self.spating*(row.items.count+1))/row.items.count))
.aspectRatio(1.0,contentMode:.fit)
文本(item.Text)
.foregroundColor(.黑色)
}
}
}
}
}
}
}

谢谢

几何体读取器是正确的,但不是环绕整个网格,
import SwiftUI
import PlaygroundSupport

struct V: View {
  var body: some View {
    VStack(alignment: .center, spacing: 10) {
      ForEach(0..<4) { row in
        HStack(alignment: .top, spacing: 10) {
          ForEach(0..<4) { item in
            ZStack {
              GeometryReader { geometry in
                Rectangle()
                  .fill(
                    RadialGradient(
                      gradient: Gradient(colors: [Color.white, Color.red, Color.green]),
                      center: .center,
                      startRadius: 0.0,
                      endRadius: geometry.size.width / 2 )
                   )
                  .aspectRatio(1.0, contentMode: .fit)
              }
              Text("text")
                .foregroundColor(.black)
            }
          }
        }
      }
    }
  }
}

PlaygroundPage.current.setLiveView(V())