Программно выровняйте панель инструментов поверх клавиатуры iPhone

94

В некоторых случаях я хочу добавить панель инструментов в верхнюю часть клавиатуры iPhone (как, например, в iPhone Safari, когда вы перемещаетесь по элементам формы).

В настоящее время я указываю прямоугольник панели инструментов с константами, но поскольку другие элементы интерфейса находятся в постоянном движении - панели инструментов и панели навигации вверху экрана - каждый раз, когда мы вносим незначительные изменения в интерфейс, панель инструментов выходит из выравнивания.

Есть ли способ программно определить положение клавиатуры по отношению к текущему виду?

Роб Дримми
источник

Ответы:

142

Начиная с iOS 3.2, есть новый способ добиться этого эффекта:

UITextFieldsи UITextViewsиметь inputAccessoryViewсвойство, которое можно установить для любого вида, которое автоматически отображается выше и анимируется с помощью клавиатуры.

Обратите внимание, что используемое вами представление не должно находиться в иерархии представлений где-либо еще, и вам не следует добавлять его в какой-либо суперпредставление, это делается за вас.

Tonklon
источник
Дай мне попробовать . Хотя выглядит лучше всего.
harshalb
Вот это да. Какая находка! Спасибо (я сделал это нелегко, и это грязно)
levous
1
У меня есть UIToolbar с UITextField внутри одного из его элементов кнопок на панели, но хотя я установил textFields inputAccessoryView на эту панель инструментов при первом нажатии, панель инструментов поднимается, но клавиатура не появляется. При втором нажатии появляется клавиатура с панелью инструментов, есть представление о ней?
Угур Кумру
Но как добавить панель инструментов в UIWebView? :(
Дмитрий
Я сделал это, заменив кнопки на стандартной панели инструментов UIWebView (тот же код, что и для его удаления).
Дмитрий
72

Итак, в основном:

В методе инициализации:

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

А затем используйте методы, упомянутые выше, чтобы отрегулировать положение полосы:

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

Можно было бы сделать это красивым, анимировав изменение позиции, обернув его

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

источник
Сегодня утром копался в своих старых вещах и заметил, что это гораздо лучший и наиболее полный ответ. Спасибо!
Роб Дримми,
Этот ответ остается актуальным и спустя год. Это помогло мне справиться с трудностями при разработке чего-то, связанного с этим.
james_womack 05
2
Просто предупреждение для людей, которые сейчас сталкиваются с этим вопросом: UIKeyboardBoundsUserInfoKey теперь устарел в iPhone OS 3.2. Есть и другие, похожие, например, UIKeyboardFrameBeginUserInfoKeyкоторые дают ту же информацию.
Стивен Дарлингтон
9
В iOS3.2 есть еще лучший новый способ сделать это - свойство inputAccessoryView в UITextField и UITextView.
tonklon
6
Этот ответ помог тонне, но немного устарел. Вы должны использовать, UIKeyboardFrameEndUserInfoKeyчтобы получить последний кадр (в экранных координатах) клавиатуры. Вы также можете использовать UIKeyboardAnimationDurationUserInfoKeyи, UIKeyboardAnimationCurveUserInfoKeyчтобы получить остальные параметры, которые вам нужны, чтобы точно соответствовать поведению клавиатуры.
Дэйв Пек,
60

Это основано на существующем ответе от tonklon - я просто добавляю фрагмент кода, который показывает полупрозрачную черную панель инструментов в верхней части клавиатуры вместе с кнопкой «Готово» справа:

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];

и -resignKeyboardвыглядит так:

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

Надеюсь, это кому-то поможет.

фи
источник
2
Просто добавляю небольшой комментарий по поводу получения следующего предыдущего на месте. UISegmentedControl * segmentControl = [[UISegmentedControl alloc] initWithItems: [NSArray arrayWithObjects: @ "Предыдущий", @ "Следующий", ноль]]; [segmentControl setSegmentedControlStyle: UISegmentedControlStyleBar]; [segmentControl addTarget: самостоятельное действие: @selector (nextPrevious :) forControlEvents: UIControlEventValueChanged];
Trausti Thor
1
Дополнение к комментарию @ TraustiThor: вам нужно обернуть сегментированный элемент управления в UIBarButtonItem, чтобы добавить его на панель инструментов.
Тим Бют
Отлично - это весь код, который мне нужен. Спасибо за публикацию :)
Stretch
Но как насчет UIWebView? Как добавить к нему панель инструментов?
Дмитрий
24

Если вы зарегистрируетесь для получения уведомлений с клавиатуры, т. Е. И т. UIKeyboardWillShowNotification UIKeyboardWillHideNotificationД., Полученное вами уведомление будет содержать границы клавиатуры в userInfodict (UIKeyboardBoundsUserInfoKey ).

См. UIWindowСсылку на класс.

Amrox
источник
16

В версии 3.0 и выше вы можете получить продолжительность анимации и кривую из userInfo словаря уведомлений.

например, чтобы анимировать размер представления, чтобы освободить место для клавиатуры, зарегистрируйтесь UIKeyboardWillShowNotificationи сделайте что-то вроде следующего:

- (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];
}

Сделайте аналогичную анимацию для UIKeyboardWillHideNotification.

Дэвид Бек
источник
Похоже, это лучший способ сделать это в SDK 3.0. Спасибо за публикацию!
Hua-Ying
Спасибо за код. Это очень помогает. Но когда я настраиваю свой UITextView на роль первого респондента в viewDidLoad, UIToolBar не перемещается при изменении размера self.view. Вы знаете почему?
RyanJM 01
1
@RyanJM: статьFirstResponder и resignFirstResponder ведут себя странно, когда представление находится вне экрана. Вместо этого вы должны вызывать статьFirstResponder из вашего метода viewWillAppear.
Дэвид Бек,
0

Создайте этот метод и вызовите его в 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

Нет способа (AFAIK) получить размеры представления клавиатуры. Однако он постоянен, по крайней мере, до сих пор в каждой версии iPhone.

Если вы рассчитываете положение панели инструментов как смещение от НИЖНЕЙ части вашего представления и принимаете во внимание размер вашего представления, то вам не нужно беспокоиться о том, присутствует ли панель навигации или нет.

Например

#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

Вместо определения вы можете легко создать keyboardHeight функцию, которая возвращает размер в зависимости от того, отображается ли клавиатура, и переместить это позиционирование панели инструментов в отдельную функцию, которая реорганизует ваш макет.

Также это может зависеть от того, где вы делаете это позиционирование, так как возможно, размер вашего представления может меняться между загрузкой и отображением в зависимости от настроек вашей панели навигации. Я считаю, что лучшим местом для этого было бы viewWillAppear.

Эндрю Грант
источник
Это отлично сработало, спасибо! До сих пор я делал этот расчет в селекторе, запускаемом UIKeyboardDidShowNotification. Я тестировал всего пару мест, но похоже, что это хорошее место.
Роб Дримми, 01
Начиная с версии 5.0 размер клавиатуры больше не статичен.
Аластер Стюарт,