我的 iOS 应用程序具有可自定义的用户颜色设置。我制作了一个用于颜色选择的视图。该视图具有标题按钮,用于在用户要更改的颜色设置和可选颜色选项网格之间进行选择。
普通颜色选择器
当我按下 在所选颜色设置之间切换时,视图大小会调整。
[更改颜色选择后拉伸的颜色选择器](https://i.sstatic.net/26nFPR5M.png
我无法弄清楚是什么原因造成的,希望外部/更有经验的观点能够抓住它。
import SwiftUI
struct ColorSelect: View {
//either 1 or 2 to represent which of the User's 2 colors is to be changed
@State var colorSelection: Int = 1
//Bool for the parent view
@Binding var windowVisible: Bool
//Color 1 Binding so parent view can update it's Colors
@Binding var color1Link: Color
//Color 2 Binding so parent view can update it's Colors
@Binding var color2Link: Color
//list of rgb values for displayed colors that is interpreted by func convertColor
let colors = [144012063, //dark red
255049049, //red
255092000, //orange
255195000, //dark orange
255240031, //yellow
170255000, //dark green
057255020, //green
188237250, //very light blue
004217255, //blue
031081255, //dark blue
125018255, //dark purple
176038255, //purple
255016240, //pink
255189186, //peach
255255255, //white
170170170 //gray
]
var body: some View {
//array for colorLinks
var colorSlots = [color1Link, color2Link]
//labels for User color setting selection buttons
let col1Label = Text("Color 1")
.font(.system(.title2,
design: .rounded))
.fontWeight(.heavy)
.foregroundStyle(.white)
let col2Label = Text("Color 2")
.font(.system(.title2,
design: .rounded))
.fontWeight(.heavy)
.foregroundStyle(.white)
ZStack {
//background visuals
RoundedRectangle(cornerRadius: 34.0)
.foregroundStyle(.white)
.padding(10)
RoundedRectangle(cornerRadius: 30.0)
.foregroundStyle(.black)
.padding(14)
VStack {
//User Color slot selection banner
HStack {
Spacer()
//selected button will apply Color change to related User Color slot
Button {
colorSelection = 1
} label: {
if(colorSelection == 1) {
col1Label
.underline()
} else {
col1Label
}
}
Spacer()
Text("|")
.font(.system(.title2,
design: .rounded))
.fontWeight(.heavy)
.foregroundStyle(.white)
Spacer()
Button {
colorSelection = 2
} label: {
if(colorSelection == 2) {
col2Label
.underline()
} else {
col2Label
}
}
Spacer()
}
.padding()
//4x4 Grid of color options
LazyVGrid(columns: [GridItem(spacing: 5),
GridItem(spacing: 5),
GridItem(spacing: 5),
GridItem(spacing: 5)], spacing: 5) {
ForEach(colors, id: \.self) { color in
//actual Color object for rgb Int in array
let trueColor = convertColor(rgb: color)
//display for selectable color option
let buttonView = RoundedRectangle(cornerRadius: 8)
.foregroundStyle(trueColor)
.shadow(color: trueColor, radius: 7)
//determines if Color selection is User's selected Color
// this has a separate issue where the User's Color
// isn't updated because the change isn't read from defaults
@State var currColor = color ==
UserDefaults.standard.integer(forKey:
"color\(colorSelection)rgb")
//Display button if Color is not selected, else a view with check
if(!currColor) {
Button {
UserDefaults.standard.set(color,
forKey: "color\(colorSelection)rgb")
colorSlots[colorSelection - 1] = convertColor(rgb: color)
} label: {
buttonView
}
.aspectRatio(contentMode: .fit)
} else {
//makes selected color tile an inactive view with checkmark
ZStack {
buttonView
Image(systemName: "checkmark")
.resizable()
.foregroundStyle(.white)
.padding()
}
}
}
}
}
.padding(20)
//'x' escape button in top right
VStack {
HStack {
Spacer()
Button {
windowVisible = false
} label: {
Image(systemName: "x.circle")
.foregroundColor(.white)
.shadow(color: .white,
radius: 10)
}
}
Spacer()
}
}
.aspectRatio(contentMode: .fit)
}
//takes the local Int interpretation of rgb and returns the associated Color object
func convertColor(rgb: Int) -> Color {
let b = Double(rgb % 1000) / 255
let g = Double((rgb % 1000000) / 1000) / 255
let r = Double((rgb % 1000000000) / 1000000) / 255
return Color(red: r, green: g, blue: b)
}
}
#Preview {
ColorSelect(windowVisible: Binding.constant(true),
color1Link: Binding.constant(.black),
color2Link: Binding.constant(.black))
}
(我的代码还存在其他问题,例如颜色选择的实际选择的颜色没有更新,因为它与 UserDefaults 相关并且无法实际观看更改,但这不是我现在关注的重点)
显而易见的是,在颜色选择之间切换时视图不应改变大小。我尝试将它放入框架中,但随后它的宽度只是缩小,而不是高度增加。我尝试删除垫片,看看它们在状态更新时是否会以某种方式改变大小,但这也没有解决问题。我盯着我的 Color 2 按钮操作以跟踪它所做的任何更改,但仍然没有找到任何线索。
当我运行应用程序模拟器时,您描述的调整大小问题并没有发生在我身上,但是,它确实在预览中偶尔发生。我怀疑预览的加载方式可能与作为应用程序运行时的加载方式不同,因此我不会担心它。
至于
UserDefaults
bug,可以使用 @AppStorage
属性来修复。例如,此代码将立即更新所选颜色:
struct ColorSelect: View {
@AppStorage("color1rgb") var color1Selection: Int = -1
@AppStorage("color2rgb") var color2Selection: Int = -1
/* other variables... */
var body: some View {
/* rest of the view... */
ForEach(colors, id: \.self) { color in
let currColor = colorSelection == 1 ?
color == color1Selection :
color == color2Selection
}
/* rest of the view... */
}
}