web-dev-qa-db-ja.com

キーボードを閉じた後、inputAccessoryViewを表示したままにします

私がやろうとしているのは、iPadのSafariで「ページで検索」検索機能に似たものを作成することです。

いくつかのアイテムを含むUIToolbarを使用しており、inputAccessoryViewUITextFieldとして設定してキーボードに接続しています。チャームのように機能しますが、理解できないことが1つあります。 Safariでは、何かを検索すると、キーボードは消えますが、ツールバーは画面の下部に残ります。

誰かがこれを達成する方法についての手がかりを持っていますか?私が考えることができる唯一の解決策は、キーボードの却下されたイベントに応答してから、UIToolBarを引き出し、それを画面の下部に移動するカスタムアニメーションを作成することです。しかし、これはハッキーです。よりエレガントなソリューションを探しています。キーボードが閉じられたときに入力アクセサリビューをどうするかを私に決定させることができる何か。

33

これは次のように行われます。

UIToolbarをViewControllerのプロパティに割り当てます。

@property (strong, nonatomic) UIToolbar *inputAccessoryToolbar;

トップビューコントローラで、次のメソッドを追加します。

- (BOOL)canBecomeFirstResponder{

    return YES;

}

- (UIView *)inputAccessoryView{

    return self.inputAccessoryToolbar;

}

そして(オプションで、通常は必要ないはずなので)、キーボードが非表示になったときはいつでも、次のように呼び出します。

[self becomeFirstResponder];

そうすれば、inputAccessoryToolbarは、ビューコントローラとテキストビューの入力アクセサリビューの両方になります。

54
arik

入力アクセサリビューとして割り当てられていないUIToolBarになってしまい、UIKeyboardWillShowNotification / UIKeyboardWillHideNotificationを上下にスライドします。

7
anticyclope

@arikの答えに加えて、ここにSwiftバージョン:

class ViewController: UIViewController {

  @IBOutlet var textField: UITextField!      

  // Input Accessory View
  private var inputAccessoryToolbar: UIToolBar?
  override func canBecomeFirstResponder() -> Bool {
    return true
  }
  override var inputAccessoryView: UIView? {
    return inputAccessoryToolbar
  }

  override func viewDidLoad() {
    super.viewDidLoad()
    inputAccessoryToolbar = UIToolbar(frame: CGRectMake(0, 0, view.frame.size.width, 50))
    textField.inputAccessoryView = inputAccessoryToolbar
  }

  // UITextFieldDelegate
  func textFieldShouldReturn(textField: UITextField) -> Bool {
    becomeFirstResponder()
    return true
  }
}

クリーンなソリューションをありがとう!

4
Alex Koshy

以前の回答に基づいてSwift 4に更新します。 ストーリーボード を介してツールバーを追加すると、これを行うことができます。

class ViewController: UIViewController {

    @IBOutlet weak var textField: UITextField!
    @IBOutlet var toolbar: UIToolbar!

    override var canBecomeFirstResponder: Bool {
        get {
            return true
        }
    }

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

    override func viewDidLoad() {
        super.viewDidLoad()

        textField.inputAccessoryView = toolbar
    }
}

この場合、テキストフィールドがファーストレスポンダーを辞任するたびに、デフォルトでファーストレスポンダーがメインビューになります。複数のUI要素があり、ファーストレスポンダーのデフォルトが辞任後に望ましくないビューになる場合は、ファーストレスポンダーを明示的に辞任し、メインビューをファーストレスポンダーとして設定することをお勧めします。

3
esesmuedgars

また、inputAccessoryViewが安全領域のマージンを尊重せず、iPhone Xでホームインジケーター用のスペースを確保しないというバグを回避する必要がある場合もあります。 iPhone X View Controller inputAccessoryViewの処理方法?

XibからUIToolbarがあり、そのUIToolbarをテキストフィールドのinputAccessoryViewとして使用している場合、オーバーライドされたinputAccessoryViewからツールバーを返すときにツールバーをUIViewに埋め込み、含まれているUIViewを高くするのが最も簡単な解決策であることがわかりました。 safeAreaInsets.bottomによって。 (他の解決策では、ツールバーの下部をサブクラスの安全な領域に制限することを提案していますが、これは制約の競合につながり、ツールバーの下の領域の色が間違っていることも意味します。)ただし、テキストにも注意する必要があります。画面にキーボードがない場合でも(たとえば、外部キーボードがある場合)、フィールドにフォーカスを設定できるため、その場合も、テキストビューのinputAccessoryViewをこのUIView内のツールバーに変更する必要があります。実際、常に包含ビューを使用し、そのサイズを適切に調整するだけで、作業が簡単になる可能性があります。とにかく、inputAccessoryViewのオーバーライドは次のとおりです。

    override var inputAccessoryView: UIView? {

    if toolbarContainerView == nil {

        let frame=CGRect(x: toolBar.frame.minX, y: toolBar.frame.minY, width: toolbar.frame.width, height: toolBar.frame.height+view.safeAreaInsets.bottom)

        toolbarContainerView = UIView(frame: frame)

    }

    if (toolbar.superview != toolbarContainerView) {

        //this is set to false when the toolbar is used above the keyboard without the container view

        //we need to set it to true again or else the toolbar will appear at the very top of the window instead of the bottom if the keyboard has previously been shown.

        toolbar.translatesAutoresizingMaskIntoConstraints=true

        toolbarContainerView?.addSubview(toolbar)

    }

    return toolbarContainerView

}

その場合も、viewSafeAreaInsetsDidChangeをオーバーライドしてtoolbarContainerViewのサイズを調整することをお勧めします。

0
Angela