fix: Improve keyboard behavior in ShareBookmarkView
- Add focus state management for proper text field scrolling - Fix keyboard padding to prevent content overlap - Smooth animations and remove visual artifacts
This commit is contained in:
parent
e4f055a6af
commit
4915a773d6
@ -3,7 +3,7 @@ import SwiftUI
|
|||||||
struct ShareBookmarkView: View {
|
struct ShareBookmarkView: View {
|
||||||
@ObservedObject var viewModel: ShareBookmarkViewModel
|
@ObservedObject var viewModel: ShareBookmarkViewModel
|
||||||
@State private var keyboardHeight: CGFloat = 0
|
@State private var keyboardHeight: CGFloat = 0
|
||||||
@State private var shouldScrollToTitle = false
|
@FocusState private var focusedField: AddBookmarkFieldFocus?
|
||||||
|
|
||||||
private func dismissKeyboard() {
|
private func dismissKeyboard() {
|
||||||
NotificationCenter.default.post(name: NSNotification.Name("DismissKeyboard"), object: nil)
|
NotificationCenter.default.post(name: NSNotification.Name("DismissKeyboard"), object: nil)
|
||||||
@ -17,19 +17,20 @@ struct ShareBookmarkView: View {
|
|||||||
logoSection
|
logoSection
|
||||||
urlSection
|
urlSection
|
||||||
tagManagementSection
|
tagManagementSection
|
||||||
|
.id(AddBookmarkFieldFocus.labels)
|
||||||
titleSection
|
titleSection
|
||||||
.id("titleField")
|
.id(AddBookmarkFieldFocus.title)
|
||||||
statusSection
|
statusSection
|
||||||
Spacer(minLength: 100) // Space for button
|
Spacer(minLength: 100) // Space for button
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.padding(.bottom, keyboardHeight / 2)
|
.padding(.bottom, max(0, keyboardHeight - 120))
|
||||||
.onChange(of: shouldScrollToTitle) { shouldScroll, _ in
|
.onChange(of: focusedField) { newField, _ in
|
||||||
if shouldScroll {
|
guard let field = newField else { return }
|
||||||
withAnimation(.easeInOut(duration: 0.3)) {
|
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
|
||||||
proxy.scrollTo("titleField", anchor: .center)
|
withAnimation(.easeInOut(duration: 0.25)) {
|
||||||
|
proxy.scrollTo(field, anchor: .center)
|
||||||
}
|
}
|
||||||
shouldScrollToTitle = false
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -39,25 +40,21 @@ struct ShareBookmarkView: View {
|
|||||||
.background(Color(.systemGroupedBackground))
|
.background(Color(.systemGroupedBackground))
|
||||||
.onAppear { viewModel.onAppear() }
|
.onAppear { viewModel.onAppear() }
|
||||||
.ignoresSafeArea(.keyboard, edges: .bottom)
|
.ignoresSafeArea(.keyboard, edges: .bottom)
|
||||||
.background(
|
.contentShape(Rectangle())
|
||||||
Color.clear
|
.onTapGesture {
|
||||||
.contentShape(Rectangle())
|
dismissKeyboard()
|
||||||
.onTapGesture {
|
}
|
||||||
// Fallback for extensions: tap anywhere to dismiss keyboard
|
|
||||||
dismissKeyboard()
|
|
||||||
}
|
|
||||||
)
|
|
||||||
.onReceive(NotificationCenter.default.publisher(for: UIResponder.keyboardWillShowNotification)) { notification in
|
.onReceive(NotificationCenter.default.publisher(for: UIResponder.keyboardWillShowNotification)) { notification in
|
||||||
if let keyboardFrame = notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect {
|
if let keyboardFrame = notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect {
|
||||||
keyboardHeight = keyboardFrame.height
|
withAnimation(.easeInOut(duration: 0.3)) {
|
||||||
// Scroll to title field when keyboard appears
|
keyboardHeight = keyboardFrame.height
|
||||||
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
|
|
||||||
shouldScrollToTitle = true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.onReceive(NotificationCenter.default.publisher(for: UIResponder.keyboardWillHideNotification)) { _ in
|
.onReceive(NotificationCenter.default.publisher(for: UIResponder.keyboardWillHideNotification)) { _ in
|
||||||
keyboardHeight = 0
|
withAnimation(.easeInOut(duration: 0.3)) {
|
||||||
|
keyboardHeight = 0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -103,6 +100,7 @@ struct ShareBookmarkView: View {
|
|||||||
.padding(.horizontal, 4)
|
.padding(.horizontal, 4)
|
||||||
.frame(maxWidth: 420)
|
.frame(maxWidth: 420)
|
||||||
.frame(maxWidth: .infinity, alignment: .center)
|
.frame(maxWidth: .infinity, alignment: .center)
|
||||||
|
.focused($focusedField, equals: .title)
|
||||||
.toolbar {
|
.toolbar {
|
||||||
ToolbarItemGroup(placement: .keyboard) {
|
ToolbarItemGroup(placement: .keyboard) {
|
||||||
Spacer()
|
Spacer()
|
||||||
@ -123,6 +121,7 @@ struct ShareBookmarkView: View {
|
|||||||
isLabelsLoading: false,
|
isLabelsLoading: false,
|
||||||
availableLabelPages: convertToBookmarkLabelPages(viewModel.availableLabelPages),
|
availableLabelPages: convertToBookmarkLabelPages(viewModel.availableLabelPages),
|
||||||
filteredLabels: convertToBookmarkLabels(viewModel.filteredLabels),
|
filteredLabels: convertToBookmarkLabels(viewModel.filteredLabels),
|
||||||
|
searchFieldFocus: $focusedField,
|
||||||
onAddCustomTag: {
|
onAddCustomTag: {
|
||||||
addCustomTag()
|
addCustomTag()
|
||||||
},
|
},
|
||||||
@ -176,7 +175,6 @@ struct ShareBookmarkView: View {
|
|||||||
.padding(.top, 16)
|
.padding(.top, 16)
|
||||||
.padding(.bottom, 32)
|
.padding(.bottom, 32)
|
||||||
.disabled(viewModel.isSaving)
|
.disabled(viewModel.isSaving)
|
||||||
.background(Color(.systemGroupedBackground))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// MARK: - Helper Functions
|
// MARK: - Helper Functions
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user