53

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

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

指定します:

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

提案された解決策:

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

このソリューションは、2 番目の要件の特殊なケースを満たしていません (キーボードが表示および非表示になると、ツールバーはキーボードに従います)。

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

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

  • 回転。この解決策では、デバイスの回転に応じてツールバーを回転させるために (次の提案された解決策で説明するように) 追加の厄介な余分なコードが必要になります。

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

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

次に提案された解決策:

UIResponderを使用inputAccessoryView

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


解決策はUIResponder'sを使用することですinputAccessoryViewが、どういうわけかinputAccessoryViewビューの下に移動しないようにします。これを達成するためのクリーンなコードを探しています。精巧で、ほとんど高尚な試みが他にもありますが、前述のように、それらは要件を満たしていません。

私の特定のケースではUINavigationController、これは意図された動作ではないため、追加の問題を伴う のツールバーを使用しようとしていUINavigationControllerます。いずれにせよ、それを達成するためのハッキーな修正を喜んで導入します。

4

5 に答える 5

60

Jason Foreman (@threeve) によって「その」解決策が示されました。ビューコントローラー(はい、ビューコントローラー)inputAccessoryView:で、ドッキングしたいビューを追加して戻し、キーボードで移動します。それだけで機能します。ビューは実際にはビュー階層にある必要はなく、ビュー コントローラーによって自動的に挿入されます。

編集: また、canBecomeFirstResponder を実装し、YES を返します (Max Seelemann が指摘したように)。reloadInputViews も便利です。

于 2014-05-27T03:23:28.483 に答える
32

Jonathan Badeenの前述のソリューションは私にとってはうまくいきました。これを実装する方法を示すArikのコードを次に示します (これは、適切なビュー コントローラーに配置する必要があります)。

    - (BOOL)canBecomeFirstResponder{

        return YES;

    }

    - (UIView *)inputAccessoryView{

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

    }
于 2014-08-08T22:37:53.050 に答える
14

Swift バージョンをお探しの方へ:

ツールバー (私の場合は ' myToolBar') をビュー コントローラーに接続します。次にcanBecomeFirstResponderメソッドをオーバーライドし、getterinputAccessoryView変数をオーバーライドします。また、追加することを忘れないでください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()
    }
}
于 2015-06-25T17:24:26.190 に答える
6

Slack の優秀な人々による、これに対する優れた、実装が容易なオープンソース ソリューションがあります: SlackTextViewController

ドッキングされたツールバーを含むビューを 4 つの手順で実装する方法を次に示します。

  1. ポッドをプロジェクトにインストールします。( http://cocoapods.org/?q=SlackTextViewController )
  2. Swift でアプリを作成している場合は、Swift コードとその Obj-C クラスを橋渡しするヘッダーを作成します。これについての簡単なチュートリアルを次に示します。(クラスが Swift に変換されると、ブリッジング ヘッダーは必要なくなります。共同作業をしたい人はいますか?)
  3. MessageViewControllerから継承する を作成します。SLKTextViewControllerこれ以上のコードを記述する必要はありません。

    import Foundation
    import UIKit
    
    class MessageViewController: SLKTextViewController {
    
        required init(coder aDecoder: NSCoder!) {
            super.init(coder: aDecoder)
        }
    }
    
  4. Storyboard で、MessageViewController を継承する View Controller を作成します。
  5. デバイスまたはエミュレーターでアプリをテストすると、ドッキングされた美しいテキストバーが表示され、ユーザーが追加のテキスト行を書き込むと (おまけとして) 拡張されます。

このような便利なポッドを抽出した Slack のチームに感謝します。

于 2014-10-20T14:00:41.883 に答える
2

これが古い投稿であることはわかっています。これを解決したかどうかはわかりませんが、これを機能させる方法を見つけました。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];
}
////////////////////////////////////////////////////////////////////////////////////////////////////
于 2013-12-24T05:11:28.573 に答える