Alinear mediante programación una barra de herramientas en la parte superior del teclado del iPhone

94

En varios casos, quiero agregar una barra de herramientas en la parte superior del teclado del iPhone (como en Safari de iPhone cuando navega por elementos de formulario, por ejemplo).

Actualmente estoy especificando el rectángulo de la barra de herramientas con constantes, pero debido a que otros elementos de la interfaz están cambiando (barras de herramientas y barras de navegación en la parte superior de la pantalla), cada vez que hacemos un cambio menor en la interfaz, la barra de herramientas se desalinea.

¿Hay alguna forma de determinar mediante programación la posición del teclado en relación con la vista actual?

Rob Drimmie
fuente

Respuestas:

142

A partir de iOS 3.2, hay una nueva forma de lograr este efecto:

UITextFieldsy UITextViewstener una inputAccessoryViewpropiedad, que puede establecer en cualquier vista, que se muestra automáticamente arriba y se anima con el teclado.

Tenga en cuenta que la vista que use no debe estar en la jerarquía de vistas en ningún otro lugar, ni debe agregarla a alguna supervista, esto está hecho por usted.

tonklon
fuente
Déjame intentarlo . Aunque parece la mejor forma.
harshalb
Guau. ¡Qué hallazgo! Gracias (lo hice de la manera difícil y es complicado)
levous
1
Tengo una UIToolbar con un UITextField dentro de uno de los elementos de su botón de barra, pero aunque configuré textFields inputAccessoryView en esa barra de herramientas en la primera pulsación, la barra de herramientas sube pero no aparece el teclado. En la segunda pulsación aparece el teclado con la barra de herramientas ¿tienes alguna idea al respecto?
Ugur Kumru
Pero, ¿cómo agregar una barra de herramientas en UIWebView? :(
Dmitry
Lo hice reemplazando botones en la barra de herramientas estándar UIWebView (el mismo código que para eliminarlo).
Dmitry
72

Así que básicamente:

En el método 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];

Y luego tenga los métodos mencionados anteriormente para ajustar la posición de la barra:

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

Podría hacerlo bonito animando el cambio de posición envolviéndolo en

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

fuente
Estaba hurgando en mis cosas viejas esta mañana y noté que esta es una respuesta mucho mejor y más completa. ¡Gracias!
Rob Drimmie
Esta respuesta sigue siendo bastante relevante más de un año después. Me ayudó a superar el problema al desarrollar algo relacionado con esto.
james_womack
2
Solo una advertencia para las personas que se encuentran con esta pregunta ahora: UIKeyboardBoundsUserInfoKey ahora está en desuso en iPhone OS 3.2. Hay otros similares como los UIKeyboardFrameBeginUserInfoKeyque dan la misma información.
Stephen Darlington
9
Hay incluso una nueva forma mejor de hacerlo en iOS3.2, la propiedad inputAccessoryView en UITextField y UITextView.
tonklon
6
Esta respuesta ayudó mucho, pero está un poco anticuada. Debe utilizar UIKeyboardFrameEndUserInfoKeypara obtener el fotograma final (en coordiantes de pantalla) del teclado. También puede usar UIKeyboardAnimationDurationUserInfoKeyy UIKeyboardAnimationCurveUserInfoKeypara obtener el resto de los parámetros que necesita para que coincidan exactamente con el comportamiento del teclado.
Dave Peck
60

Esto se basa en la respuesta existente de tonklon : solo estoy agregando un fragmento de código que muestra una barra de herramientas negra semitransparente en la parte superior del teclado, junto con un botón "listo" a la derecha:

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

y se -resignKeyboardve como:

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

Espero que ayude a alguien.

fi
fuente
2
Solo agrego un pequeño comentario sobre cómo poner el siguiente anterior en su lugar. UISegmentedControl * segmentoControl = [[UISegmentedControl alloc] initWithItems: [NSArray arrayWithObjects: @ "Anterior", @ "Siguiente", nulo]]; [segmentoControl setSegmentedControlStyle: UISegmentedControlStyleBar]; [segmentoControl addTarget: autoacción: @selector (nextPrevious :) forControlEvents: UIControlEventValueChanged];
Trausti Thor
1
Una adición al comentario de @ TraustiThor: debe envolver el control segmentado en un UIBarButtonItem para agregarlo a la barra de herramientas.
Tim Büthe
Excelente, este es todo el código que necesitaba. Gracias por publicar :)
Estire
Pero, ¿qué pasa con UIWebView? ¿Cómo agregarle una barra de herramientas?
Dmitry
24

Si se registra para UIKeyboardWillShowNotification UIKeyboardWillHideNotificationrecibir notificaciones del teclado, es decir , etc., la notificación que reciba contendrá los límites del teclado en el userInfodict ( UIKeyboardBoundsUserInfoKey).

Consulte la UIWindowreferencia de la clase.

amrox
fuente
16

En 3.0 y superior, puede obtener la duración y la curva de la animación del userInfodiccionario de notificaciones.

por ejemplo, para animar el tamaño de la vista para hacer espacio para el teclado, regístrese para UIKeyboardWillShowNotificationy haga algo como lo siguiente:

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

Haz una animación similar para UIKeyboardWillHideNotification.

David Beck
fuente
Parece una mejor manera de hacerlo en el SDK 3.0, ¡gracias por publicar!
Hua-Ying
Gracias por el codigo. Esto ayuda mucho. Pero cuando configuro mi UITextView para que sea el primero en responder en viewDidLoad, UIToolBar no se mueve con el cambio de tamaño de self.view. ¿Tienes idea de por qué?
RyanJM
1
@RyanJM: BecomeFirstResponder y resignFirstResponder tienen un comportamiento extraño cuando la vista está fuera de la pantalla. En su lugar, debería llamar a BecomeFirstResponder desde su método viewWillAppear.
David Beck
0

Cree este método y llámelo en 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
fuente
-3

No hay forma (AFAIK) de obtener las dimensiones de la vista del teclado. Sin embargo, es constante, al menos en todas las versiones de iPhone hasta ahora.

Si calcula la posición de la barra de herramientas como un desplazamiento desde la PARTE INFERIOR de su vista y tiene en cuenta el tamaño de su vista, entonces no debería tener que preocuparse si una barra de navegación está presente o no.

P.ej

#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

En lugar de definir, puede crear fácilmente una keyboardHeightfunción que devuelva el tamaño en función de si se muestra el teclado y mover esta posición de la barra de herramientas a una función separada que reorganice su diseño.

También puede depender de dónde haga este posicionamiento, ya que es posible que el tamaño de su vista cambie entre cargarse y mostrarse según la configuración de la barra de navegación. Creo que el mejor lugar para hacerlo sería en viewWillAppear.

Andrew Grant
fuente
¡Esto funcionó muy bien, gracias! Hasta ahora he estado haciendo este cálculo en el selector activado por UIKeyboardDidShowNotification. Solo he probado en un par de lugares, pero parece un buen lugar.
Rob Drimmie
A partir de 5.0, el tamaño del teclado ya no es estático.
Alastair Stuart