Вопрос

Я работаю над приложением для iPad, используя 3.2 sdk.Я имею дело с получением размера клавиатуры, чтобы мои текстовые поля не скрывались за ней.

Я получаю предупреждение в Xcode -> UIKeyboardBoundsUserInfoKey устарел, что я должен использовать вместо этого, чтобы не получать это предупреждение?

Это было полезно?

Решение

Я играл с ранее предложенным решением, но все еще имел проблемы. Вот что я придумал вместо этого:

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

Другие советы

Из самого Документация для UIKeyboardBoundsUserInfoKey:

Ключ для объекта NSValue, содержащего CGRect, который идентифицирует прямоугольник границ клавиатуры в оконных координатах.Этого значения достаточно для получения размера клавиатуры.Если вы хотите определить происхождение клавиатуры на экране (до или после анимации), используйте значения, полученные из справочника информации о пользователе с помощью констант UIKeyboardCenterBeginUserInfoKey или UIKeyboardCenterEndUserInfoKey. Вместо этого используйте ключ UIKeyboardFrameBeginUserInfoKey или UIKeyboardFrameEndUserInfoKey.

Apple рекомендует внедрить удобную процедуру, подобную этой (которая могла бы быть реализована как дополнение к категории 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];
}

чтобы восстановить измененные в окне свойства размера рамки клавиатуры.

Я применил другой подход, который включает в себя проверку ориентации устройства:

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

Вы просто используете этот код:

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

Следующий код исправляет проблему в Ответ Джей, что предполагает, что UIKeyboardWillShowNotification Не будет снова стрелять, когда клавиатура уже присутствует.

При печати с японской / китайской клавиатурой, iOS стреляет в дополнение UIKeyboardWillShowNotification С новой рамой клавиатуры, даже если клавиатура уже присутствует, ведущая к высоте self.textView Быть сокращенным во второй раз в исходном коде.

Это уменьшается self.textView почти ничего. Затем становится невозможным оправи от этой проблемы, поскольку мы ожидаем только одного UIKeyboardWillHideNotification В следующий раз клавиатура уволен.

Вместо вычитания / добавления высоты до self.textView В зависимости от того, отображается ли клавиатура / скрытая, как в исходном коде, следующий код только что рассчитывает максимально возможную высоту для self.textView После вычитания высоты клавиатуры на экране.

Это предполагает что self.textView Предположим, чтобы заполнить весь вид контроллера просмотра, и нет другого подзрена, который должен быть виден.

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

}

Кроме того, не забудьте зарегистрировать уведомления клавиш в 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];
}

О разделении изменения размера в две части

Причина, по которой код TextView изменений разделяется на две части (resizeTextViewWithKeyboardNotification: а также resizeViewToAccommodateKeyboardFrame:withAnimationDuration:animationCurve:) - это исправить другую проблему, когда клавиатура сохраняется через толкание из одного контроллера просмотра к другому (см. Как мне обнаружить клавиатуру iOS, когда она оставалась между контроллерами?).

Поскольку клавиатура уже присутствует до того, как контроллер просмотра нажата, нет дополнительных уведомлений клавиатуры, не генерируемую IOS, и, следовательно, нет способа изменить размер textView на основе этих уведомлений на клавиатуре.

Вышеуказанный код (а также оригинальный код), который изменяет изменение изменений self.textView Таким образом, будет только работать, когда показана клавиатура после Вид был загружен.

Мое решение состоит в том, чтобы создать синглтон, который хранит последние координаты клавиатуры и на - viewDidAppear: ViewController, позвоните:

- (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 Мой синглтон здесь. В идеале мы должны называть это в - viewWillAppear:, Однако в моем опыте (хотя бы на iOS 6) convertRect:fromView: метод, который нам нужно использовать в resizeViewToAccommodateKeyboardFrame:withAnimationDuration:animationCurve: Не преобразует кадр клавиатуры к координатам просмотра до того, как представление полностью виден.

Просто используйте UIKeyboardFrameBeginUserInfoKey или UIKeyboardFrameEndUserInfoKey ключ вместо UIKeyboardBoundsUserInfoKey

@Jason, вы код, если хорошо, за исключением одной точки.

На данный момент вы на самом деле не анимируете все, и представление будет просто «POP» на свой новый размер.

Вы должны указать состояние, из которого для анимации. Анимация - это своего рода (из штата) -> (к государственной) вещи.

К счастью, существует очень удобный метод для указания текущего состояния представления как (от состояния).

[UIView setAnimationBeginsFromCurrentState:YES];

Если вы добавите эту строку сразу после начинаний: контекст: ваш код работает отлично.

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

Это работало так

Это ограничение нижней кнопки «Сохранить»

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

Внутри 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

Это функции, которые нам нужны

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()
    })
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top