Programowo dopasuj pasek narzędzi do górnej części klawiatury iPhone'a


94

W kilku przypadkach chcę dodać pasek narzędzi u góry klawiatury iPhone'a (jak na przykład w iPhone Safari podczas nawigowania po elementach formularza).

Obecnie określam prostokąt paska narzędzi za pomocą stałych, ale ponieważ inne elementy interfejsu są zmienne - paski narzędzi i paski nawigacyjne u góry ekranu - za każdym razem, gdy robimy niewielką zmianę interfejsu, pasek narzędzi traci wyrównanie.

Czy istnieje sposób, aby programowo określić położenie klawiatury w stosunku do bieżącego widoku?

Odpowiedzi:


142

Od iOS 3.2 jest nowy sposób na osiągnięcie tego efektu:

UITextFieldsi UITextViewsmają inputAccessoryViewwłaściwość, którą można ustawić dla dowolnego widoku, która jest automatycznie wyświetlana powyżej i animowana za pomocą klawiatury.

Zauważ, że widok, którego używasz, nie powinien znajdować się w hierarchii widoków w innym miejscu, ani nie powinieneś dodawać go do jakiegoś superviewu, zrobimy to za Ciebie.


pozwól mi spróbować . Choć wygląda to najlepiej.
harshalb

Łał. Co za znalezisko! Dzięki (zrobiłem to na
własnej skórze

1
Mam pasek narzędzi UIT z UITextField wewnątrz jednego z elementów przycisku paska, ale mimo że ustawiłem inputAccessoryView textFields na ten pasek narzędzi po pierwszym naciśnięciu, pasek narzędzi podnosi się, ale nie pojawia się klawiatura. Po drugim naciśnięciu pojawi się klawiatura z paskiem narzędzi. Masz o tym jakieś pojęcie?
Ugur Kumru,

Ale jak dodać pasek narzędzi do UIWebView? :(
Dmitry

Zrobiłem to, zastępując przyciski na standardowym pasku narzędzi UIWebView (ten sam kod, co do jego usuwania).
Dmitry,

72

Więc w zasadzie:

W metodzie init:

NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
[nc addObserver:self selector:@selector(keyboardWillShow:) name: UIKeyboardWillShowNotification object:nil];
[nc addObserver:self selector:@selector(keyboardWillHide:) name: UIKeyboardWillHideNotification object:nil];

Następnie skorzystaj z metod opisanych powyżej, aby dostosować położenie paska:

-(void) keyboardWillShow:(NSNotification *) note
{
    CGRect r  = bar.frame, t;
    [[note.userInfo valueForKey:UIKeyboardBoundsUserInfoKey] getValue: &t];
    r.origin.y -=  t.size.height;
    bar.frame = r;
}

Może to zrobić ładnie, animując zmianę pozycji, zawijając ją

    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration:0.3];
//...
    [UIView commitAnimations];

Grzebałem dziś rano wokół moich starych rzeczy i zauważyłem, że jest to znacznie lepsza i najbardziej wyczerpująca odpowiedź. Dzięki!
Rob Drimmie,

Ta odpowiedź jest nadal dość aktualna rok później. Pomogło mi to przezwyciężyć garb podczas opracowywania czegoś z tym związanego.
james_womack

2
Tylko ostrzeżenie dla ludzi, którzy teraz natkną się na to pytanie: UIKeyboardBoundsUserInfoKey jest teraz przestarzały w iPhone OS 3.2. Istnieją inne, podobne, takie jak UIKeyboardFrameBeginUserInfoKeypodające te same informacje.
Stephen Darlington

9
Jest jeszcze lepszy nowy sposób na zrobienie tego w iOS3.2 we właściwości inputAccessoryView w UITextField i UITextView.
tonklon

6
Ta odpowiedź pomogła tonę, ale jest nieco przestarzała. Powinieneś użyć, UIKeyboardFrameEndUserInfoKeyaby uzyskać ostatnią klatkę (w koordynatach ekranu) klawiatury. Możesz także użyć UIKeyboardAnimationDurationUserInfoKeyi, UIKeyboardAnimationCurveUserInfoKeyaby uzyskać pozostałe parametry, których potrzebujesz, aby dokładnie dopasować zachowanie klawiatury.
Dave Peck

60

Jest to oparte na istniejącej odpowiedzi od Tonklon - po prostu dodam fragment kodu, który pokazuje półprzezroczysty czarny pasek narzędzi na górze klawiatury, wraz z przyciskiem „gotowe” po prawej stronie:

UIToolbar *toolbar = [[[UIToolbar alloc] init] autorelease];
[toolbar setBarStyle:UIBarStyleBlackTranslucent];
[toolbar sizeToFit];

UIBarButtonItem *flexButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:self action:nil];
UIBarButtonItem *doneButton =[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(resignKeyboard)];

NSArray *itemsArray = [NSArray arrayWithObjects:flexButton, doneButton, nil];

[flexButton release];
[doneButton release];
[toolbar setItems:itemsArray];

[aTextField setInputAccessoryView:toolbar];

a -resignKeyboardwygląda następująco:

-(void)resignKeyboard {
  [aTextField resignFirstResponder];
}

Mam nadzieję, że to komuś pomoże.


2
Dodam tylko mały komentarz na temat umieszczania następnego poprzedniego na miejscu. UISegmentedControl * segmentControl = [[UISegmentedControl assign] initWithItems: [NSArray arrayWithObjects: @ "Previous", @ "Next", nil]]; [segmentControl setSegmentedControlStyle: UISegmentedControlStyleBar]; [segmentControl addTarget: self action: @selector (nextPrevious :) forControlEvents: UIControlEventValueChanged];
Trausti Thor

1
Dodatek do komentarza @ TraustiThor: Musisz zawinąć segmentowaną kontrolkę w UIBarButtonItem, aby dodać ją do paska narzędzi.
Tim Büthe

Doskonale - to cały kod, którego potrzebowałem. Dzięki za wysłanie :)
Stretch

Ale co z UIWebView? Jak dodać do niego pasek narzędzi?
Dmitry

24

Jeśli zarejestrujesz się w celu UIKeyboardWillShowNotification UIKeyboardWillHideNotificationotrzymywania powiadomień z klawiatury, tj. Itp., Otrzymane powiadomienie będzie zawierało granice klawiatury w userInfodict ( UIKeyboardBoundsUserInfoKey).

Zobacz informacje o UIWindowklasie.


16

W wersji 3.0 i nowszych możesz uzyskać czas trwania animacji i krzywą ze userInfosłownika powiadomień.

na przykład, aby animować rozmiar widoku, aby zrobić miejsce na klawiaturę, zarejestruj się UIKeyboardWillShowNotificationi wykonaj coś podobnego do:

- (void)keyboardWillShow:(NSNotification *)notification
{
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationCurve:[[[notification userInfo] objectForKey:UIKeyboardAnimationCurveUserInfoKey] intValue]];
    [UIView setAnimationDuration:[[[notification userInfo] objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue]];

    CGRect frame = self.view.frame;
    frame.size.height -= [[[notification userInfo] objectForKey:UIKeyboardBoundsUserInfoKey] CGRectValue].size.height;
    self.view.frame = frame;

    [UIView commitAnimations];
}

Zrób podobną animację dla UIKeyboardWillHideNotification.


Wygląda na to, że jest to lepszy sposób na zrobienie tego w SDK 3.0, dzięki za wysłanie!
Hua-Ying

Dzięki za kod. To bardzo pomaga. Ale kiedy ustawię mój UITextView, aby stał się pierwszym odpowiadającym w viewDidLoad, UIToolBar nie przesuwa się wraz ze zmianą rozmiaru self.view. Czy masz pojęcie, dlaczego?
RyanJM

1
@RyanJM: getFirstResponder i resignFirstResponder mają dziwne zachowanie, gdy widok jest poza ekranem. Zamiast tego powinieneś wywołać funkcję getFirstResponder z metody viewWillAppear.
David Beck,

0

Utwórz tę metodę i wywołaj ją w ViewWillLoad:

        - (void) keyboardToolbarSetup
{
    if(self.keyboardToolbar==nil)
        {
        self.keyboardToolbar = [[UIToolbar alloc] initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, 44)];

        UIBarButtonItem *cancelButton = [[UIBarButtonItem alloc] initWithTitle:@"Cancel" style:UIBarButtonItemStylePlain target:self action:@selector(anyAction)];

        UIBarButtonItem *extraSpace = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];

        UIBarButtonItem *doneButton = [[UIBarButtonItem alloc] initWithTitle:@"Done" style:UIBarButtonItemStyleDone target:self action:@selector(anyOtherAction)];


        NSArray *toolbarButtons = [[NSArray alloc]initWithObjects:cancelButton,extraSpace,doneButton, nil];

        [self.keyboardToolbar setItems:toolbarButtons];

        self.myTextView.inputAccessoryView=self.keyboardToolbar;
        }
}

-3

Nie ma sposobu (AFAIK), aby uzyskać wymiary widoku klawiatury. Jest jednak stały, przynajmniej w każdej dotychczasowej wersji iPhone'a.

Jeśli obliczysz pozycję paska narzędzi jako odsunięcie od DOLNEGO widoku i weźmiesz pod uwagę rozmiar widoku, nie powinieneś się martwić, czy pasek nawigacyjny jest obecny, czy nie.

Na przykład

#define KEYBOARD_HEIGHT 240 // example - can't remember the exact size
#define TOOLBAR_HEIGHT 30

toolBarRect.origin.y = viewRect.size.height - KEYBOARD_HEIGHT - TOOLBAR_HEIGHT;

// move toolbar either directly or with an animation

Zamiast definicji, możesz łatwo utworzyć plik keyboardHeight funkcję, która zwraca rozmiar na podstawie tego, czy klawiatura jest wyświetlana, i przenieść to pozycjonowanie paska narzędzi do osobnej funkcji, która reorganizuje układ.

Może to również zależeć od tego, gdzie robisz to pozycjonowanie, ponieważ jest możliwe, że rozmiar widoku może się zmieniać między wczytywaniem a wyświetlaniem w zależności od konfiguracji paska nawigacyjnego. Uważam, że najlepszym miejscem do zrobienia tego będzie widok WillAppear.


To działało świetnie, dzięki! Do tej pory robiłem to obliczenie w selektorze wyzwalanym przez UIKeyboardDidShowNotification. Testowałem tylko w kilku miejscach, ale wygląda na to, że jest to dobre miejsce.
Rob Drimmie

Od wersji 5.0 rozmiar klawiatury nie jest już statyczny.
Alastair Stuart
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.