How to Make Swiftui Listmenu with Different Behaviors

Is it possible to make SwiftUI ListMenu with different behaviors?

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 Generic Array Model

Here's a basic example showing a view that has a generic requirement for the @Binding array like you have:


enum TrafficSignSectionType: String, Codable, Hashable {
case A = "A"
case B = "B"
}

struct TrafficSign: Codable, Hashable, Question { //<-- Here
var id: Int?
var image: String?
var sections: [TrafficSignSectionType.RawValue : String]?
var correct: String?
}

enum PoliceSignSectionType: String, Codable, Hashable {
case A = "A"
case B = "B"
case C = "C"
}

struct PoliceSign: Codable, Hashable, Question { //<-- Here
var id: Int?
var image: String?
var sections: [PoliceSignSectionType.RawValue : String]?
var correct: String?
}


protocol Question : Identifiable { //<-- Here
var image: String? { get set }
}

struct ContentView : View {
@State private var questions : [PoliceSign] = []
@State private var questions2 : [TrafficSign] = []

var body: some View {
QuestionCardView(questions: $questions)
QuestionCardView(questions: $questions2)
}
}

struct QuestionCardView<T: Question>: View {
@Binding var questions: [T]

var body: some View {
ForEach(questions) { question in
Text(question.image ?? "")
}
}
}

You'll want a protocol that defines the requirements for the type. In your original code, it looked like image was the only obvious property.

Your original code will have:

struct QuestionCardView<T: Question>: View {
@EnvironmentObject var optionConfigure: OptionConfigure
@Binding var questions: [Question]

How to get the index of the element in the List in SwiftUI when the List is populated with the array?

This can be done using using .enumerated. For your MenuItem values it will be as follows

List {
ForEach(Array(menuItems.enumerated()), id: \.1.id) { (index, textItem) in
// do with `index` anything needed here
Text(textItem.text)
}
}

Is it possible to make SwiftUIPager scroll the icons with the newest version?

Option 1
Try changing your implementation of func pageView(_ page: Int) -> some View:

The idea is to replace the button items in the pageView with Image

// MARK: - Page class for Scroll View - Levels icons

func pageView(_ page: Int) -> some View {
Image(uiImage: UIImage(named: LobbyView.levels[page] )!)
.renderingMode(.original)
.resizable()
.aspectRatio(contentMode: .fit)
.onTapGesture {
withAnimation{
// the same action button does
}
}
}

Option 2
If not, go to line 169 inside Pager.swift (Pod framework):
Sample Image

and swap

wrappedView = AnyView(wrappedView.gesture(allowsDragging ? swipeGesture : nil))

with

wrappedView = AnyView(wrappedView.highPriorityGesture(allowsDragging ? swipeGesture : nil))

I'd go for option 1. Notice in option 2 if you do this, any gesture
you add inside your page content won't be recognized.

Fernando Moya de Rivas

SwiftUI: How to remove caret right in NavigationLink which is inside a List

you can do it like this:

var body: some View {
NavigationView() {
List(menu, id: \.self) { section in

VStack{
Text(section.name)
NavigationLink(destination: Dest()) {
EmptyView()
}
}
}
}


Related Topics



Leave a reply



Submit