2014-12-23 10 views
12

Próbuję przenieść UITextView powyżej klawiatury, gdy klawiatura pojawia się/zmienia. Powiedzmy, że mam wyświetlaną angielską klawiaturę, a następnie przełączam się bezpośrednio na chińską klawiaturę (która jest wyższa niż standardowa angielska klawiatura). W tym scenariuszu widok mojego tekstu zawsze wydaje się zbyt wysoki (nieuzbrojone oko, wygląda na to, że widok tekstu jest nieprawidłowo przesunięty o rozmiar chińskiej klawiatury "widok akcesoriów wejściowych". Wpisałbym obrazek, ale brak mu reputacji więc :)). Zmieniam pozycję widoku tekstu, gdy moja aplikacja otrzymuje UIKeyboardDidShowNotification (za pomocą UIKeyboardFrameEndUserInfoKey, aby uzyskać wysokość), a po pewnym dochodzeniu UIKeyboardDidShowNotification jest wywoływana wiele razy, często z nieprawidłowymi wymiarami klawiatury (Mam NSLogged słownik userInfo). Zgłaszam się do powiadomień na klawiaturze w ViewWillAppear i wyrejestruję w ViewWillDisappear. Nie jestem w stanie określić, co może powodować wielokrotne uruchamianie tego powiadomienia; rozumiem, że to powiadomienie powinno zostać uruchomione tylko jeden raz, zaraz po zakończeniu wyświetlania klawiatury. Dodatkowa uwaga: Mam NSLogged "self" w metodzie, która odpowiada na UIKeyboardDidShowNotification i to jest w rzeczywistości zawsze ten sam View Controller Object.UIKeyboardDidShowNotification wywołana wiele razy, a czasami z nieprawidłowymi wymiarami klawiatury

Mimo tego powiadomienia wielokrotnie, nadal nie rozumiem, dlaczego wysokość klawiatury byłaby inna w przypadku niektórych z tych powiadomień. Jedno z powiadomień ma zawsze odpowiednią wysokość, ale kiedy nie jest to ostatnie powiadomienie, widok tekstu kończy się w niewłaściwym miejscu. Dowiemy się, jak dalej rozwiązywać problemy!

EDYCJA: Im więcej testuję, tym bardziej wydaje mi się, że jest to problem z chińską klawiaturą. Ilekroć przełączyć klawiaturę z angielskiego na chiński mam trzy UIKeyboardWillShowNotifications:

2014-12-24 22:49:29.385 Example[1055:421943] info dictionary: { 
UIKeyboardAnimationCurveUserInfoKey = 0; 
UIKeyboardAnimationDurationUserInfoKey = 0; 
UIKeyboardBoundsUserInfoKey = "NSRect: {{0, 0}, {320, 252}}"; 
UIKeyboardCenterBeginUserInfoKey = "NSPoint: {160, 460}"; 
UIKeyboardCenterEndUserInfoKey = "NSPoint: {160, 442}"; 
UIKeyboardFrameBeginUserInfoKey = "NSRect: {{0, 352}, {320, 216}}"; 
UIKeyboardFrameEndUserInfoKey = "NSRect: {{0, 316}, {320, 252}}"; 
} 
2014-12-24 22:49:29.408 Example[1055:421943] info dictionary: { 
UIKeyboardAnimationCurveUserInfoKey = 0; 
UIKeyboardAnimationDurationUserInfoKey = 0; 
UIKeyboardBoundsUserInfoKey = "NSRect: {{0, 0}, {320, 216}}"; 
UIKeyboardCenterBeginUserInfoKey = "NSPoint: {160, 442}"; 
UIKeyboardCenterEndUserInfoKey = "NSPoint: {160, 460}"; 
UIKeyboardFrameBeginUserInfoKey = "NSRect: {{0, 316}, {320, 252}}"; 
UIKeyboardFrameEndUserInfoKey = "NSRect: {{0, 352}, {320, 216}}"; 
} 
2014-12-24 22:49:29.420 Example[1055:421943] info dictionary: { 
UIKeyboardAnimationCurveUserInfoKey = 0; 
UIKeyboardAnimationDurationUserInfoKey = 0; 
UIKeyboardBoundsUserInfoKey = "NSRect: {{0, 0}, {320, 288}}"; 
UIKeyboardCenterBeginUserInfoKey = "NSPoint: {160, 442}"; 
UIKeyboardCenterEndUserInfoKey = "NSPoint: {160, 424}"; 
UIKeyboardFrameBeginUserInfoKey = "NSRect: {{0, 316}, {320, 252}}"; 
UIKeyboardFrameEndUserInfoKey = "NSRect: {{0, 280}, {320, 288}}"; 
} 

Pierwszy z nich ma prawidłową wysokość końcową: 252. Jednak następne dwa są błędne na 216 i 288. Dzieje się tak wiarygodnie.

Oto kilka fragmentów, aby pokazać, jak ja zarządzam subskrypcji powiadomień:

-(void)viewWillAppear:(BOOL)animated { 

     [super viewWillAppear:animated]; 


     [self registerForKeyboardNotifications]; 


} 

-(void)viewWillDisappear:(BOOL)animated { 
     [super viewWillDisappear:animated]; 

     [[NSNotificationCenter defaultCenter] removeObserver:self 
               name:UIKeyboardWillHideNotification 
               object:nil]; 
     [[NSNotificationCenter defaultCenter] removeObserver:self 
               name:UIKeyboardDidShowNotification 
               object:nil]; 

} 

