3.2 SDKを使用してiPadアプリで作業しています。私はキーボードのサイズを取得して、テキストフィールドが背後に隠れないようにしています。
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
の- ドキュメント から:
ウィンドウ座標でキーボードの境界矩形を識別するCGRectを含むNSValueオブジェクトのキー。この値は、キーボードのサイズを取得するには十分です。画面上のキーボードの原点(アニメーションの前後)を取得する場合は、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
が再び起動しないことを前提とする Jayの答え の問題を修正します。
日本語/中国語キーボードで入力すると、iOSは、キーボードが既に存在している場合でも、新しいキーボードフレームで余分なUIKeyboardWillShowNotification
を起動し、self.textView
の高さを2回減らします。元のコード。
これにより、self.textView
がほとんどゼロになります。次に、キーボードが閉じられたときに単一のUIKeyboardWillHideNotification
しか期待しないため、この問題から回復することは不可能になります。
キーボードが元のコードのように表示/非表示になっているかどうかに応じてself.textView
の高さを減算/加算する代わりに、次のコードは、キーボードの高さを減算した後にself.textView
の最大可能高さを計算します画面。
これは、self.textView
がView Controllerのビュー全体を埋めると仮定し、表示する必要のある他のサブビューがないことを前提としています。
- (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のサイズ変更コードが2つの部分(resizeTextViewWithKeyboardNotification:
およびresizeViewToAccommodateKeyboardFrame:withAnimationDuration:animationCurve:
)に分割される理由は、あるView Controllerから別のView Controllerへのプッシュを介してキーボードが持続する場合の別の問題を修正するためです( How iOSキーボードがコントローラー間で立ち上がっているときに検出できますか? )。
View Controllerがプッシュされる前にキーボードがすでに存在するため、iOSによって追加のキーボード通知が生成されることはありません。したがって、これらのキーボード通知に基づいてtextView
のサイズを変更する方法はありません。
したがって、self.textView
のサイズを変更する上記のコード(および元のコード)は、キーボードが表示されている場合にのみ機能しますafterビューがロードされました。
私の解決策は、最後のキーボード座標を格納するシングルトンを作成し、viewControllerの- viewDidAppear:
で次を呼び出します。
- (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、1ポイントを除いて問題なければコーディングします。
現時点では、実際には何もアニメートしておらず、ビューは単に新しいsize.heightに「ポップ」します。
アニメーション化する状態を指定する必要があります。アニメーションは(状態から)->(状態へ)のようなものです。
幸いなことに、ビューの現在の状態を(from state)として指定する非常に便利な方法があります。
[UIView setAnimationBeginsFromCurrentState:YES];
BeginAnimations:context:の直後にその行を追加すると、コードは完全に機能します。
- (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()
})
}