Прокрутите вверх, чтобы увидеть TextField, когда клавиатура появится в SwiftUI.

В моем случае использования я должен поставить TextField под доступными элементами в List, и, используя этот TextField, мы можем добавить элементы в List.

Изначально элементов списка нет (массив items пуст)

Вот минимальный воспроизводимый пример

import SwiftUI

struct ContentView: View {
    @State var itemName = ""
    @State var items = [String]()

    var body: some View {
        NavigationView {
            List {
                ForEach(self.items, id: \.self) {
                    Text($0)
                }

                VStack {
                    TextField("Item Name", text: $itemName)
                        .textFieldStyle(RoundedBorderTextFieldStyle())

                    Button(action: {
                        self.items.append(self.itemName)
                        self.itemName = ""

                    }) {
                        Text("Add Item")
                    }
                }
            }
        .navigationBarTitle(Text("Title"))
        }
    }
}

Мы можем добавить новый элемент в список, набрав что-нибудь в TextField и нажав «Добавить элемент» Button. Каждый элемент, который мы добавляем с помощью TextField, появляется над текстовым полем в List. Итак, TextField падает в List (точно так же, как приложение Apple Reminders).

Если в приложении много элементов (более 7 элементов), клавиатура закрывает TextField, когда появляется клавиатура, и мы не можем видеть TextField.
Проверьте этот снимок экрана:

Я хочу знать, как автоматически прокручивать список (перемещать представление вверх), чтобы увидеть TextField при появлении клавиатуры (как в приложении Apple Reminders).


person umayanga    schedule 17.09.2019    source источник
comment
Одна вещь, которую вы могли бы сделать (уклоняясь от вашего вопроса здесь), - это переместить текстовое поле в другое место. Это могло бы решить этот случай, но, очевидно, не решило бы более серьезной проблемы, связанной с перемещением предметов в соответствии с клавиатурой.   -  person LinusGeffarth    schedule 17.09.2019
comment
Это может вам помочь: stackoverflow.com/questions/57753060/   -  person Sagar Chauhan    schedule 17.09.2019
comment
см. также здесь: stackoverflow.com/questions/56716311/   -  person Andre Carrera    schedule 18.09.2019
comment
comment
Я пробовал несколько разных подходов, и в итоге у меня сработало stackoverflow.com/a/60178361/4189037   -  person Predrag Samardzic    schedule 12.02.2020


Ответы (1)


У меня была аналогичная проблема в моем недавнем проекте, самый простой способ решить ее - обернуть UITextField в SwiftUI и из моей настраиваемой оболочки добраться до родительского представления прокрутки и сказать ему прокручивать при появлении клавиатуры. Я попробовал свой подход к вашему проекту, и, похоже, он работает.

Если вы возьмете мой код для оболочки и другие файлы из этой папки GitHub: https://github.com/LostMoa/SwiftUI-Code-Examples/tree/master/ScrollTextFieldIntoVisibleRange, а затем замените SwiftUI TextField моим пользовательским представлением (TextFieldWithKeyboardObserver), после чего оно должно прокрутиться.

import SwiftUI

struct ContentView: View {
    @State var itemName = ""
    @State var items = [String]()

    var body: some View {
        NavigationView {
            List {
                ForEach(self.items, id: \.self) {
                    Text($0)
                }

                VStack {
                    TextFieldWithKeyboardObserver(text: $itemName, placeholder: "Item Name")

                    Button(action: {
                        self.items.append(self.itemName)
                        self.itemName = ""

                    }) {
                        Text("Add Item")
                    }
                }
            }
        .navigationBarTitle(Text("Title"))
        }
    }
}

Недавно я написал статью, объясняющую это решение: https://lostmoa.com/blog/ScrollTextFieldIntoVisibleRange/

person Natalia Panferova    schedule 13.02.2020
comment
Большое спасибо за это! Отличный ответ и отличная статья. Я думаю, что SwiftUI нуждается в лучшем способе справиться с этим, а до тех пор упаковка UIKitTextField - лучший способ, на мой взгляд - я перепробовал множество решений. Спасибо еще раз! - person Daniel Barclay; 20.02.2020
comment
это лучший ответ для обработки UITextField с помощью List или ScrollView, я использовал ваш подход, чтобы переместить UITextView вверх, пока пользователь набирает, где UITextView расширяется по высоте (не прокручивается) в соответствии с введенным текстом - person JAHelia; 24.02.2020
comment
Гениальная идея! Хороший пост в блоге тоже. - person Brett; 01.04.2020
comment
Я пытаюсь использовать это решение, поскольку оно работает очень хорошо, но использование настраиваемого текстового поля отключает все другие методы swiftui, которые вы можете вызывать в обычное текстовое поле, например .keyboardType(), multilineTextAlignment() и т. Д. Есть ли способ обойти это? - person Amin; 14.04.2020
comment
Это лучшее решение, и его следует отметить как принятый ответ. - person Di Nerd; 26.05.2020