Question

Je travaille sur une application iPad en utilisant 3.2 sdk. Je fais face à obtenir la taille du clavier pour empêcher mes textfields de hidding derrière elle.

Je reçois un avertissement dans Xcode -> UIKeyboardBoundsUserInfoKey est dépréciée que dois-je utiliser au lieu de ne pas obtenir cet avertissement

Était-ce utile?

La solution

Je joue avec la solution précédemment proposée, mais encore eu des problèmes. Voici ce que je suis venu avec la place:

    - (void)keyboardWillShow:(NSNotification *)aNotification {
    [self moveTextViewForKeyboard:aNotification up:YES];
}

    - (void)keyboardWillHide:(NSNotification *)aNotification {
        [self moveTextViewForKeyboard:aNotification up:NO]; 
    }

- (void) moveTextViewForKeyboard:(NSNotification*)aNotification up: (BOOL) up{
NSDictionary* userInfo = [aNotification userInfo];

// Get animation info from 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];
[UIView setAnimationDuration:animationDuration];
[UIView setAnimationCurve:animationCurve];

CGRect newFrame = textView.frame;
CGRect keyboardFrame = [self.view convertRect:keyboardEndFrame toView:nil];

newFrame.origin.y -= keyboardFrame.size.height * (up? 1 : -1);
textView.frame = newFrame;

[UIView commitAnimations];
}

Autres conseils

De documentation pour UIKeyboardBoundsUserInfoKey:

  

La clé d'un objet NSValue contenant un CGRect qui identifie le rectangle des bornes du clavier en coordonnées fenêtre. Cette valeur est suffisante pour obtenir la taille du clavier. Si vous voulez obtenir l'origine du clavier à l'écran (avant ou après l'animation) utiliser les valeurs obtenues à partir du dictionnaire informations utilisateur à travers les constantes de UIKeyboardCenterBeginUserInfoKey ou UIKeyboardCenterEndUserInfoKey. Utilisez le UIKeyboardFrameBeginUserInfoKey ou UIKeyboardFrameEndUserInfoKey clé à la place.

Apple recommande l'application d'une routine de pratique comme celle-ci (qui pourrait être mis en œuvre comme un ajout de catégorie à UIScreen):

+ (CGRect) convertRect:(CGRect)rect toView:(UIView *)view {
    UIWindow *window = [view isKindOfClass:[UIWindow class]] ? (UIWindow *) view : [view window];
    return [view convertRect:[window convertRect:rect fromWindow:nil] fromView:nil];
}

pour récupérer les propriétés de taille cadre du clavier ajusté fenêtre.

Je pris une approche différente, qui consiste à vérifier l'orientation de l'appareil:

CGRect _keyboardEndFrame;
[[notification.userInfo valueForKey:UIKeyboardFrameEndUserInfoKey] getValue:&_keyboardEndFrame];
CGFloat _keyboardHeight = ([[UIDevice currentDevice] orientation] == UIDeviceOrientationPortrait || [[UIDevice currentDevice] orientation] == UIDeviceOrientationPortraitUpsideDown) ? _keyboardEndFrame.size.height : _keyboardEndFrame.size.width;

Vous utilisez simplement ce code:

//NSVale *aValue = [info objectForKey:UIKeyboardBoundsUserInfoKey];
//instead of Upper line we can use either next line or nextest line.
//NSValue *aValue = [info objectForKey:UIKeyboardFrameEndUserInfoKey];
NSValue *aValue = [info objectForKey:UIKeyboardFrameBeginUserInfoKey];

Le code suivant résout un problème dans réponse de Jay , ce qui suppose que UIKeyboardWillShowNotification ne le feu à nouveau lorsque le clavier est déjà présent.

Lors de la saisie avec le clavier japonais / chinois, iOS déclenche un UIKeyboardWillShowNotification supplémentaire avec le nouveau cadre du clavier, même si le clavier est déjà présent, ce qui conduit à la hauteur de la self.textView étant réduite une seconde fois dans le code d'origine.

Cela réduit self.textView à presque rien. Il devient alors impossible de récupérer de ce problème car nous n'attendre un UIKeyboardWillHideNotification la prochaine fois que le clavier est rejeté.