- (void)registerForKeyboardNotifications { 



     [[NSNotificationCenter defaultCenter] addObserver:self 
             selector:@selector(keyboardDidHide:) 
              name:UIKeyboardWillHideNotification object:nil]; 

     [[NSNotificationCenter defaultCenter] addObserver:self  
             selector:@selector(keyboardDidShow:)          
              name:UIKeyboardDidShowNotification object:nil]; 
} 
+0

Doświadczyłem tego również ustawienie niestandardowego inputView (UIPickerView) w polu tekstowym. – MrTJ

+1

Zidentyfikowałem problem i obejść go. W mojej metodzie, która jest wywoływana w odpowiedzi na UIKeyboardWillShowNotification, wywołuję [self.view layoutSubviews] w bloku animacji. Kiedy animuję layoutSubviews, dodatkowe wyskakujące powiadomienia UIKeyboardWillShow są uruchamiane z dziwnymi wartościami opublikowanymi w moim pytaniu. Jeśli zadzwonię do [self.view layoutSubviews] poza blokiem animacji, powiadomienie zostanie wyzwolone tylko raz, a wartość jest zawsze poprawna. Bez animacji działa to dobrze, ale nadal nie rozumiem, dlaczego nie działa poprawnie z animacją. –

+0

Mam do czynienia z tym samym problemem! W moim teście angielska/japońska klawiatura nie stanowi problemu, tylko chiński czasami powiadomienie jest wywoływane wiele razy i z niewłaściwymi wymiarami. – Alston

Odpowiedz

0
- (void)keyboardDidAppear:(NSNotification *)note { 
    CGSize keyboardSize = [note.userInfo[UIKeyboardFrameBeginUserInfoKey] CGRectValue].size; 
    UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, keyboardSize.height, 0.0); 
    textView.contentInset = contentInsets; 
    textView.scrollIndicatorInsets = contentInsets; 
} 

- (void)keyboardWillBeHidden:(NSNotification *)note { 
    UIEdgeInsets contentInsets = UIEdgeInsetsZero; 
    textView.contentInset = contentInsets; 
    textView.scrollIndicatorInsets = contentInsets; 
} 

Rozwiązaniem jest od oficjalnego rozwiązania Apple'a here jak 曹 powiedział.

0

W moim przypadku, Zarejestrowałem się w powiadomieniach klawiatury w ViewWillAppear i wyrejestrowałem w ViewWillDisappear. Ale spowoduje to wielokrotne uruchamianie programu obsługi UIKeyboardDidShowNotification. Wydaje się, że metoda wyrejestrowania nie działa, więc za każdym razem, gdy pojawia się widok, liczy się Observer dla UIKeyboardDidShowNotification plus 1. Następnie dotykasz UITextField, wielokrotnego obserwowania powiadamiamy, treser jest uruchamiany raz za razem.

Musisz więc zarejestrować się, aby otrzymywać powiadomienia z klawiatury w ViewDidLoad i nie wyrejestrowywać się. Podobnie jak Apple wymienione w tym page,

// Wywołanie tej metody gdzieś w widoku kodu instalacyjnego sterownika.

myślę „setup” oznacza ViewDidLoad.And w obchodzeniu się z listą kodów powiadomień klawiatury, nie ViewWillDisappear.

Oto mój przewodnik do obsługi klawiatury i działa.

func keyboardWillShow(notification: NSNotification) { 
    let userInfo = notification.userInfo! 
    let keyboardHeight = (userInfo[UIKeyboardFrameEndUserInfoKey] as! NSValue).CGRectValue().height 
    debugPrint("Before",NotifyView.frame) 
    NotifyView.frame.offsetInPlace(dx: 0, dy: -keyboardHeight) 
    debugPrint("After",NotifyView.frame) 
} 
func keyboardWillHide(notification: NSNotification) {//Do Nothing 
} 
+0

To zadziałało specjalnie dla chińskiej klawiatury? –

+0

Myślę, że to nie jest ograniczone do Chińczyków, ale nie jestem pewien. –

1

odpowiedź SWIFT: Głównym powodem jest to, że twoje zgłoszenie jest wywoływana wielokrotnie. Na przykład, w szybkim, jeśli masz NSNotificationCenter.defaultCenter(). AddObserver (xx "keyboardWillShow" xx) wewnątrz metody viewWillAppear i jeśli będziesz jechał tam iz powrotem między widokami, to spowoduje to, że będziesz mieć wielu obserwatorów tego samego " keyboardWillShow ". Zamiast tego powinieneś rozważyć przeniesienie wywołania addObserver do metody "viewDidLoad()". Alternatywnie możesz zarejestrować/wyrejestrować obserwatora, gdy widok pojawi się/zniknie.

+6

To jest dobra odpowiedź, ale nie ma w tym nic specyficznego dla Swifta. –

3

Jeśli używasz skrótu Cmd + K na symulatorze, aby pokazać/ukryć klawiaturę, może zostać wywołany wiele razy, ponieważ to nie powoduje rezygnacji z pola tekstowego jako pierwszej odpowiedzi.

Jeśli zamiast tego użyjesz przycisku klawiatury Return, zrobi to, co trzeba i zrezygnujesz z niego.

+3

Nie mogę uwierzyć, że ktoś przegłosował tę odpowiedź. Rzeczywiście z Cmd + K nazywa się to dwukrotnie. Dzięki! – Borzh

Powiązane problemy