My iOS app has customizable user color settings. I made a view to be used for the color selection. The view has header buttons to pick between which color setting the user is changing and a grid of selectable color options.
Normal ColorSelector
When I press to switch between the selected color setting, the view resizes.
[Stretched ColorSelector after changing Color selection](https://i.sstatic.net/26nFPR5M.png
I cannot figure out what is causing this and am hoping an outside/more experienced perspective could catch it.
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 = Binding.constant(true)
//Color 1 Binding so parent view can update it's Colors
@Binding var color1Link: Color = Binding.constant(.black)
//Color 2 Binding so parent view can update it's Colors
@Binding var color2Link: Color = Binding.constant(.black)
//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))
}
(There are other issues with my code like the actual picked Color for the color selection not updating since it is tied to UserDefaults and can’t actually watch the change, but that’s not what I’m focusing on right now)
To state the obvious, the window should not change size when switching between the Color Selection. I have tried putting it in a frame, but then it just shrinks in width in place of growing in height. I’ve tried removing spacers to see if they are somehow changing size when the state updates, but that didn’t fix it either. I’ve stared at my Color 2 button action to follow any changes it makes, but still have not found any leads.
Alec Ruedi is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.