web-dev-qa-db-ja.com

下部にドッキングされたInputAccessoryView

Appleのメッセージアプリの下部のテキスト入力バーと同様の配置動作を実現しようとしています。

私は多くのアプローチを試し、高低を検索し、同様の質問がたくさんありますが、満足できるものはありませんでした。

指定します:

  1. ビューの下部にUIToolbarがあります
  2. ツールバーは、キーボードの表示と非表示に合わせてキーボードをたどります
  3. キーボードが表示されているとき、ツールバーはキーボードの上にある必要があります
  4. キーボードが非表示の場合、ツールバーはビューの下部に留まります(「ドッキング」)

提案されたソリューション:

キーボードの外観通知に応じてツールバーを手動でアニメーション化する

このソリューションは、2番目の要件の特殊なケースを満たしていません(ツールバーは、キーボードが表示されたり消えたりするときにキーボードをたどることです):

  • IOS 7では、UIScrollViewKeyboardDismissModeが導入されました。キーボードを閉じるためのインタラクティブなジェスチャーを有効にします。ユーザーがキーボードの上端を超えてパンすると、キーボードフレームが徐々に追従します。このソリューションは、この動作に対応するために何もせず、ツールバーをアニメーション化された位置に取り残します。

さらに、このソリューションは、3番目の要件の特殊なケースも満たせません(キーボードが表示されている場合、ツールバーはキーボードの上に留まる必要があります) :

  • 回転。このソリューションでは、デバイスの回転に応じてツールバーを回転させるために、追加の迷惑な外部コードが必要です(次の提案ソリューションで説明します)。

このソリューションの別の問題:

  • キーボードの高さ。このソリューションでは、ツールバーがキーボードの高さの一部であると想定されていないため、コンテンツの適切なインセットをサポートするために追加のコードを記述する必要があります。

次に提案される解決策:

UIResponderinputAccessoryViewを使用

この解決策は、ツールバーを手動でアニメートすることのすべての欠点を解決するため、Appleがこの種の動作をサポートすることを意図した方法のようです。ただし、このソリューションでは、4番目の要件(が非表示の場合、ツールバーはビューの下部にある(ドッキングされた)ままです)。


解決策はUIResponderinputAccessoryViewを使用することですが、どういうわけかinputAccessoryViewをビューの下に移動させないようにすることです。これを実現するためのきれいなコードを探しています。精巧な、ほとんど高貴な試みが他の場所にありますが、前述のように、それらは要件を満たしていません。

私の特定のケースでは、UINavigationControllerの意図された動作ではないため、追加の問題を伴うUINavigationControllerのツールバーを使用したいと考えています。関係なく、私はそれを達成するためにいくつかのハッキーな修正を導入したいと思っています。

46
Stian Høiland

Jason Foreman(@threeve)による "the"ソリューションが示されました。 View Controller(はい、View Controller)にinputAccessoryView:そして、ドッキングしたいビューを一番下に戻し、キーボードで移動します。それはただ動作します。ビューは実際にはビュー階層にある必要はなく、View Controllerによって自動的に挿入されます。

編集:canBecomeFirstResponderも実装し、YESを返します(Max Seelemannが述べています)。 reloadInputViewsも便利です。

57
Jonathan Badeen

ジョナサン・バディーンの前述の 解決策 は私のために働いた。 Arik のコードは、それを実装する方法を示しています(これは適切なView Controllerで実行する必要があります)。

    - (BOOL)canBecomeFirstResponder{

        return YES;

    }

    - (UIView *)inputAccessoryView{

        return self.inputAccessoryToolbar;  
     // where inputAccessoryToolbar is your keyboard accessory view

    }
31
Russ Hooper

Swiftバージョン:

ツールバー(私の場合は 'myToolBar')をView Controllerに接続します。次に、canBecomeFirstResponderメソッドをオーバーライドし、ゲッターinputAccessoryView変数をオーバーライドします。また、self.myToolBar.removeFromSuperview()を追加することを忘れないでください。そうしないと、xcodeが文句を言います。

class ViewController: UIViewController {

    @IBOutlet var myToolBar: UIToolbar!

    override func canBecomeFirstResponder() -> Bool {
        return true
    }


    override var inputAccessoryView:UIView{
        get{
            return self.myToolBar
        }
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        self.myToolBar.removeFromSuperview()
    }
}
9
jonprasetyo

ですから、これは古い投稿であり、これを解決したかどうかはわかりませんが、これを機能させる方法を見つけました。 inputAccessoryViewにはバグがあると思いますが、メッセージアプリと同じように振る舞うためのハッキングソリューションを作成しました。回避策を実装するために必要なすべてのコードを提供したと思います。私は、近い将来いつかより適切なブログ投稿を作成し、私の調査結果をより詳細に説明するつもりです。ご質問は、私に知らせてください。

@property(nonatomic,assign)BOOL isFirstKeyboard; //workaround for keyboard bug

@property(nonatomic,assign)BOOL isViewAppear;

@property(nonatomic,strong)ChatBarView *chatView; //custom chat bar view

@property(nonatomic,strong)UIView *footerPadView; //just to add some Nice padding
////////////////////////////////////////////////////////////////////////////////////////////////////
//in the view did load
- (void)viewDidLoad
{
    //more app specific code...
    self.tableView.keyboardDismissMode = UIScrollViewKeyboardDismissModeInteractive;
    self.chatView.textView.inputAccessoryView = self.chatView;
}

////////////////////////////////////////////////////////////////////////////////////////////////////
-(void)done
{
    self.isFirstKeyboard = YES;
    [self.chatView.textView becomeFirstResponder];
}
////////////////////////////////////////////////////////////////////////////////////////////////////
- (void) moveTextViewForKeyboard:(NSNotification*)aNotification up:(BOOL)up
{
    if(!self.isViewAppear)
        return;
    //NSLog(@"keyboard is: %@", up ? @"UP" : @"Down");
    if(!up && !self.isFirstKeyboard)
        [self performSelector:@selector(done) withObject:nil afterDelay:0.01];
    else if(!up & self.isFirstKeyboard)
    {
        self.isFirstKeyboard = NO;
        [self.view addSubview:self.chatView];
        CGRect frame = self.chatView.frame;
        frame.Origin.y = self.view.frame.size.height - self.chatView.frame.size.height;
        self.chatView.frame = frame;
    }
    else
    {
        NSDictionary* userInfo = [aNotification 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];
        if(up)
            [UIView setAnimationDuration:0.2];
        else
            [UIView setAnimationDuration:0.3];
        [UIView setAnimationCurve:animationCurve];

        CGRect frame = self.footerPadView.frame;
        CGRect keyboardFrame = [self.view convertRect:keyboardEndFrame toView:nil];
        if (up)
            frame.size.height = keyboardFrame.size.height - self.chatView.frame.size.height;
        else
            frame.size.height = 0;
        self.footerPadView.frame = frame;
        self.tableView.tableFooterView = self.footerPadView;
        [UIView commitAnimations];
    }
}
////////////////////////////////////////////////////////////////////////////////////////////////////
- (void)keyboardWillShow:(NSNotification *)aNotification {
    [self moveTextViewForKeyboard:aNotification up:YES];
}
////////////////////////////////////////////////////////////////////////////////////////////////////
- (void)keyboardWillHide:(NSNotification *)aNotification
{
    [self moveTextViewForKeyboard:aNotification up:NO];
}
////////////////////////////////////////////////////////////////////////////////////////////////////
2
daltoniam