web-dev-qa-db-ja.com

キーボードが表示されたときにビューのサイズを変更する(iOS)

TPKeyboardAvoidingAppleの有名なソリューション 、UIScrollViewの使用に関するさまざまな提案など、多くの同様のソリューションがあることに気付きました。私の場合、キーボードをスクロールしたり移動したりするのではなく、キーボードに合わせてビューのサイズを変更する必要があります。 この解決策 私が達成しようとしていることに最も近いので、それが私の基礎でした。ただし、ランドスケープモードで動作させるのに問題があります。キーボードが表示されたときにビューのサイズを変更する私の方法は次のとおりです。

- (void)keyboardWillShow:(NSNotification *)note {
    NSDictionary *userInfo = note.userInfo;
    NSTimeInterval duration = [[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
    UIViewAnimationCurve curve = [[userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] intValue];

    CGRect keyboardFrame = [[self textField].superview convertRect:[[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue] fromView:nil];
    CGRect statusBarFrame = [[self textField].superview convertRect:[UIApplication sharedApplication].statusBarFrame fromView:nil];

    CGRect bounds = [self textField].superview.bounds;    
    CGRect newFrame = CGRectMake(0.0, 0.0, bounds.size.width, keyboardFrame.Origin.y + statusBarFrame.size.height);
    [UIView animateWithDuration:duration delay:0 options:UIViewAnimationOptionBeginFromCurrentState | curve animations:^{
        [self textField].superview.frame = newFrame;
    } completion:nil];
}

これはポートレートモードで完全に機能します。

enter image description here

ただし、横向きモードでは、ビューは下からではなく、デバイスが回転した方向に応じて、左から右または右から左にサイズ変更されます。

enter image description here

明らかに、座標の使用方法に問題があり、ランドスケープモードの場合、参照フレームの一部が私が思うものではありませんが、それを解決する方法を整理するのにかなりの時間がかかります。 -convertRectを使用してあらゆる種類のものを変換しようとしましたが、何も試みていません。

これらすべての長方形と、向きが変わったときに長方形がどのように変化するかについて混乱が少ない人が、私が間違っていることと、これを正しくするために何をする必要があるかを見つけられることを本当に望んでいます。参考までに、私は プロジェクトを作成しました 私が抱えている問題を再現する最も単純なケースを示しています。

12
bkocik

ビューコントローラのルートビューのサイズを変更することはお勧めしません。contentViewを作成してビューコントローラのビューに追加できます。このcontentViewのサイズは次のように変更できます(自動レイアウトは使用しません)。

- (void)keyboardWillShow:(NSNotification *)note {
    NSDictionary *userInfo = note.userInfo;
    NSTimeInterval duration = [userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue];
    UIViewAnimationCurve curve = [userInfo[UIKeyboardAnimationCurveUserInfoKey] integerValue];

    CGRect keyboardFrameEnd = [userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
    keyboardFrameEnd = [self.view convertRect:keyboardFrameEnd fromView:nil];

    [UIView animateWithDuration:duration delay:0 options:UIViewAnimationOptionBeginFromCurrentState | curve animations:^{
        self.contentView.frame = CGRectMake(0, 0, keyboardFrameEnd.size.width, keyboardFrameEnd.Origin.y);
    } completion:nil];
}

- (void)keyboardWillHide:(NSNotification *)note {
    NSDictionary *userInfo = note.userInfo;
    NSTimeInterval duration = [userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue];
    UIViewAnimationCurve curve = [userInfo[UIKeyboardAnimationCurveUserInfoKey] integerValue];

    CGRect keyboardFrameEnd = [userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
    keyboardFrameEnd = [self.view convertRect:keyboardFrameEnd fromView:nil];

    [UIView animateWithDuration:duration delay:0 options:UIViewAnimationOptionBeginFromCurrentState | curve animations:^{
        self.contentView.frame = CGRectMake(0, 0, keyboardFrameEnd.size.width, keyboardFrameEnd.Origin.y);
    } completion:nil];
}
27
Vitaly Berg

SwiftでのVitaliyBの答え。 templateHeaderContentViewというビューを取得し、関数を作成して、そこでビューの高さを構成しました。独自のビューを使用し、それに応じて高さを変更します。

func keyboardWillShow(notification: NSNotification) {
    keyboardShowOrHide(notification)
}

func keyboardWillHide(notification: NSNotification) {
    keyboardShowOrHide(notification)
}

private func keyboardShowOrHide(notification: NSNotification) {
    guard let userInfo = notification.userInfo else {return}
    guard let duration = userInfo[UIKeyboardAnimationDurationUserInfoKey]else { return }
    guard let curve = userInfo[UIKeyboardAnimationCurveUserInfoKey] else { return }
    guard let keyboardFrameEnd = userInfo[UIKeyboardFrameEndUserInfoKey] else { return }

    let curveOption = UIViewAnimationOptions(rawValue: UInt(curve.integerValue << 16))
    let keyboardFrameEndRectFromView = view.convertRect(keyboardFrameEnd.CGRectValue, fromView: nil)
    UIView.animateWithDuration(duration.doubleValue ?? 1.0,
        delay: 0,
        options: [curveOption, .BeginFromCurrentState],
        animations: { () -> Void in
            self.templateHeaderContentView.configureView(keyboardFrameEndRectFromView.Origin.y)
        }, completion: nil)
}
5
xiongemi
2
Michael Favia

私はこのコードがあなたに役立つことを願っていました。

- (void)viewWillAppear:(BOOL)animated
{
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(keyboardWillShow:)
                                                 name:UIKeyboardWillShowNotification
                                               object:nil];

    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(keyboardWillBeHidden:)
                                                 name:UIKeyboardWillHideNotification
                                               object:nil];
}

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

- (void)keyboardWillBeHidden:(NSNotification*)notification
{
    [self moveControls:notification up:NO];
}

- (void)moveControls:(NSNotification*)notification up:(BOOL)up
{
    NSDictionary* userInfo = [notification userInfo];
    CGRect newFrame = [self getNewControlsFrame:userInfo up:up];

    [self animateControls:userInfo withFrame:newFrame];
}

- (CGRect)getNewControlsFrame:(NSDictionary*)userInfo up:(BOOL)up
{
    CGRect kbFrame = [[userInfo objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue];
    kbFrame = [self.view convertRect:kbFrame fromView:nil];

    CGRect newFrame = self.view.frame;
    newFrame.Origin.y += kbFrame.size.height * (up ? -1 : 1);

    return newFrame;
}

- (void)animateControls:(NSDictionary*)userInfo withFrame:(CGRect)newFrame
{
    NSTimeInterval duration = [[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
    UIViewAnimationCurve animationCurve = [[userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] integerValue];

    [UIView animateWithDuration:duration
                          delay:0
                        options:animationOptionsWithCurve(animationCurve)
                     animations:^{
                         self.view.frame = newFrame;
                     }
                     completion:^(BOOL finished){}];
}

static inline UIViewAnimationOptions animationOptionsWithCurve(UIViewAnimationCurve curve)
{
    return (UIViewAnimationOptions)curve << 16;
}
1
Patel Jigar