Skip to content

Instantly share code, notes, and snippets.

@svenoaks
Last active June 2, 2023 19:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save svenoaks/e51114e898e265d2e5fb7a6a1190f8b1 to your computer and use it in GitHub Desktop.
Save svenoaks/e51114e898e265d2e5fb7a6a1190f8b1 to your computer and use it in GitHub Desktop.
testSelect
import SwiftUI
struct ContentView: View {
@State var editMode = EditMode.inactive
@State private var selection = Set<String>()
let names = [
"Cyril",
"Lana",
"Mallory",
"Sterling"
]
var body: some View {
NavigationView {
let navTitle = editMode == .inactive || selection.isEmpty ? "Library" : "\(selection.count) selected"
List(names, id: \.self, selection: $selection) { name in
Text(name)
//On iOS>=16 shows single item contextMenu with custom Preview, otherwise old contextMenu
.modifier(SingleItemContextMenu(name: name))
}
.modifier(MultiItemContextMenu()) //On iOS>=16 shows contextMenu for multi-item select, otherwise nothing
.navigationTitle(navTitle)
.modifier(TrailingToolbar(editMode: $editMode)) //On iOS>=16 adds Select button, otherwise just the Sort button
.environment(\.editMode, $editMode)
}
}
}
struct TrailingToolbar : ViewModifier {
@Binding var editMode: EditMode
func body(content: Content) -> some View {
let sortButton = Menu {
Button("Title") {}
Button("Artist") {}
} label: {
Text("Sort")
}
let selectButton = Button(editMode == .inactive ? "Select" : "Done") {
withAnimation {
if editMode == .inactive {
editMode = .active
} else {
editMode = .inactive
}
}
}
return content
.toolbar {
ToolbarItemGroup(placement: .navigationBarTrailing) {
if #available(iOS 16, *) {
if editMode == .active {
selectButton
}
Menu {
if editMode == .inactive {
selectButton
}
sortButton
} label: {
Button{} label: {
Image(systemName: "ellipsis.circle")
}
}
} else {
sortButton
}
}
}
}
}
extension View {
func trailingToolbar(editMode: Binding<EditMode>) -> some View {
let selectButton = Button(editMode.wrappedValue == .inactive ? "Select" : "Done") {
withAnimation {
if editMode.wrappedValue == .inactive {
editMode.wrappedValue = .active
} else {
editMode.wrappedValue = .inactive
}
}
}
return toolbar {
ToolbarItem(placement: .navigationBarTrailing) {
if #available(iOS 16, *) {
} else {
}
}
}
}
}
struct SingleItemContextMenu: ViewModifier {
let name: String
@ViewBuilder var menuItems: some View {
Button {
print("Change country setting")
} label: {
Label("Choose Country", systemImage: "globe")
}
Button {
print("Enable geolocation")
} label: {
Label("Detect Location", systemImage: "location.circle")
}
}
func body(content: Content) -> some View {
if #available(iOS 16, *) {
content.contextMenu {
menuItems
} preview: {
VStack {
Text(name)
.padding(.bottom, 8)
Image(systemName: "square.stack")
}
.frame(width: 200, height: 200)
}
} else {
content.contextMenu {
menuItems
}
}
}
}
struct MultiItemContextMenu: ViewModifier {
func body(content: Content) -> some View {
if #available(iOS 16, *) {
content.contextMenu(forSelectionType: String.self) { items in
if items.count > 1 { // Multi-item menu.
Button("Copy") { }
Button("New Folder With Selection") { }
Button("Delete Selected", role: .destructive) { }
}
}
} else {
content
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment