Skip to content

Instantly share code, notes, and snippets.

@odrobnik
Last active Feb 9, 2021
Embed
What would you like to do?
Trying to emulate Picker behaviour inside a List
//
// NavPicker.swift
// ColorCore Demo
//
// Created by Oliver Drobnik on 09.02.21.
//
import SwiftUI
public struct NavPicker<Label, Items> : View where Label : View, Items: CustomStringConvertible & Identifiable
{
let selection: Binding<Int?>
let items:[Items]
let label: Label
let firstIndexToShow: Int
public init(selection: Binding<Int?>, label: Label, items: [Items], firstIndexToShow: Int = 0)
{
self.selection = selection
self.label = label
self.items = items
self.firstIndexToShow = firstIndexToShow
}
public var body: some View
{
NavigationLink(
destination: NavPickerDetail(selection: selection, items: items, firstIndexToShow: firstIndexToShow)
.toolbar { ToolbarItem(placement: .principal) { label } }) {
HStack {
label
Spacer()
if let index = selection.wrappedValue
{
Text(items[index].description)
}
}
}
}
}
public struct NavPickerDetail<Items> : View where Items: CustomStringConvertible & Identifiable
{
@Binding var selection: Int?
var items:[Items]
@State var firstIndexToShow: Int = 0
@State var highlightedIndex: Int?
@Environment(\.presentationMode) var presentationMode
public var body: some View
{
List {
ForEach(firstIndexToShow..<items.count) { index in
HStack {
Text(items[index].description)
Spacer()
}
.contentShape(Rectangle())
.onTapGesture {
self.selection = index
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
self.presentationMode.wrappedValue.dismiss()
}
}
.onLongPressGesture(minimumDuration: .greatestFiniteMagnitude, maximumDistance: .greatestFiniteMagnitude, pressing: { self.highlightedIndex = $0 ? index : nil }) {}
.modifier(CheckmarkModifier(checked: index == selection))
.background(Color(UIColor.opaqueSeparator)
.opacity(highlightedIndex == index ? 1.0 : 0.0)
.padding(EdgeInsets(top: -12, leading: -16, bottom: -12, trailing: -16))
)
}
}
.listStyle(GroupedListStyle())
}
}
struct CheckmarkModifier: ViewModifier {
var checked: Bool = false
func body(content: Content) -> some View {
Group {
if checked {
ZStack(alignment: .trailing) {
content
Image(systemName: "checkmark")
.resizable()
.frame(width: 16, height: 16)
.shadow(radius: 1)
.foregroundColor(Color.accentColor)
}
} else {
content
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment