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?

Rob Drimmie
źródło

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.

tonklon
źródło
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];

źródło
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.

phi
źródło
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.

amrox
źródło
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.

David Beck
źródło
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;
        }
}
Juan Sebastián López
źródło
-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.

Andrew Grant
źródło
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