I have the following SwiftUI
menu:
import SwiftUI
struct ContentView: View {
private enum Constants {
static let arrowIcon = Image(systemName: "chevron.down")
static let background = Color.blue
static let buttonFont = Font.system(size: 14.0)
}
@State private var menuIndex = 0
private let menuItems = ["This year", "Last Year"]
private var menuTitle: String {
guard menuItems.indices.contains(menuIndex) else { return "" }
return menuItems[menuIndex]
}
// MARK: - Views
var body: some View {
makeMenu()
}
// MARK: - Buttons
private func menuItemTapped(title: String) {
guard let index = menuItems.firstIndex(of: title) else { return }
menuIndex = index
}
// MARK: - Factory
@ViewBuilder private func makeMenu() -> some View {
Menu {
ForEach(menuItems, id: \.self) { title in
Button(title, action: { menuItemTapped(title: title) })
}
} label: {
Text("\(menuTitle) \(Constants.arrowIcon)")
.font(Constants.buttonFont)
.fontWeight(.bold)
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
When a menu item is tapped the index to the title array is updated causing the Text
title to update. This works as desired however the text is slow to resize to the changes Last Year...
will briefly show before it resizes correctly.
What am I doing wrong here?
CodePudding user response:
This is because the size of the label is being set but not being changed. If you're okay with it, setting a maxWidth
of .infinity
on the frame of the Label gives you this capability.
@ViewBuilder private func makeMenu() -> some View {
VStack {
Menu {
ForEach(menuItems, id: \.self) { title in
Button(title, action: { menuItemTapped(title: title) })
}
} label: {
Text("\(menuTitle) \(Constants.arrowIcon)")
.font(Constants.buttonFont)
.fontWeight(.bold)
.frame(maxWidth: .infinity) //--> Add this line
}
}
}