Last active
August 20, 2024 16:11
-
-
Save sammcode/a57b54c9f43154b12c6fb646aca0dc5e to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import SwiftUI | |
import SwiftData | |
import UIKit | |
@Model | |
class Item { | |
var text: String = "" | |
init(text: String) { | |
self.text = text | |
} | |
} | |
struct TextInputView: View { | |
@Environment(\.modelContext) var modelContext | |
@State private var textFieldText = "" | |
var body: some View { | |
TextField("Type here", text: $textFieldText) | |
.textFieldStyle(RoundedBorderTextFieldStyle()) | |
.padding() | |
.onSubmit { | |
modelContext.insert(Item(text: textFieldText)) | |
textFieldText = "" | |
} | |
} | |
} | |
struct KeyboardAnchoredContainer<Content: View, Input: View>: UIViewControllerRepresentable { | |
typealias ViewController = KeyboardAnchoredContainerViewController | |
@ViewBuilder var content: () -> Content | |
@ViewBuilder var input: () -> Input | |
func makeUIViewController(context: Context) -> ViewController<Content, Input> { | |
ViewController(content: content(), input: input()) | |
} | |
func updateUIViewController(_ uiViewController: ViewController<Content, Input>, context: Context) {} | |
} | |
class KeyboardAnchoredContainerViewController<Content: View, Input: View>: UIViewController { | |
var content: Content | |
var input: Input | |
init(content: Content, input: Input) { | |
self.content = content | |
self.input = input | |
super.init(nibName: nil, bundle: nil) | |
} | |
required init?(coder: NSCoder) { | |
fatalError("init(coder:) has not been implemented") | |
} | |
override func viewDidLoad() { | |
setUpContent() | |
setUpInput() | |
} | |
private func setUpContent() { | |
let hostingView = UIHostingController(rootView: content) | |
hostingView.view.translatesAutoresizingMaskIntoConstraints = false | |
view.addSubview(hostingView.view) | |
// Anchor content to top of keyboard layout | |
NSLayoutConstraint.activate([ | |
hostingView.view.bottomAnchor.constraint(equalTo: view.keyboardLayoutGuide.topAnchor), | |
hostingView.view.leadingAnchor.constraint(equalTo: view.leadingAnchor), | |
hostingView.view.trailingAnchor.constraint(equalTo: view.trailingAnchor), | |
hostingView.view.topAnchor.constraint(equalTo: view.topAnchor), | |
]) | |
} | |
private func setUpInput() { | |
let hostingView = UIHostingController(rootView: TextInputView()) | |
view.addSubview(hostingView.view) | |
hostingView.view.translatesAutoresizingMaskIntoConstraints = false | |
// Anchor input to top of keyboard layout | |
NSLayoutConstraint.activate([ | |
hostingView.view.bottomAnchor.constraint(equalTo: view.keyboardLayoutGuide.topAnchor), | |
hostingView.view.leadingAnchor.constraint(equalTo: view.leadingAnchor), | |
hostingView.view.trailingAnchor.constraint(equalTo: view.trailingAnchor), | |
hostingView.view.heightAnchor.constraint(equalToConstant: 46) | |
]) | |
} | |
} | |
struct ContentView: View { | |
var body: some View { | |
KeyboardAnchoredContainer { | |
ItemListView() | |
} input: { | |
TextInputView() | |
} | |
// This is key, otherwise the text input taps into SwiftUI's keyboard safe area avoidance. | |
.ignoresSafeArea(.keyboard) | |
} | |
} | |
struct ItemListView: View { | |
// Define the Query here so the view can update itself. | |
@Query var items: [Item] | |
var body: some View { | |
ScrollView { | |
VStack { | |
ForEach(items) { item in | |
HStack { | |
Text(item.text) | |
.padding() | |
Spacer() | |
} | |
} | |
} | |
// Inset content slightly to avoid overlap with text input. | |
.padding(.bottom, 40) | |
} | |
.scrollDismissesKeyboard(.interactively) | |
.scrollClipDisabled() | |
.defaultScrollAnchor(.bottom) | |
} | |
} | |
#Preview { | |
ContentView() | |
.modelContainer(for: Item.self, inMemory: true) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment