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