InputAccessoryView acoplado en la parte inferior

Estoy tratando de lograr similares posicionamiento de comportamiento como la parte inferior de entrada de texto de la barra en la Apple app Mensajes.

He probado muchos métodos, buscado de alta y baja y hay muchas preguntas similares pero ninguno ha sido satisfactoria.

Especificar:

  1. Hay un UIToolbar en la parte inferior de la vista de
  2. La barra de herramientas es seguir el teclado como el teclado que aparece y desaparece
  3. La barra de herramientas debe permanecer en la parte superior del teclado cuando el teclado está visible
  4. Cuando el teclado está oculto, la barra de herramientas permanece («acoplado») en la parte inferior de la vista de

La propuesta de soluciones:

Animación manual de la barra de herramientas en respuesta a teclado apariencia notificaciones

Esta solución no cumple un caso especial de la segunda requisito (la barra de herramientas es seguir el teclado como el teclado que aparece y desaparece):

  • En iOS 7, UIScrollViewKeyboardDismissMode fue introducido. Permite a un interactiva gesto para despedir el teclado. Como el usuario se desplaza pasado el borde superior del teclado, el teclado marco gradualmente de la siguiente manera. Esta solución no hace nada para acomodar este comportamiento y sólo sale de la barra de herramientas de la cadena en la animación de la posición.

Además, esta solución también incumple un caso especial de la tercer requisito (la barra de herramientas debe permanecer en la parte superior del teclado cuando el teclado está visible):

  • De rotación. Esta solución llamadas adicionales, molesto extraños código (como veremos en la siguiente propuesta de solución) para girar la barra de herramientas en respuesta a la rotación del dispositivo.

Otro problema con esta solución:

  • De la altura del teclado. Con esta solución, la barra de herramientas no se supone que para ser parte de la altura del teclado, de modo adicional, el código debe ser escrito como apoyo adecuado a establecer de contenido.

Siguiente propuesta de solución:

Uso UIResponder‘s inputAccessoryView

Esta solución parece ser la forma en que Apple pretende apoyar este tipo de comportamiento, como los que resuelve todos los problemas de forma manual la animación de la barra de herramientas. Pero esta solución completamente pierde el cuarto requisito (cuando el teclado está oculto, la barra de herramientas permanece («acoplado») en la parte inferior de la vista de).


Parece que la solución es el uso de UIResponder‘s inputAccessoryView, pero de alguna manera hacer que el inputAccessoryView no se mueven por debajo de la vista. Estoy buscando para la limpieza de código para lograr esto. No son complicadas, casi nobles, los intentos en otros lugares, pero como se mencionó, a que no cumplen con los requisitos.

En mi caso particular, estoy buscando a utilizar UINavigationController‘s de la barra de herramientas, que conlleva a problemas adicionales como esta no es la intención de comportamiento para UINavigationController. No importa, estoy dispuesto a introducir algunos hacky correcciones para lograr eso.

