Dzięki pakietowi SDK dla systemu iOS:
Mam UIView
z UITextField
S, które wprowadzają się do klawiatury. Potrzebuję, aby móc:
Zezwól na przewijanie zawartości,
UIScrollView
aby zobaczyć inne pola tekstowe po podniesieniu klawiaturyAutomatycznie „skacz” (przewijając w górę) lub skracając
Wiem, że potrzebuję UIScrollView
. Próbowałem zmienić klasę UIView
na UIScrollView
ale, ale nadal nie mogę przewijać pól tekstowych w górę lub w dół.
Czy potrzebuję zarówno a, jak UIView
i a UIScrollView
? Czy jedno wchodzi w drugie?
Co należy zaimplementować, aby automatycznie przewinąć do aktywnego pola tekstowego?
Najlepiej, jak najwięcej ustawień komponentów zostanie przeprowadzonych w Konstruktorze interfejsów. Chciałbym pisać kod tylko dla potrzeb.
Uwaga: UIView
(lub UIScrollView
), z którym pracuję, jest wywoływane przez tabbar ( UITabBar
), który musi działać normalnie.
Edycja: Dodaję pasek przewijania tylko na czas, gdy pojawia się klawiatura. Chociaż nie jest to potrzebne, wydaje mi się, że zapewnia lepszy interfejs, ponieważ wtedy użytkownik może na przykład przewijać i zmieniać pola tekstowe.
Mam to działa tam, gdzie zmieniam rozmiar ramki, UIScrollView
gdy klawiatura idzie w górę i w dół. Po prostu używam:
-(void)textFieldDidBeginEditing:(UITextField *)textField {
//Keyboard becomes visible
scrollView.frame = CGRectMake(scrollView.frame.origin.x,
scrollView.frame.origin.y,
scrollView.frame.size.width,
scrollView.frame.size.height - 215 + 50); //resize
}
-(void)textFieldDidEndEditing:(UITextField *)textField {
//keyboard will hide
scrollView.frame = CGRectMake(scrollView.frame.origin.x,
scrollView.frame.origin.y,
scrollView.frame.size.width,
scrollView.frame.size.height + 215 - 50); //resize
}
Nie powoduje to jednak automatycznego „przesunięcia w górę” ani wyśrodkowania dolnych pól tekstowych w widocznym obszarze, czego naprawdę chciałbym.
źródło
Odpowiedzi:
Będziesz potrzebował tylko,
ScrollView
jeśli zawartość, którą masz teraz, nie mieści się na ekranie iPhone'a. (Jeśli dodajeszScrollView
jako podgląd elementów tylko po to, abyTextField
przewijać w górę, gdy pojawia się klawiatura, nie jest to konieczne).Standardowym sposobem zapobiegania
TextField
zasłonięciu klawiatury jest przesuwanie widoku w górę / w dół za każdym razem, gdy pokazana jest klawiatura.Oto przykładowy kod:
źródło
textFieldDidBeginEditing
sekcję.Miałem też duży problem z
UIScrollView
komponowaniem wieluUITextFields
, z których jeden lub więcej z nich zostałoby zasłoniętych przez klawiaturę podczas edytowania.Oto kilka rzeczy do rozważenia, jeśli twoje
UIScrollView
przewijanie nie jest prawidłowe.1) Upewnij się, że rozmiar contentSize jest większy niż
UIScrollView
rozmiar ramki. Można zrozumieć,UIScrollViews
żeUIScrollView
jest to okno do oglądania treści zdefiniowanej w contentSize. Gdy więc,UIScrollview
aby przewijać w dowolnym miejscu, contentSize musi być większy niżUIScrollView
. W przeciwnym razie przewijanie nie jest wymagane, ponieważ wszystko zdefiniowane w contentSize jest już widoczne. BTW, domyślna treść Rozmiar =CGSizeZero
.2) Teraz, gdy rozumiesz, że
UIScrollView
tak naprawdę jest to okno na twoją „treść”, sposobem na upewnienie się, że klawiatura nie zasłania twojegoUIScrollView's
„okna” oglądania, będzie zmiana rozmiaruUIScrollView
tak, aby gdy klawiatura była obecna, maszUIScrollView
okno rozmiar tylko do oryginalnejUIScrollView
ramki. rozmiar. wysokość minus wysokość klawiatury. Zapewni to, że twoje okno jest tylko tym małym widocznym obszarem.3) Oto haczyk: kiedy po raz pierwszy to zaimplementowałem, pomyślałem, że będę musiał pobrać
CGRect
edytowane pole tekstowe i wywołaćUIScrollView's
metodę scrollRecToVisible. ZaimplementowałemUITextFieldDelegate
metodętextFieldDidBeginEditing
za pomocą wywołaniascrollRecToVisible
metody To faktycznie zadziałało z dziwnym efektem ubocznym, że przewijanie zatrzasnęło sięUITextField
w pozycji. Najdłużej nie mogłem zrozumieć, co to było. Potem skomentowałemtextFieldDidBeginEditing
metodę Delegata i wszystko działa !! (???). Jak się okazało, wierzę, żeUIScrollView
faktycznie niejawnie przenosi aktualnie edytowaneUITextField
do widocznego okna. Moja implementacjaUITextFieldDelegate
metody i późniejsze wywołanie jejscrollRecToVisible
było zbędne i było przyczyną dziwnego efektu ubocznego.Oto kroki, które należy wykonać, aby poprawnie przewinąć urządzenie
UITextField
w odpowiednieUIScrollView
miejsce, gdy pojawi się klawiatura.viewDidLoad
viewDidUnload
contentSize
jest ustawiony i większy niż twójUIScrollView
wviewDidLoad
UIScrollView
gdy klawiatura jest obecnyUIScrollView
gdy klawiatura odchodzi.UITextField
jest kartach nawet jeśli klawiatura jest już obecny, aby uniknąć kurczeniaUIScrollView
kiedy jest już skurczonyJedną rzeczą do odnotowania jest to, że
UIKeyboardWillShowNotification
uruchomi się nawet, gdy klawiatura jest już na ekranie, gdy tabulujesz innąUITextField
. Zadbałem o to, używając ivara, aby uniknąć zmiany rozmiaru,UIScrollView
gdy klawiatura jest już na ekranie. Nieumyślna zmiana rozmiaru,UIScrollView
gdy klawiatura jest już dostępna, byłaby katastrofalna!Mam nadzieję, że ten kod zaoszczędzi niektórym z was dużo bólu głowy.
źródło
UIKeyboardBoundsUserInfoKey
jest przestarzały. 2. KeyboardSize ma „współrzędne ekranu”, więc obliczenia viewFrame zakończą się niepowodzeniem, jeśli ramka zostanie obrócona lub skalowana.CGSize keyboardSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
zamiast przestarzałegoUIKeyboardBoundsUserInfoKey
[[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size
powinno być[[userInfo objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size
. Świetne rozwiązanie!W rzeczywistości najlepiej jest po prostu korzystać z implementacji Apple, zgodnie z dokumentacją . Podany przez nich kod jest jednak wadliwy. Zamień część znajdującą się
keyboardWasShown:
tuż pod komentarzami na następujące:Problemy z kodem Apple są następujące: (1) Zawsze obliczają, czy punkt znajduje się w ramce widoku, ale jest to
ScrollView
, więc mógł już przewinąć i trzeba uwzględnić to przesunięcie:(2) Przesuwają zawartość Offset o wysokość klawiatury, ale chcemy mieć coś przeciwnego (chcemy przesunąć
contentOffset
o wysokość widoczną na ekranie, a nie to, co nie jest):źródło
UIKeyboardFrameEndUserInfoKey
zamiastUIKeyboardFrameBeginUserInfoKey
przy uzyskiwaniu rozmiaru klawiatury, ponieważ spowoduje to przechwycenie takich zmian, jak niestandardowe zmiany klawiatury i włączanie / wyłączanie predykcyjnego tekstu.self.scrollView.contentOffset = self.currentSVoffset;
W
textFieldDidBeginEditting
i wtextFieldDidEndEditing
wywołaniu funkcji[self animateTextField:textField up:YES]
tak:Mam nadzieję, że ten kod ci pomoże.
W Swift 2
SWIFT 3
źródło
[UIView animateWithDuration: animations:^{ }];
?Po prostu używając TextFields:
1a) Używając
Interface Builder
: Wybierz wszystkie pola tekstowe => Edytuj => Osadź w => ScrollView1b) Ręcznie osadzaj TextFields w UIScrollView o nazwie scrollView
2) Ustaw
UITextFieldDelegate
3) Ustaw każdy
textField.delegate = self;
(lub wykonaj połączeniaInterface Builder
)4) Kopiuj / Wklej:
źródło
textField
jest już widoczny.CGPointMake(0, textField.frame.origin.y);
naCGPointMake(0, textField.frame.origin.y + scrollView.contentInset.top);
W przypadku rozwiązania uniwersalnego oto moje podejście do implementacji IQKeyboardManager .
Krok 1: - dodałem globalne notyfikacje
UITextField
,UITextView
orazUIKeyboard
w klasie singleton. Nazywam to IQKeyboardManager .Krok 2: - W przypadku stwierdzenia
UIKeyboardWillShowNotification
,UITextFieldTextDidBeginEditingNotification
czyUITextViewTextDidBeginEditingNotification
powiadomienia, staram się dostaćtopMostViewController
wystąpienie zUIWindow.rootViewController
hierarchii. W celu prawidłowego odkryciaUITextField
/UITextView
na nim,topMostViewController.view
rama musi zostać dostosowana.Krok 3: - Obliczyłem spodziewaną odległość ruchu
topMostViewController.view
w stosunku do pierwszej odpowiedziUITextField
/UITextView
.Krok 4: - Poruszałem się w
topMostViewController.view.frame
górę / w dół zgodnie z oczekiwaną odległością ruchu.Krok 5: - W przypadku stwierdzenia
UIKeyboardWillHideNotification
,UITextFieldTextDidEndEditingNotification
czyUITextViewTextDidEndEditingNotification
zgłoszenie, znowu postarać siętopMostViewController
wystąpienie zUIWindow.rootViewController
hierarchii.Krok 6: - Obliczyłem zakłóconą odległość,
topMostViewController.view
którą należy przywrócić do pierwotnej pozycji.Krok 7: - Przywróciłem w
topMostViewController.view.frame
dół zgodnie z zakłóconą odległością.Krok 8: - Utworzyłem instancję klasy singleton IQKeyboardManager podczas ładowania aplikacji, więc każda
UITextField
/UITextView
w aplikacji dostosuje się automatycznie zgodnie z oczekiwaną odległością ruchu.To wszystko, co IQKeyboardManager robi dla Ciebie bez NO LINE OF CODE naprawdę !! wystarczy przeciągnąć i upuścić powiązany plik źródłowy do projektu. IQKeyboardManager obsługuje również orientację urządzenia , automatyczne zarządzanie paskiem narzędzi UITool , KeybkeyboardDistanceFromTextField i wiele więcej niż myślisz.
źródło
Stworzyłem uniwersalną, rozwijaną
UIScrollView
,UITableView
a nawetUICollectionView
podklasę, która zajmuje się przenoszeniem wszystkich pól tekstowych poza klawiaturę.Kiedy klawiatura ma się pojawić, podklasa znajdzie widok podrzędny, który ma być edytowany, i dostosuje przesunięcie ramki i zawartości, aby upewnić się, że widok jest widoczny, z animacją dopasowaną do wyskakującego okna klawiatury. Kiedy klawiatura znika, przywraca jej poprzedni rozmiar.
Powinien działać w zasadzie z dowolną konfiguracją,
UITableView
opartą na interfejsie lub opartą na widokach umieszczanych ręcznie.Oto rozwiązanie : przenoszenie pól tekstowych z klawiatury
źródło
To zrobi wszystko za Ciebie, po prostu umieść je w klasie kontrolera widoku i zaimplementuj w
UITextFieldDelegate
kontrolerze widoku i ustaw delegata textField naself
Wdróż delegowane metody wywołania zwrotnego:
Dla Swift 4, 4.2, 5: zmiana
do
Ostatnia uwaga na temat tej implementacji: jeśli wepchniesz inny kontroler widoku na stos, gdy klawiatura jest wyświetlona, spowoduje to błąd, gdy widok zostanie przywrócony do środkowej ramki, ale przesunięcie klawiatury nie zostanie zresetowane. Na przykład klawiatura jest pierwszą odpowiedzią dla nameField, ale następnie naciskasz przycisk, który wpycha kontroler widoku pomocy na stos. Aby naprawić błąd przesunięcia, pamiętaj o wywołaniu nameField.resignFirstResponder () przed opuszczeniem kontrolera widoku, upewniając się, że wywoływana jest również metoda delegowania textFieldDidEndEditing. Robię to w metodzie viewWillDisappear.
źródło
self.view.frame = CGRectOffset(self.view.frame, 0, movement)
więc zmieniłem tę linię naself.view.frame.offsetInPlace(dx: 0, dy: movement)
Jest już wiele odpowiedzi, ale wciąż żadne z powyższych rozwiązań nie zawierało wszystkich wymyślnych elementów pozycjonowania wymaganych do „idealnej” bezbłędnej, kompatybilnej wstecz i bez migotania animacji. (błąd podczas animacji ramki / granic i zawartości razem, różne ustawienia interfejsu, podzielona klawiatura iPada, ...)
Pozwól, że podzielę się moim rozwiązaniem:
(zakładając, że skonfigurowałeś
UIKeyboardWill(Show|Hide)Notification
)źródło
UIApplication.shared.sendAction(...)
. Oto twoja odpowiedź Swift 3 (bez części willHide), zsendAction
zaimplementowanym: gist.github.com/xaphod/7aab1302004f6e933593a11ad8f5a72dShiun powiedział: „Jak się okazało, uważam, że UIScrollView pośrednio przenosi obecnie edytowany UITextField do widocznego okna”. Wydaje się, że tak jest w przypadku iOS 3.1.3, ale nie 3.2, 4.0 lub 4.1. Musiałem dodać wyraźny scrollRectToVisible, aby UITextField był widoczny w iOS> = 3.2.
źródło
[UITextField scrollTextFieldToVisibleIfNecessary]
metodę prywatną , która z kolei wywołuje,[UIScrollView scrollRectToVisible]
gdy[UITextField becomeFirstResponder]
jest wywoływana. Zobacz github.com/leopatras/ios_textfields_on_scrollview . Jeśli ograniczenia i kontrolery widoku są poprawnie skonfigurowane, tak naprawdę nie ma potrzebyscrollRectToVisible
jawnego wywoływania (przynajmniej od IOS 11).Jedną z rzeczy do rozważenia jest to, czy kiedykolwiek będziesz chciał używać
UITextField
własnego. Nie spotkałem dobrze zaprojektowanych aplikacji na iPhone'a, które faktycznie używająUITextFields
pozaUITableViewCells
.To będzie dodatkowa praca, ale zalecam wdrożenie wszystkich widoków wprowadzania danych w widokach tabel. Dodaj
UITextView
do swojegoUITableViewCells
.źródło
UITableView
jest niestety jedyną drogą do przejścia. Powiadomienia z klawiatury są kruche i z czasem uległy zmianie. Przykładowy kod dotyczący przepełnienia stosu: stackoverflow.com/a/32390936/218152W tym dokumencie szczegółowo opisano rozwiązanie tego problemu. Spójrz na kod źródłowy w części „Przenoszenie treści znajdujących się pod klawiaturą”. To całkiem proste.
EDYCJA: Zauważyłem usterkę wee w przykładzie. Prawdopodobnie będziesz chciał słuchać
UIKeyboardWillHideNotification
zamiastUIKeyboardDidHideNotification
. W przeciwnym razie widok przewijania za klawiaturą zostanie przycięty na czas animacji zamykania klawiatury.źródło
Najłatwiejsze znalezione rozwiązanie
źródło
int movement = (up ? -movementDistance : movementDistance);
if (textField.frame.origin.y < self.view.frame.size.height - keyboard.height) { movementDistance = 0 }
Proszę niekeyboard
pamiętać, że zmienna jest CGRect klawiatury, która się wyskakuje, którą otrzymujesz, wykonując:let keyboard = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey]!.CGRectValue())!
Mała poprawka, która działa dla wielu UITextFields
źródło
rect.origin.y=+currTextField.frame.origin.y
działa dobrze dziękujęKod RPDP skutecznie usuwa pole tekstowe z klawiatury. Ale po przewinięciu do góry po użyciu i zwolnieniu klawiatury góra została przewinięta w górę z widoku. Dotyczy to symulatora i urządzenia. Aby przeczytać treść u góry tego widoku, należy go ponownie załadować.
Czy jego poniższy kod nie powinien obniżać widoku?
źródło
Nie jestem pewien, czy przesunięcie widoku w górę jest właściwym podejściem, zrobiłem to w inny sposób, zmieniając rozmiar UIScrollView. Wyjaśniłem to szczegółowo w małym artykule
źródło
Aby przywrócić pierwotny stan widoku, dodaj:
źródło
Wypróbuj tę krótką sztuczkę.
źródło
Jest tak wiele rozwiązań, ale spędziłem kilka godzin, zanim zacznie działać. Więc umieszczam ten kod tutaj (wystarczy wkleić do projektu, żadne modyfikacje nie muszą):
PS: Mam nadzieję, że kod pomoże komuś szybko uzyskać pożądany efekt. (Xcode 4.5)
źródło
@ user271753
Aby przywrócić widok do oryginalnego, dodaj:
źródło
Przesunięcie ramki widoku nie wymaga widoku przewijania. Możesz zmienić ramkę
viewcontroller's
widoku, aby cały widok przesunął się w górę na tyle, aby umieścić pierwsze pole tekstowe nad klawiaturą. Kiedy napotkałem ten problem, stworzyłem podklasęUIViewController
, która to robi. Zauważa, że na klawiaturze pojawi się powiadomienie i znajdzie widok pierwszego reagującego i (w razie potrzeby) animuje widok główny w górę tak, aby pierwszy odpowiadający znalazł się nad klawiaturą. Gdy klawiatura się chowa, animuje widok z powrotem tam, gdzie była.Aby użyć tej podklasy, ustaw niestandardowy kontroler widoku na podklasę GMKeyboardVC i dziedziczy ona tę funkcję (upewnij się, że ją zaimplementowałeś
viewWillAppear
iviewWillDisappear
że musi ona wywoływać super). Klasa jest na githubie .źródło
Szybki 4 .
Można łatwo poruszać się w górę iw dół
UITextField
OrUIView
WithUIKeyBoard
WithAnimation
źródło
Oto rozwiązanie hakerskie, które wymyśliłem dla konkretnego układu. To rozwiązanie jest podobne do rozwiązania Matta Gallaghera, ponieważ przewija sekcję do widoku. Nadal jestem nowicjuszem w projektowaniu iPhone'ów i nie znam sposobu działania układów. Tak więc ten hack.
Moja implementacja musiała obsługiwać przewijanie po kliknięciu pola, a także przewijanie, gdy użytkownik wybierze następny na klawiaturze.
Miałem UIView o wysokości 775. Elementy sterujące są rozmieszczone zasadniczo w grupach po 3 na dużej przestrzeni. Skończyło się na następującym układzie IB.
Nadchodzi hack
Ustawiłem wysokość UIScrollView na 500 jednostek większą niż rzeczywisty układ (1250). Następnie utworzyłem tablicę z absolutnymi pozycjami, do których muszę przewijać, oraz prostą funkcją, aby uzyskać je na podstawie numeru znacznika IB.
Teraz wystarczy użyć dwóch następujących wierszy kodu w textFieldDidBeginEditing i textFieldShouldReturn (ten ostatni, jeśli tworzysz nawigację po kolejnych polach)
Przykład.
Ta metoda nie „przewija do tyłu”, jak inne metody. To nie był wymóg. Znów było to dla dość „wysokiego” UIView i nie miałem dni na naukę wewnętrznych mechanizmów układu.
źródło
Zgodnie z dokumentacją , w iOS 3.0
UITableViewController
klasa automatycznie zmienia rozmiar i zmienia położenie widoku tabeli, gdy istnieje bezpośrednia edycja pól tekstowych. Myślę, że nie wystarczy umieścić pole tekstowe w polu,UITableViewCell
jak niektórzy wskazywali.Z dokumentów :
źródło
Musisz po prostu skopiować i wkleić poniższy przykładowy kod i zmienić pole tekstowe lub dowolny widok, który chcesz przenieść w górę.
Krok 1
Krok 2
Krok 3
Referencje : cóż, proszę docenić tego faceta , który udostępnił to piękne wycięcie kodu, czyste rozwiązanie.
Mam nadzieję, że byłoby to bardzo pomocne komuś tam.
źródło
Szukając dobrego samouczka dla początkujących na ten temat, znalazłem najlepszy samouczek tutaj .
W
MIScrollView.h
przykładzie na dole samouczka umieść spację wjak widzicie.
źródło
Kiedy
UITextField
jest wUITableViewCell
przewijanie powinno być ustawione automatycznie.Jeśli tak nie jest, prawdopodobnie przyczyną jest niewłaściwy kod / ustawienie widoku tabeli.
Na przykład, kiedy ponownie załadowałem mój długi stół z jednym
UITextField
na dole w następujący sposób,wtedy moje pole tekstowe u dołu zostało zasłonięte przez klawiaturę, która pojawiła się po kliknięciu wewnątrz pola tekstowego.
Aby to naprawić, musiałem to zrobić -
źródło
viewWillAppear
nie jest wywoływana. IreloadData
nie powoduje, że zasłonięte rzędy stają się widoczne.Użyj tej strony trzeciej, nie musisz pisać nawet jednej linii
https://github.com/hackiftekhar/IQKeyboardManager
pobierz projekt i przeciągnij i upuść
IQKeyboardManager
swój projekt. Jeśli znajdziesz jakiś problem, przeczytajREADME
dokument.Chłopaki naprawdę usuwają ból głowy, aby zarządzać klawiaturą.
źródło
Uwaga : ta odpowiedź zakłada, że pole tekstowe znajduje się w scrollView.
Wolę sobie z tym poradzić, używając scrollContentInset i scrollContentOffset zamiast mieszać się z ramkami mojego widoku.
Najpierw posłuchajmy powiadomień z klawiatury
Następnym krokiem jest zachowanie właściwości reprezentującej bieżącego pierwszego respondera (UITextfield / UITextVIew, która obecnie ma klawiaturę).
Używamy metod delegowania, aby ustawić tę właściwość. Jeśli używasz innego komponentu, będziesz potrzebować czegoś podobnego.
Zauważ, że dla pola tekstowego ustawiamy go w didBeginEditing, a dla textView w shouldBeginEditing. Wynika to z tego, że textViewDidBeginEditing jest wywoływany po UIKeyboardWillShowNotification z jakiegoś powodu.
Wreszcie, oto magia
źródło
To jest rozwiązanie wykorzystujące Swift.
źródło