我在3x4网格上有几个月的浏览量。每个子视图都是一个小框,其中包含选中/未选中的月份名称和状态。问题是...我想从父视图中观察枚举变量,并取消选择除最后一次按下以外的所有按钮。
到目前为止,我已经实现了下一个逻辑。最初,我有 currentMonthSelected ,状态为.none (未选择月份)。当我按下 JAN 按钮时,我将 currentMonthSelected == .jax传递给单月子视图,它返回给我返回更改currentMonthSelected应该遵守的回调其他视图。
ParentView
@State var currentMonthSelected: MonthsTypes = .none
SingleButtonView(title: .jan, isSelected: currentMonthSelected == .jan ? true : false, action: { month in
self.currentMonthSelected = month
})
SingleButtonView(title: .feb, isSelected: currentMonthSelected == .feb ? true : false, action: { month in
self.currentMonthSelected = month
})
单月子视图
struct SingleButtonView: View {
var title: MonthsTypes = .none
@State var isSelected = false
var action: (MonthsTypes) -> ()
var body: some View {
VStack(spacing: 0){
Button(action: {
self.action(self.title)
}){
Spacer()
Text(title.rawValue.prefix(3))
.font(.Montserrat(weight: isSelected ? .SemiBold : .Regular, size: 16))
.foregroundColor(isSelected ? Color.white : Color.gray)
Spacer()
}
}
.frame(width: 80, height: 40)
.background(isSelected ? Color.white : Color.brand_purple)
}
}
答案 0 :(得分:0)
通过一个视图模型更容易管理这种视图层次结构。这是一个基于您的代码的方法演示(只需用自定义字体/颜色放一些行,但这不会影响想法)。
struct ParentView_Previews: PreviewProvider {
static var previews: some View {
ParentView().environmentObject(ViewModel()) // inject view model
}
}
enum MonthsTypes: String { // restored enum
case none = "None"
case jan = "January"
case feb = "February"
case mar = "March"
}
class ViewModel: ObservableObject { // selection holder (extendable for anything)
@Published var currentMonthSelected: MonthsTypes = .none
}
struct ParentView: View {
@EnvironmentObject var viewModel: ViewModel // assuming injected by .environmentObject(ViewModel)
var body: some View {
VStack {
SingleButtonView(title: .jan) // simple declaration, action can be added
SingleButtonView(title: .feb)
SingleButtonView(title: .mar)
}
}
}
struct SingleButtonView: View {
@EnvironmentObject var vm: ViewModel // logic on selection change is inside
var title: MonthsTypes = .none
var action: (MonthsTypes) -> () = { _ in } // default action does nothing
var body: some View {
VStack(spacing: 0){
Button(action: {
// change selection to self or toggle
self.vm.currentMonthSelected = (self.vm.currentMonthSelected != self.title ? self.title : MonthsTypes.none)
self.action(self.title) // callback if needed
}){
Spacer()
Text(title.rawValue.prefix(3))
.foregroundColor(self.vm.currentMonthSelected == self.title ? Color.white : Color.gray)
Spacer()
}
}
.frame(width: 80, height: 40)
.background(vm.currentMonthSelected == title ? Color.purple : Color.white)
}
}
答案 1 :(得分:0)
enum MonthsTypes: String {
case jan = "January"
case feb = "February"
case none
}
struct ContentView: View {
@State var currentMonthSelected: MonthsTypes = .none
var body: some View {
VStack() {
SingleButtonView(title: .jan, currentMonthSelected: $currentMonthSelected)
SingleButtonView(title: .feb, currentMonthSelected: $currentMonthSelected)}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
struct SingleButtonView: View {
var title: MonthsTypes = .none
@Binding var currentMonthSelected: MonthsTypes
var isSelected: Bool {
if title == currentMonthSelected { return true}
return false
}
var body: some View {
VStack(spacing: 0){
Button(action: {
self.currentMonthSelected = self.title
}){
Spacer()
Text(title.rawValue.prefix(3))
.foregroundColor(isSelected ? Color.white : Color.gray)
Spacer()
}
}
.frame(width: 80, height: 40)
.background(isSelected ? Color.white : Color.yellow)
}
}