文本未通过循环放置在同一位置

Text not being put in same position through loop

我有一个循环遍历日期名称数组,并为每个日期名称创建一个文本,然后围绕一个圆圈展开。问题是文本在每次迭代中都会改变位置 - 看起来越来越低,然后又变高。下面是我使用的代码:

struct LabelPositionTest: View {

private var sectorAngle: Double = Double(360/7)
private var dayNameArray: Array<String> = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"]
private var viewWidth: CGFloat = 180
private var viewHeight: CGFloat = 100

var body: some View {
    GeometryReader
    {   selectorWheelGeometry in
            ForEach((0...6), id: \.self) {i in
            ZStack(alignment: .trailing)
            {
                if dayNameArray.count > i
                {
                    Rectangle()
                        .foregroundColor(.red)
                    Text(dayNameArray[i])
                        .rotationEffect(Angle.degrees(90))
                        .foregroundColor(.black)
                }
            }
            .frame(width: selectorWheelGeometry.size.width/2.25, height: viewHeight)
            .rotationEffect(Angle.degrees(Double((i-1)*(360/7))+(90 + (0.5 * sectorAngle))), anchor: .leading)
            .position(x: selectorWheelGeometry.size.width/2 + (selectorWheelGeometry.size.width/2.25)/2, y: selectorWheelGeometry.size.height/2)
        }
    }
}
}

ForEach 7 天的常数范围语法是:

ForEach(0..<7) { i in

你的常量变量应该是 lets。

在处理这种旋转视图时,我发现最简单的修复错误的方法是先创建基础视图,然后将基础视图作为一个单元进行定位和旋转。通常,我会将此单元创建为单独的视图,但您的示例非常简单,我只是创建了 Rectangle() 并覆盖了 Text()。我做的另一件事是切换 Rectangle() 上的维度。本质上,您有一个 Rectangle() 侧放,然后您旋转文本以尝试匹配 Rectangle()。我将 Rectangle() 竖起并以正常方向覆盖文本,顶部对齐和一些 .padding().

你的标签不在同一个地方的原因是它们在定位之前都被旋转了。如果您在预览中显示您的代码,然后突出显示 Text(),您将看到 Text() 视图轮廓的大小各不相同。这说明了放错标签的原因。按照上述放置,解决了这个问题。

注释代码如下:

struct LabelPositionTest: View {
    
    private var sectorAngle: Double {
        Double(360/dayNameArray.count)
    }
    private var dayNameArray: Array<String> = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"]
    private var viewWidth: CGFloat = 100

    var body: some View {
        GeometryReader { selectorWheelGeometry in
            ZStack {
                // A much safer way of obtaining the index of an array in a ForEach is to zip the array
                // and its indices together, and then iterate off the array. This prevents out of bounds
                // errors, and, if the array elements are Identifiable, still allows you to use .move()
                // and .delete. The id: \.0 simply tells the ForEach to iterate on the first element in the zip
                ForEach(Array(zip(dayNameArray, dayNameArray.indices)), id: \.0) { day, index in
                    Rectangle()
                        .foregroundColor(.red)
                        .overlay(
                            Text(day)
                                .foregroundColor(.black)
                                .padding(.top),
                            alignment: .top
                        )
                        .frame(width: viewWidth, height: selectorWheelGeometry.size.width/2.25)
                        // You already had sectorAngle defined, so I just used that. I also removed
                        // the extra 90 degree rotation. You can put that back in if you don't want a
                        // top start. This was just simplification for the answer.
                        .rotationEffect(Angle.degrees(Double(index) * sectorAngle), anchor: .bottom)
                }
            }
            .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .center)
        }
    }
}