web-dev-qa-db-fra.com

Clavier en retrait de style iMessage dans une application iOS

Je me demandais s'il était possible de reproduire le comportement du clavier iOS5 d'Apple dans l'application Messages, sans utiliser d'appels d'API privés. Lorsque vous faites défiler le clavier vers le bas dans l'application Messages, le clavier s'effondre, laissant plus de place pour voir les messages - essayez-le pour voir.

Je ne pouvais rien trouver qui pointe vers cela sans avoir à commencer à sauter à travers quelques cerceaux sérieux pour obtenir une instance de la vue du clavier. Et je suis sûr que Apple ne serait pas satisfait de cela.

En plus de la réponse donnée ci-dessous, vous pouvez voir un projet xcode entièrement cuit de mon implémentation ici: https://github.com/orta/iMessage-Style-Receding-Keyboard

67
orta

Il s'agit d'une solution incomplète, mais elle devrait vous donner un bon point de départ.

Ajoutez les ivars suivants à votre UIViewController:

CGRect        keyboardSuperFrame; // frame of keyboard when initially displayed
UIView      * keyboardSuperView;  // reference to keyboard view

Ajoutez un InputAccessoryView à votre contrôleur de texte. J'ai créé une petite vue à insérer comme accessoire

accView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 0, 0)];
accView.backgroundColor = [UIColor clearColor];
textField.inputAccessoryView = accView;

J'ai ajouté le code ci-dessus à -(void)loadView

Inscrivez-vous pour recevoir UIKeyboardDidShowNotification et UIKeyboardDidHideNotification lorsque la vue est chargée:

- (void)viewDidLoad
{
    [super viewDidLoad];
    [[NSNotificationCenter defaultCenter] addObserver:self
        selector:@selector(keyboardWillShow:)
        name:UIKeyboardWillShowNotification
        object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self
        selector:@selector(keyboardDidShow:)
        name:UIKeyboardDidShowNotification
        object:nil];
    return;
}

Ajoutez des méthodes à spécifiées comme sélecteurs pour les notifications:

// method is called whenever the keyboard is about to be displayed
- (void)keyboardWillShow:(NSNotification *)notification
{
    // makes keyboard view visible incase it was hidden
    keyboardSuperView.hidden = NO;
    return;
}
// method is called whenever the keyboard is displayed
- (void) keyboardDidShow:(NSNotification *)note
{
    // save reference to keyboard so we can easily determine
    // if it is currently displayed
    keyboardSuperView  = textField.inputAccessoryView.superview;

    // save current frame of keyboard so we can reference the original position later
    keyboardSuperFrame = textField.inputAccessoryView.superview.frame;
    return;
}

Ajoutez des méthodes pour suivre le toucher et mettre à jour la vue du clavier:

// stops tracking touches to divider
- (void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
    CGRect newFrame;
    CGRect bounds = [[UIScreen mainScreen] bounds];

    newFrame = keyboardSuperFrame;
    newFrame.Origin.y = bounds.size.height;  

    if ((keyboardSuperView.superview))
        if (keyboardSuperFrame.Origin.y != keyboardSuperView.frame.Origin.y)
            [UIView animateWithDuration:0.2
                    animations:^{keyboardSuperView.frame = newFrame;}
                    completion:^(BOOL finished){
                                keyboardSuperView.hidden = YES;
                                keyboardSuperView.frame = keyboardSuperFrame;
                                [textField resignFirstResponder]; }];
    return;
}


// updates divider view position based upon movement of touches
- (void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
   UITouch  * touch;
   CGPoint    point;
   CGFloat    updateY;

   if ((touch = [touches anyObject]))
   {
      point   = [touch locationInView:self.view];
      if ((keyboardSuperView.superview))
      {
         updateY = keyboardSuperView.frame.Origin.y;
         if (point.y < keyboardSuperFrame.Origin.y)
            return;
         if ((point.y > updateY) || (point.y < updateY))
            updateY = point.y;
         if (keyboardSuperView.frame.Origin.y != updateY)
            keyboardSuperView.frame = CGRectMake(keyboardSuperFrame.Origin.x,
                                                 point.y,
                                                 keyboardSuperFrame.size.width,
                                                 keyboardSuperFrame.size.height);
      };
   };
   return;
}

Avertissements:

  • Lors de la démission comme première réponse, le clavier revient à sa position d'origine avant de glisser hors de l'écran. Pour rendre la fermeture du clavier plus fluide, vous devez d'abord créer une animation pour déplacer le clavier hors de l'écran, puis masquer la vue. Je laisserai cette partie comme exercice aux lecteurs.
  • Je n'ai testé cela que sur le simulateur iOS 5 et avec un iPhone avec iOS 5. Je n'ai pas testé cela avec des versions antérieures d'iOS.

Le projet SlidingKeyboard que j'ai créé pour tester ce concept est disponible sur GitHub dans le répertoire d'exemples de BindleKit:

https://github.com/bindle/BindleKit

Modifier: exemple de mise à jour pour répondre à la première exclusion de responsabilité.

23
David M. Syzdek

Dans iOS 7, il existe une propriété keyboardDismissMode sur UIScrollView. Il suffit donc de le définir sur "UIScrollViewKeyboardDismissModeInteractive" et vous obtiendrez ce comportement. Fonctionne dans les sous-classes UIScrollView telles que UITableView.

self.tableView.keyboardDismissMode = UIScrollViewKeyboardDismissModeInteractive;

Swift 3:

tableView.keyboardDismissMode = .interactive

Ou modifiez-le dans le storyboard (si vous l'utilisez) dans l'inspecteur d'attributs de votre sous-classe UIScrollView.

49
Vladimir Shutyuk

La solution simple de Vladimir masquera le clavier lorsque l'utilisateur défilera vers le bas. Cependant, pour terminer la question concernant iMessage, afin de garder un TextField toujours visible et ancré en haut du clavier, vous devez implémenter ces méthodes:

- (UIView *) inputAccessoryView {
     // Return your textfield, buttons, etc
}

- (BOOL) canBecomeFirstResponder {
    return YES;
}

Voici un bon tutoriel le décomposer plus

3
Oren