Au lieu de soustraction / ajoutant hauteur self.textView selon que le clavier apparaît / disparaît comme dans le code d'origine, le code suivant calcule juste la hauteur maximale possible pour self.textView après soustraction de la hauteur du clavier à l'écran.

Cela suppose que self.textView est censé remplir toute la vue du contrôleur de vue, et il n'y a pas d'autre sous-vue qui doit être visible.

- (void)resizeTextViewWithKeyboardNotification:(NSNotification*)notif {

    NSDictionary* userInfo = [notif userInfo];
    NSTimeInterval animationDuration;
    UIViewAnimationCurve animationCurve;
    CGRect keyboardFrameInWindowsCoordinates;

    [[userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] getValue:&animationCurve];
    [[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] getValue:&animationDuration];
    [[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] getValue:&keyboardFrameInWindowsCoordinates];

    [self resizeTextViewToAccommodateKeyboardFrame:keyboardFrameInWindowsCoordinates
                             withAnimationDuration:animationDuration
                                    animationCurve:animationCurve];

}

- (void)resizeTextViewToAccommodateKeyboardFrame:(CGRect)keyboardFrameInWindowsCoordinates
                           withAnimationDuration:(NSTimeInterval)duration
                                  animationCurve:(UIViewAnimationCurve)curve
{

    CGRect fullFrame = self.view.frame;

    CGRect keyboardFrameInViewCoordinates =
    [self.view convertRect:keyboardFrameInWindowsCoordinates fromView:nil];

    // Frame of the keyboard that intersects with the view. When keyboard is
    // dismissed, the keyboard frame still has width/height, although the origin
    // keeps the keyboard out of the screen.
    CGRect keyboardFrameVisibleOnScreen =
    CGRectIntersection(fullFrame, keyboardFrameInViewCoordinates);

    // Max frame availble for text view. Assign it to the full frame first
    CGRect newTextViewFrame = fullFrame;

    // Deduct the the height of any keyboard that's visible on screen from
    // the height of the text view
    newTextViewFrame.size.height -= keyboardFrameVisibleOnScreen.size.height;

    if (duration)
    {
        [UIView beginAnimations:nil context:nil];
        [UIView setAnimationDuration:duration];
        [UIView setAnimationCurve:curve];
    }

    // Adjust the size of the text view to the new one
    self.textView.frame = newTextViewFrame;

    if (duration)
    {
        [UIView commitAnimations];
    }

}

En outre, ne pas oublier d'enregistrer les notifications de clavier dans viewDidLoad:

- (void)viewDidLoad
{
    [super viewDidLoad];
    NSNotificationCenter* notifCenter = [NSNotificationCenter defaultCenter];

    [notifCenter addObserver:self selector:@selector(resizeTextViewWithKeyboardNotification:) name:UIKeyboardWillShowNotification object:nil];
    [notifCenter addObserver:self selector:@selector(resizeTextViewWithKeyboardNotification:) name:UIKeyboardWillHideNotification object:nil];
}

A propos de diviser le code de redimensionnement en deux parties

La raison pour laquelle le code de redimensionnement textView est divisé en deux parties (resizeTextViewWithKeyboardNotification: et resizeViewToAccommodateKeyboardFrame:withAnimationDuration:animationCurve:) est de fixer un autre problème lorsque le clavier persiste par une poussée d'un contrôleur de vue à l'autre (voir Comment détecter le clavier iOS quand il reste entre contrôleurs? ).

Depuis le clavier est déjà présent avant que le contrôleur de vue est poussé, il n'y a aucune notification de clavier supplémentaires générées par iOS, et donc aucun moyen de redimensionner la textView en fonction de ces notifications de clavier.

Le code ci-dessus (ainsi que le code d'origine) qui redimensionne self.textView sera donc que le travail lorsque le clavier est montré après la vue a été chargé.

Ma solution est de créer un singleton qui stocke les dernières coordonnées du clavier, et - viewDidAppear: du viewController, appelez:

- (void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];

    // Resize the view if there's any keyboard presence before this
    // Only call in viewDidAppear as we are unable to convertRect properly
    // before view is shown
    [self resizeViewToAccommodateKeyboardFrame:[[UASKeyboard sharedKeyboard] keyboardFrame]
                         withAnimationDuration:0
                                animationCurve:0];
}

