首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用RadialGradient大小填充动态大小的矩形,以便使用SWIFT5.1中的SwiftUI非常适合iOS

用RadialGradient大小填充动态大小的矩形,以便使用SWIFT5.1中的SwiftUI非常适合iOS
EN

Stack Overflow用户
提问于 2019-12-14 04:55:15
回答 1查看 493关注 0票数 1

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

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

如下所示:

代码语言:javascript
复制
RadialGradient(gradient: item.isBlue ? self.blue : self.red,
               center: .center,
               startRadius: 0.0,
               endRadius: 100.0)

在上面的例子中,我选择了一个任意大小的100分作为endRadius。这是很好的工作,但真正给广场一个不同的外观,当他们是不同的大小。请参阅下面的两个示例。

示例1 -- 3x2网格

示例2 -- 2x3网格:

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

代码语言:javascript
复制
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)
                        }
                    }
                }
            }
        }
    }
}

我想让RadialGradient使用与正方形的高度和宽度相匹配的endRadius。

我希望它能自动做到这一点。例如,LinearGradient,以UnitPoint for startPointendPoint为例,这将是完美的,但对于RadialGradient,我们需要做所有的工作。

我对此的主要想法是在某种程度上合并一个GeometryReader.

我尝试过这样包装,用GeometryReader.计算endRadius这一次失败是因为“编译器无法在合理的时间内键入-检查该表达式;尝试将表达式拆分为不同的子表达式”。

代码语言:javascript
复制
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)
                        }
                    }
                }
            }
            }
        }
    }

谢谢!

EN

回答 1

Stack Overflow用户

发布于 2019-12-14 06:32:22

几何读取器是正确的,但不是包装整个网格,只是包装正方形,然后你不需要做任何额外的计算:几何宽度是正方形的宽度,这是你的梯度半径的两倍。这里有个游乐场:

代码语言:javascript
复制
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())
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59332412

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档