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


94

У декількох випадках я хочу додати панель інструментів у верхню частину клавіатури iPhone (як, наприклад, у iPhone Safari, коли ви переходите до елементів форми).

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

Чи є спосіб програмно визначити положення клавіатури щодо поточного вигляду?

Відповіді:


142

Станом на iOS 3.2 є новий спосіб досягти цього ефекту:

UITextFieldsі UITextViewsмають inputAccessoryViewвластивість, яку можна встановити для будь-якого подання, яке автоматично відображається вгорі та анімується за допомогою клавіатури.

Зверніть увагу, що використовуваний вами вигляд не повинен бути в ієрархії перегляду в іншому місці, а також не слід додавати його до якогось суперпрегляду, це зроблено для вас.


Дозвольте мені спробувати . Хоча це виглядає найкращим чином.
harshalb

Ого. Яка знахідка! Дякую (я зробив це важким способом, і це брудно)
левус

1
У мене є панель UITool з UITextField всередині одного з пунктів кнопки панелі, але, хоча я встановив textFields inputAccessoryView на цю панель інструментів, першим натисканням панель інструментів піднімається, але жодної клавіатури не відображається. Під час другого натискання на панелі інструментів з’являється клавіатура.
Угур Кумру,

Але як додати панель інструментів на UIWebView? :(
Дмитро

Я зробив це, замінивши кнопки на стандартній панелі інструментів UIWebView (той самий код, що і для його видалення).
Дмитро

72

Так в основному:

У методі 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];

А потім використовуйте методи, згадані вище, для регулювання положення штанги:

-(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

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: [масив NSArrayWithObjects: @ "Попередній", @ "Далі", нуль]]; [segmentControl setSegmentedControlStyle: UISegmentedControlStyleBar]; [segmentControl addTarget: самодіяльність: @selector (nextPrevious :) forControlEvents: UIControlEventValueChanged];
Траусті Тор,

1
Додаток до коментаря @ TraustiThor: Вам потрібно обернути сегментований елемент управління в UIBarButtonItem, щоб додати його на панель інструментів.
Тім Бюте,

Відмінно - це все, що мені потрібно. Дякуємо за публікацію :)
Розтягування

Але як щодо UIWebView? Як додати на нього панель інструментів?
Дмитро

24

Якщо ви реєструєтесь для отримання сповіщень на клавіатурі, тобто UIKeyboardWillShowNotification UIKeyboardWillHideNotificationтощо, сповіщення, яке ви отримуєте, міститиме межі клавіатури в userInfodict ( UIKeyboardBoundsUserInfoKey).

Дивіться UIWindowпосилання на клас.


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.


Схоже, кращий спосіб зробити це на 3.0 SDK, дякую за публікацію!
Хуа-Ін,

Дякую за код. Це дуже допомагає. Але коли я встановлюю свій UITextView, щоб він став першим відповідачем у viewDidLoad, панель UIToolBar не рухається із зміною розміру self.view. Ви уявляєте, чому?
RyanJM

1
@RyanJM: becomeFirstResponder і resignFirstResponder мають дивну поведінку, коли вигляд поза екраном. Вам натомість слід викликати becomeFirstResponder з вашого методу 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. Я тестував лише в декількох місцях, але це виглядає як гарне місце.
Роб Дріммі,

Станом на 5.0 розмір клавіатури вже не є статичним.
Alastair Stuart
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.