Следующий код исправляет проблему в ответе Джея , в которой предполагается, что 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:
, неправильно преобразовывает кадр клавиатуры в координаты представления перед просмотром полностью виден.