forked from AcaMate/AcaMate_iOS
96 lines
2.6 KiB
Swift
96 lines
2.6 KiB
Swift
//
|
|
// DropDownView.swift
|
|
// AcaMate
|
|
//
|
|
// Created by TAnine on 3/25/25.
|
|
//
|
|
|
|
import SwiftUI
|
|
class DropdownManager: ObservableObject {
|
|
static let shared = DropdownManager()
|
|
|
|
@Published var isPresented = false
|
|
@Published var items: [String] = []
|
|
@Published var anchor: CGRect = .zero
|
|
var onSelect: ((String) -> Void)?
|
|
|
|
func show(items: [String], anchor: CGRect, onSelect: @escaping (String) -> Void) {
|
|
self.items = items
|
|
self.anchor = anchor
|
|
self.onSelect = onSelect
|
|
isPresented = true
|
|
}
|
|
|
|
func dismiss() {
|
|
isPresented = false
|
|
}
|
|
}
|
|
|
|
struct DropdownButton: View {
|
|
let title: String
|
|
let items: [String]
|
|
|
|
@State private var frame: CGRect = .zero
|
|
|
|
var body: some View {
|
|
Button {
|
|
DropdownManager.shared.show(items: items, anchor: frame) { selected in
|
|
print("선택한 항목:", selected)
|
|
}
|
|
} label: {
|
|
HStack {
|
|
Text(title)
|
|
Image(systemName: "chevron.down")
|
|
}
|
|
.padding()
|
|
.background(RoundedRectangle(cornerRadius: 8).stroke(Color.gray))
|
|
}
|
|
.background(
|
|
GeometryReader { geo in
|
|
Color.clear
|
|
.onAppear {
|
|
frame = geo.frame(in: .global)
|
|
}
|
|
}
|
|
)
|
|
}
|
|
}
|
|
|
|
|
|
struct GlobalDropdownOverlay: View {
|
|
@ObservedObject var manager = DropdownManager.shared
|
|
|
|
var body: some View {
|
|
if manager.isPresented {
|
|
ZStack(alignment: .topLeading) {
|
|
Color.black.opacity(0.001)
|
|
.ignoresSafeArea()
|
|
.onTapGesture {
|
|
manager.dismiss()
|
|
}
|
|
|
|
VStack(alignment: .leading, spacing: 0) {
|
|
ForEach(manager.items, id: \.self) { item in
|
|
Button {
|
|
manager.onSelect?(item)
|
|
manager.dismiss()
|
|
} label: {
|
|
Text(item)
|
|
.padding()
|
|
.frame(maxWidth: .infinity, alignment: .leading)
|
|
}
|
|
.buttonStyle(.plain)
|
|
.background(Color.white)
|
|
}
|
|
}
|
|
.frame(width: manager.anchor.width)
|
|
.background(RoundedRectangle(cornerRadius: 8).stroke(Color.gray))
|
|
.shadow(radius: 5)
|
|
.position(x: manager.anchor.midX, y: manager.anchor.maxY + 10)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|