是否可以使 SwiftUI ListMenu 具有不同的行为? [英] Is it possible to make SwiftUI ListMenu with different behaviors?

查看:36
本文介绍了是否可以使 SwiftUI ListMenu 具有不同的行为?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

是否可以使用 swiftUI 制作一个列表菜单,其中列表项具有不同的行为(并使用 foreach 添加到视图中)?

列表项将是模型.

EG.第一个将打开个人资料视图,第二个将打开另一个不同的视图,第三个只是简单地注销.

并用 ForEach 模型填充列表.

我正在使用 SwiftUI 列表制作更多菜单.

代码:

<预><代码>var主体:一些视图{导航视图{列表(viewModel.menuItems){ item in//这里应该显示另一个视图或根据项目类型调用一个函数//例如.如果是个人资料菜单项,则显示个人资料//如果是注销菜单项,则注销}}}

解决方案

继承可以很容易地与相似项共享属性,然后根据类型路由视图

导入 SwiftUI类 MenuOption: ObservableObject, Identifiable{var id: UUID = UUID()@Published var 标题:字符串初始化(标题:字符串){self.title = 标题}}MOToggle 类:MenuOption{@Published var 值:布尔值init(title: String, value: Bool = false){self.value = 价值super.init(标题:标题)}}MOOptions 类:MenuOption{@Published var 选择:选项枚举选项:字符串,CaseIterable{案例优先案例二案例三案件不明}init(title: String, selection: Options = .unknown){self.selection = 选择super.init(标题:标题)}}//您可以拥有使用每种类型的视图struct MenuOptionToggleView:查看{@ObservedObject var 选项:MOTogglevar主体:一些视图{切换(isOn:$option.value,标签:{文本(选项.标题)})}}struct MenuOptionOptionsView:查看{@ObservedObject var 选项:MOOptionsvar主体:一些视图{选择器(选择:$option.selection,标签:文本(选项.标题), 内容: {ForEach(MOOptions.Options.allCases, id:\.rawValue, content: { item in文本(item.rawValue).tag(item)})}).pickerStyle(MenuPickerStyle())}}//并在一个视图中显示它们struct MenuListView:查看{//当他们共享一个类型时,他们可以一起放在一个数组中@State var options: [MenuOption] = [MenuOption(title: "say hello"),MOToggle(title: "toggle the option"), MOOptions(title: "show the menu")]var主体:一些视图{List(options, id: \.id){option in//然后当你有项目时确定它是什么类型如果选项是 MOToggle{//当你把它传递给它指定的View时//您将其转换为其特定类型MenuOptionToggleView(选项:选项为!MOToggle)} else if option 是 MOOptions{//当你把它传递给它指定的View时//您将其转换为其特定类型MenuOptionOptionsView(option: option as! MOOptions)} 别的{//并且由于它们是相同的类型,因此您可以一网打尽按钮(动作:{打印(选项.标题)}, 标签: {文本(选项.标题)})}}}}struct MenuListView_Previews: PreviewProvider {静态 var 预览:一些视图 {菜单列表视图()}}

Is it possible to make a list menu with swiftUI where the List items have different behaviors(and added to the view with foreach)?

The list items would be models.

EG. the first would open a Profile view, the second would open another different view, the third would just simply log out.

And fill the List with a ForEach of the models.

I'm making a MoreMenu with SwiftUI list.

Code:


var body: some View {
        NavigationView {
            List(viewModel.menuItems) { item in
                //Here should show another view or call a function depending on the item type
                //EG. if its a profile Menu item, show profile
                // if its a logout Menu item, logout
            }
        }
}

解决方案

Inheritance makes it easy to share properties with similar items and then routing Views depending on the type

import SwiftUI
class MenuOption: ObservableObject, Identifiable{
    var id: UUID = UUID()
    @Published var title: String
    
    init(title: String){
        self.title = title
    }
}

class MOToggle: MenuOption{
    @Published var value: Bool
    init(title: String, value: Bool = false){
        self.value = value
        super.init(title: title)
    }
}
class MOOptions: MenuOption{
    @Published var selection: Options
    
    enum Options: String, CaseIterable{
        case first
        case second
        case third
        case unknown
    }
    init(title: String, selection: Options = .unknown){
        self.selection = selection
        super.init(title: title)
    }
}
//You can have Views that use each type
struct MenuOptionToggleView: View {
    @ObservedObject var option: MOToggle
    var body: some View {
        Toggle(isOn: $option.value, label: {
            Text(option.title)
        })
    }
}
struct MenuOptionOptionsView: View {
    @ObservedObject var option: MOOptions
    var body: some View {
        Picker(selection: $option.selection, label:
                Text(option.title)
               , content: {
            ForEach(MOOptions.Options.allCases, id:\.rawValue, content: { item in
                Text(item.rawValue).tag(item)
            })
        }).pickerStyle(MenuPickerStyle())
    }
}
//And show them all in one View
struct MenuListView: View {
    //When they share a type they can be put in an array together
    @State var options: [MenuOption] = [MenuOption(title: "say hello"),MOToggle(title: "toggle the option"), MOOptions(title: "show the menu")]
    var body: some View {
        List(options, id: \.id){option in
            //Then when you have the item determine what type it is
            if option is MOToggle{
                //When you pass it to its designated View
                //You convert it to its specifc type
                MenuOptionToggleView(option: option as! MOToggle)
            } else if option is MOOptions{
                //When you pass it to its designated View
                //You convert it to its specifc type
                MenuOptionOptionsView(option: option as! MOOptions)
            } else{
                //And since they are if the same type you can have a catch all
                Button(action: {
                    print(option.title)
                }, label: {
                    Text(option.title)
                })
            }
            
        }
    }
}
struct MenuListView_Previews: PreviewProvider {
    static var previews: some View {
        MenuListView()
    }
}

这篇关于是否可以使 SwiftUI ListMenu 具有不同的行为?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