Предотвращение клавиатуры SwiftUI ScrollView

#swiftui

#swiftui

Вопрос:

Во-первых. Я знаю, что SwiftUI ScrollView имеет ограничения. Я надеюсь обойти это здесь.

Моя проблема в том, что у меня есть чат box…so VStack с видом прокрутки и вводом текста. Я могу сделать так, чтобы ввод текста был адаптивным к клавиатуре … т.е. При вводе он сдвигается вверх вместе с клавиатурой.

Проблема в том, что ScrollView теряет свою позицию прокрутки. Итак, если вы прокрутите страницу вниз, а затем активируете клавиатуру … вы больше не увидите дно. Это почти как ZStack.

Я хочу имитировать то же поведение, что и WhatsApp, который сохраняет положение прокрутки при вводе нового сообщения.

Я знаю о ScrollViewReader и scrollTo … в данном случае это кажется взломом, и я надеюсь избежать этого. Если что, может быть, есть исправление, связанное с макетом?

Ответ №1:

По счастливой случайности я смог решить эту проблему, добавив .keyboardAdaptive() как к ScrollView, так и к текстовому вводу, а также изменив отступ на смещение

 struct KeyboardAdaptive: ViewModifier {
    @State private var keyboardHeight: CGFloat = 0

    @State var offset: CGFloat
    
    func body(content: Content) -> some View {
        content
            .offset(y: -keyboardHeight)
            .onReceive(Publishers.keyboardHeight) {
                self.keyboardHeight = $0 == 0 ? 0 : $0 - offset
            }
    }
}
 

Комментарии:

1. Это выглядит как отличный ответ @Timmerz, но я не уверен, откуда Publishers.keyboardHeight берется 😕

2. github.com/V8tr/KeyboardAvoidanceSwiftUI

3. есть ли собственный способ получить высоту клавиатуры?

Ответ №2:

Может быть, лучший вариант. Если вы используете iOS 14 с scrollview или у вас есть возможность использовать scrollview.

https://developer.apple.com/documentation/swiftui/scrollviewproxy
https://developer.apple.com/documentation/swiftui/scrollviewreader

Ниже может помочь

         ScrollViewReader { (proxy: ScrollViewProxy) in
            ScrollView {
                view1().frame(height: 200)
                view2().frame(height: 200)

                view3() <-----this has textfields 
                    .onTapGesture {
                        proxy.scrollTo(1, anchor: .center)
                    }
                    .id(1)

                view4() <-----this has text editor
                    .onTapGesture {
                        proxy.scrollTo(2, anchor: .center)
                    }
                    .id(2)

                view5().frame(height: 200)
                view6().frame(height: 200)
                submtButton().frame(height: 200)
            }
        }
 

часть imp сверху

          anyView().onTapGesture {
              proxy.scrollTo(_ID, anchor: .center)
         }.id(_ID)
 

Надеюсь, это кому-то поможет 🙂