UASKeyboard est mon singleton ici. Idéalement, nous devrions appeler cela dans - viewWillAppear:, mais dans mon expérience (au moins sur iOS 6), la méthode convertRect:fromView: que nous devons utiliser dans resizeViewToAccommodateKeyboardFrame:withAnimationDuration:animationCurve: ne convertit pas correctement le cadre du clavier à la vue les coordonnées avant que la vue est entièrement visible.

Il suffit d'utiliser la touche UIKeyboardFrameBeginUserInfoKey ou UIKeyboardFrameEndUserInfoKey au lieu de UIKeyboardBoundsUserInfoKey

@ Jason, vous codez si bien sauf pour un point.

Au moment où vous n'êtes pas animez quoi que ce soit et la vue sera tout simplement `pop » à son nouveau size.height.

Vous devez spécifier un état à partir de laquelle à animer. Une animation est une sorte de (de l'état) -.> (À l'autre) chose

Heureusement, il existe une méthode très pratique pour indiquer l'état actuel de la vue comme (de l'état).

[UIView setAnimationBeginsFromCurrentState:YES];

Si vous ajoutez ce droit de ligne après beginAnimations: contexte: votre code fonctionne parfaitement.

- (CGSize)keyboardSize:(NSNotification *)aNotification {
    NSDictionary *info = [aNotification userInfo];
    NSValue *beginValue = [info objectForKey:UIKeyboardFrameBeginUserInfoKey];

    UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];

    CGSize keyboardSize;
    if ([UIKeyboardDidShowNotification isEqualToString:[aNotification name]]) {
        _screenOrientation = orientation;
        if (UIDeviceOrientationIsPortrait(orientation)) {
            keyboardSize = [beginValue CGRectValue].size;
        } else {
            keyboardSize.height = [beginValue CGRectValue].size.width;
            keyboardSize.width = [beginValue CGRectValue].size.height;
        }
    } else if ([UIKeyboardDidHideNotification isEqualToString:[aNotification name]]) {
        // We didn't rotate
        if (_screenOrientation == orientation) {
            if (UIDeviceOrientationIsPortrait(orientation)) {
                keyboardSize = [beginValue CGRectValue].size;
            } else {
                keyboardSize.height = [beginValue CGRectValue].size.width;
                keyboardSize.width = [beginValue CGRectValue].size.height;
            }
        // We rotated
        } else if (UIDeviceOrientationIsPortrait(orientation)) {
            keyboardSize.height = [beginValue CGRectValue].size.width;
            keyboardSize.width = [beginValue CGRectValue].size.height;
        } else {
            keyboardSize = [beginValue CGRectValue].size;
        }
    }


    return keyboardSize;
}

Son travaillé comme ceci

Ceci est la contrainte du fond du bouton Enregistrer

@IBOutlet weak var saveBtnBottom: NSLayoutConstraint!
@IBOutlet weak var nameText: UITextField!

A l'intérieur viewDidLoad

NotificationCenter.default.addObserver(self, selector: #selector(keyBoardWillShow(notification:)), name: UIResponder.keyboardWillShowNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(keyBoardWillHide(notification:)), name: UIResponder.keyboardWillHideNotification, object: nil)
nameText.delegate = self

Ce sont les fonctions dont nous avons besoin

func textFieldShouldReturn(_ textField: UITextField) -> Bool {
    nameText.resignFirstResponder()
    return true
}


@objc func keyBoardWillShow(notification: Notification){
    if let userInfo = notification.userInfo as? Dictionary<String, AnyObject>{
        let frame = userInfo[UIResponder.keyboardFrameEndUserInfoKey]
        let keyBoardRect = frame?.cgRectValue
        if let keyBoardHeight = keyBoardRect?.height {
            self.saveBtnBottom.constant = keyBoardHeight 

            UIView.animate(withDuration: 0.5, animations: {
                self.view.layoutIfNeeded()
            })
        }
    }
}

@objc func keyBoardWillHide(notification: Notification){
    self.saveBtnBottom.constant = 30.0
    UIView.animate(withDuration: 0.5, animations: {
        self.view.layoutIfNeeded()
    })
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top