5 Kommentare

  1. 57

    Yo era sólo muestra «la» solución por Jason Capataz (@threeve). En su punto de vista controlador (sí, la vista controlador) agregar inputAccessoryView: y volver la vista que desea acoplar en la parte inferior y mover con el teclado. Simplemente funciona. La vista no es realmente necesario en la vista de jerarquía será introducido por el punto de vista controlador automáticamente.

    edit: también implementar canBecomeFirstResponder y la de regreso SI (como señaló Max Seelemann). reloadInputViews puede ser útil también.

    • Se debe añadir que el controlador de vista de también que se necesita para volver a YES de -canBecomeFirstResponder y la necesidad de hacer de sí mismo la primera respuesta. Pero después de eso, sólo la magia. +100 😉
    • Suena interesante, pero no acabo de entender. Atención a elaborar?
    • Espera… creo que entiendo (voy a probar en el código): El UIViewController debe devolver un inputAccessoryView, en lugar de, por ejemplo, la UITextView o UITextField.
    • Sí, fantástico, esto funciona. También hace sentido semántico. D’oh! Gracias por compartir!
    • Esto también funciona para la UIToolbar administrado por UINavigationController.
    • ¿Por qué son características como esta tan mal documentado ? Hay un repositorio o algo donde indocumentados encuentra como este son recogidos ? (UINavigationBars también pueden ser aliviadas de lado por la llamada ‘setHidden’ en los lugares correctos en viewWillAppear, etc.) <- cosas como eso ! )
    • Sería bueno ver un ejemplo de código completo de esta «magia» de la solución.
    • La solución que se propone generar una retener el ciclo entre la UIViewController y inputView. Tal vez es un bug de iOS SDK, pero hace que el UIViewController que nunca se publicó, y la generación de fugas.
    • Lamentablemente yo no puedo conseguir que esta técnica se trabaja en conjunto con un UITabBar. El inputAccessoryView es dibujado por encima de las fichas.
    • Me debe faltar algo. Ni inputAccessoryView ni canBecomeFirstResponder se llama en mi punto de vista controlador cuando se muestra por primera vez. Se supone que tengo que agregar la entrada de la vista a la vista de forma manual, así como la devolución de inputAccessoryView?
    • Yo tengo trabajo llamando [self becomeFirstResponder] en viewDidLoad de todas las cosas.
    • Estoy recibiendo *** Terminating app due to uncaught exception 'UIViewControllerHierarchyInconsistency', reason: 'child view controller:<UICompatibilityInputViewController: 0x159ec54b0> should have parent view controller:<ULPostViewController: 0x157dec330> but requested parent is:<UIInputWindowController: 0x1580f0800>' de error con este método. (iOS 8.3)
    • Creo que esto podría ocurrir si lo he intentado agregar el «accesorio» de la vista a la vista principal controlador de la que estamos trabajando. No es necesario agregar manualmente cuando se utiliza como un inputAccessoryView.
    • No puedo creer que esto funciona. Esto es increíble! Gran hallazgo!

  2. 31

    Jonathan Badeen citados solución trabajó para mí. Aquí está el código de Arik muestra cómo llevarlo a cabo (esto debería ir en su correspondiente controlador de vista):

        - (BOOL)canBecomeFirstResponder{
    
            return YES;
    
        }
    
        - (UIView *)inputAccessoryView{
    
            return self.inputAccessoryToolbar;  
         //where inputAccessoryToolbar is your keyboard accessory view
    
        }
    • wow, funciona! eres el mejor
    • el problema existe cuando se trata de ir a una diferente de la controladora, por empujar o presente, el inputAccessoryView todavía muestra
  3. 9

    Para aquellos que buscan Swift versión:

    Conectar de la barra de herramientas (en mi caso ‘myToolBar‘) en el controlador de vista. A continuación, reemplazar canBecomeFirstResponder método y reemplazar la función de captador inputAccessoryView variable. También no se olvide de agregar el self.myToolBar.removeFromSuperview() o más xcode se quejan.

    class ViewController: UIViewController {
    
        @IBOutlet var myToolBar: UIToolbar!
    
        override func canBecomeFirstResponder() -> Bool {
            return true
        }
    
    
        override var inputAccessoryView:UIView{
            get{
                return self.myToolBar
            }
        }
    
        override func viewDidLoad() {
            super.viewDidLoad()
            self.myToolBar.removeFromSuperview()
        }
    }
    • OMG, se ha simplificado en absoluto mínimo!
    • Al final yo no uso este código me fui con github.com/slackhq/SlackTextViewController mucho más fácil sin complicaciones lol
    • He probado con el STVC, pero no me gusta añadir tanto la hinchazón de los códigos de la misma para una TextView, y el STVC no es totalmente adaptarse al guión gráfico, necesita usar XIB. Estoy muy decepcionado de que no es propiamente un accesorios de vista de la barra, no se adaptan a interactivo descartar como en Whatsapp / iMessage. Yo todavía para encontrar la mejor solución. Pero vale la pena visitar github.com/muukii/NextGrowingTextView si todos la necesidad de u es 100% storyboard compatible para su simple entrada TextView. Pero aún así, este no adaptarse a accessoriesbar vista..
    • Gracias por compartir
  4. 6

    Hay un excelente, fácil de implementar, solución de código abierto para esto de la buena gente de la Holgura: SlackTextViewController.

    Aquí cómo implementar una vista con una barra de herramientas acoplada en cuatro pasos:

    1. Instalar el sensor en el proyecto. (http://cocoapods.org/?q=SlackTextViewController)
    2. Si usted está escribiendo una aplicación en Swift, crear una cabecera de puente entre el código Swift y sus Obj-C clases. He aquí una bonita rápido tutorial sobre la que. (El puente de encabezado no va a ser necesario una vez que las clases se traducen en Swift, alguien quiere colaborar en que?)
    3. Crear un MessageViewController que hereda de SLKTextViewController, no hay necesidad de escribir ningún código más que esto:

      import Foundation
      import UIKit
      
      class MessageViewController: SLKTextViewController {
      
          required init(coder aDecoder: NSCoder!) {
              super.init(coder: aDecoder)
          }
      }
    4. En el Guión gráfico, crear un Controlador de Vista que hereda de MessageViewController.
    5. Probar la aplicación en un dispositivo o emulador, podrás ver una hermosa acoplado textbar que también (como un bono) se expande a medida que el usuario escribe adicionales de líneas de texto.

    Accesorios para el equipo de Holgura para la extracción de tan útil el pod.

    • Gracias por la punta en la SlackTextViewController!
    • Agradable y rápido – cool de la biblioteca
  5. 2

    Así que sé que esto es un viejo post y no estoy seguro de si se ha resuelto o no, pero he encontrado una manera de conseguir este trabajo. Creo que hay un error en el inputAccessoryView, pero he creado un hacky solución a comportarse de la manera en que los mensajes de la aplicación. Creo que me proporciona todo el código necesario para implementar el trabajo alrededor. Voy a intentar y conseguir una más adecuada blog creado en algún momento en el futuro cercano, con una descripción en profundidad con mis conclusiones. Cualquier duda, dejenme saber.

    @property(nonatomic,assign)BOOL isFirstKeyboard; //workaround for keyboard bug
    
    @property(nonatomic,assign)BOOL isViewAppear;
    
    @property(nonatomic,strong)ChatBarView *chatView; //custom chat bar view
    
    @property(nonatomic,strong)UIView *footerPadView; //just to add some nice padding
    ////////////////////////////////////////////////////////////////////////////////////////////////////
    //in the view did load
    - (void)viewDidLoad
    {
        //more app specific code...
        self.tableView.keyboardDismissMode = UIScrollViewKeyboardDismissModeInteractive;
        self.chatView.textView.inputAccessoryView = self.chatView;
    }
    
    ////////////////////////////////////////////////////////////////////////////////////////////////////
    -(void)done
    {
        self.isFirstKeyboard = YES;
        [self.chatView.textView becomeFirstResponder];
    }
    ////////////////////////////////////////////////////////////////////////////////////////////////////
    - (void) moveTextViewForKeyboard:(NSNotification*)aNotification up:(BOOL)up
    {
        if(!self.isViewAppear)
            return;
        //NSLog(@"keyboard is: %@", up ? @"UP" : @"Down");
        if(!up && !self.isFirstKeyboard)
            [self performSelector:@selector(done) withObject:nil afterDelay:0.01];
        else if(!up & self.isFirstKeyboard)
        {
            self.isFirstKeyboard = NO;
            [self.view addSubview:self.chatView];
            CGRect frame = self.chatView.frame;
            frame.origin.y = self.view.frame.size.height - self.chatView.frame.size.height;
            self.chatView.frame = frame;
        }
        else
        {
            NSDictionary* userInfo = [aNotification userInfo];
            NSTimeInterval animationDuration;
            UIViewAnimationCurve animationCurve;
            CGRect keyboardEndFrame;
    
            [[userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] getValue:&animationCurve];
            [[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] getValue:&animationDuration];
            [[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] getValue:&keyboardEndFrame];
    
            //Animate up or down
            [UIView beginAnimations:nil context:nil];
            if(up)
                [UIView setAnimationDuration:0.2];
            else
                [UIView setAnimationDuration:0.3];
            [UIView setAnimationCurve:animationCurve];
    
            CGRect frame = self.footerPadView.frame;
            CGRect keyboardFrame = [self.view convertRect:keyboardEndFrame toView:nil];
            if (up)
                frame.size.height = keyboardFrame.size.height - self.chatView.frame.size.height;
            else
                frame.size.height = 0;
            self.footerPadView.frame = frame;
            self.tableView.tableFooterView = self.footerPadView;
            [UIView commitAnimations];
        }
    }
    ////////////////////////////////////////////////////////////////////////////////////////////////////
    - (void)keyboardWillShow:(NSNotification *)aNotification {
        [self moveTextViewForKeyboard:aNotification up:YES];
    }
    ////////////////////////////////////////////////////////////////////////////////////////////////////
    - (void)keyboardWillHide:(NSNotification *)aNotification
    {
        [self moveTextViewForKeyboard:aNotification up:NO];
    }
    ////////////////////////////////////////////////////////////////////////////////////////////////////

Kommentieren Sie den Artikel

Bitte geben Sie Ihren Kommentar ein!
Bitte geben Sie hier Ihren Namen ein

Pruebas en línea