2017-01-30 4 views
2

UITextFieldUITableViewの両方を含む私の主なアプリビューでは、UITapGestureRecognizerを使用して「通常の」コードを使用して、キーボードの外でタップが検出された場合は、 UITextFieldの内容を編集しています。複数のUIGestureRecognizersでiOSキーボードを解読

これは、仮想キーボードが実際に表示されている場合にのみ有効になります。仮想キーボードが表示されていない場合でも「バックグラウンドタップ」で編集を終了させたくない仮想キーボードが現在表示されている場合は消費されるはずです。 UITableView各もUITapGestureRecognizerが取り付けられてい対話ヘッダセルを有することを除いて

override func viewDidLoad() { 
    ... 

    tapper = UITapGestureRecognizer(target: self, action: #selector(viewTapped)) 

    NotificationCenter.default.addObserver(self, selector: #selector(keyboardShown), name: 
     NSNotification.Name(rawValue: "UIKeyboardDidShowNotification"), object: nil) 

    NotificationCenter.default.addObserver(self, selector: #selector(keyboardHidden), name: 
     NSNotification.Name(rawValue: "UIKeyboardDidHideNotification"), object: nil) 
} 

@IBAction func keyboardShown(_ sender: AnyObject) { 
    view.addGestureRecognizer(tapper!) 
} 

@IBAction func keyboardHidden(_ sender: AnyObject) { 
    view.removeGestureRecognizer(tapper!) 
} 

@IBAction func viewTapped(_ sender: AnyObject) { 
    view.endEditing(false) 
} 

このほとんど作品。

結果的に、ヘッダーセルをクリックすると、そのセルのジェスチャ認識機能が起動され、親ビューのジェスチャ認識機能は起動せず、キーボードは閉じられません。代わりにデータセルをクリックすると、すべて正常に動作します。

それが重要ならば、私のUITableViewは独自のUIViewControllerサブクラスを持ち、ネストされたUIViewに含まれている - の表は、私のメインビューコントローラでそのコードを持っているにはあまりにも複雑です。

親ビューの認識機能が接続されている場合に、サブビューのジェスチャ認識機能がこれらのタップを処理できないようにするにはどうすればよいですか?

+0

が、それはあまりにもあなたのビューコントローラを使用することを示唆しているために楽器を鈍らです'hitTest:withEvent:'をオーバーライドするカスタムビュークラスをルートとして使用します。これは、「ユーザーが画面に触れていますか?テストではなく、ジェスチャー認識機能を使用しますか?それは受動的なリスニングを可能にします。あなたはタッチを消費する必要はなく、いつものようにそれを渡すことができますが、タッチがシステムに入ることも知っています。 – Tommy

+0

@トミー私は重要な詳細(今は含まれています)を取り除いた - 私は(条件付きで)これらの接触を消費する必要があります。なぜなら、テキストフィールド以外のものがタッチされたときに通常のタッチイベントを発生させたくないからです。キーボードが消える。 – Alnitak

+0

@Tommyのヒントのおかげで、私は今より良い解決策を得ました! :) – Alnitak

答えて

0

私はまた、UITableView'sコントローラで仮想キーボード通知を観察し、キーボードの可視性の状態を追跡して、ヘッダ細胞のジェスチャー認識の上にこのUIGestureRecognizerDelegateメソッドを実装することで、「一時的な」解決策と考えるもの実装しました:

func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool { 
    return !keyboardShowing 
} 

これは、サブビュー内のメインビューから特定の量の機能を複製します。これは実際にはキーボードの状態を知る必要はありません。私はまだ親ビュー内から完全に処理できるメソッドを探しています。


EDIT - ヒントの@Tommyのおかげで、私は今、サブビューでキーボードの状態を追跡する必要性を取り除き、より良い解決策を持っています。

私の親ビューは、もはやUIGestureRecognizerを使用していますが、代わりにタッチイベントを追跡するためにUIViewのカスタムサブクラスを使用し、条件付きでそれらを無視:

class KeyboardDismissingView: UIView { 

    private var keyboardVisible = false 

    override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? { 
     guard let r = super.hitTest(point, with: event) else { return nil } 
     var v : UIView! = r 
     while v != nil { 
      if v is UITextField { 
       return r 
      } 
      v = v.superview 
     } 

     if keyboardVisible { 
      self.endEditing(false) 
      return nil 
     } 

     return r 
    } 

    func setup() { 
     NotificationCenter.default.addObserver(self, selector: #selector(keyboardShown), name: 
      NSNotification.Name(rawValue: "UIKeyboardDidShowNotification"), object: nil) 

     NotificationCenter.default.addObserver(self, selector: #selector(keyboardHidden), name: 
      NSNotification.Name(rawValue: "UIKeyboardDidHideNotification"), object: nil) 
    } 

    @IBAction func keyboardShown(_ sender: AnyObject) { 
     keyboardVisible = true 
    } 

    @IBAction func keyboardHidden(_ sender: AnyObject) { 
     keyboardVisible = false 
    } 

    override init (frame: CGRect) { 
     super.init(frame: frame) 
     setup() 
    } 

    required init(coder aDecoder: NSCoder) { 
     super.init(coder: aDecoder)! 
     setup() 
    } 
} 
関連する問題