質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.49%
Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

Q&A

解決済

1回答

9079閲覧

UITapGestureRecognizerを子ビューでは反応しないようにする方法

mitci

総合スコア37

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

0グッド

0クリップ

投稿2017/11/19 09:22

編集2017/11/19 09:56

###前提
storyboard上で以下のような配置をしました。
storyBoard
親ビューの中に子ビューを配置し、その上にボタンやスライダーを配置したものです。

この親ビューにタップジェスチャーをaddすると、
子ビューをタップしてもUIButtonとUISliderのツマミ以外の部分をタップしてしまうと親ビューのタップジェスチャーが呼び出されてしまいます。

###実現したいこと
こうなってほしい
上のようにしたいため、
子ビューにタップしたときに親ビューのタップジェスチャーが呼び出されてしまうと、困るのです。
もっとも困るのは、
UISliderのツマミを動かしただけも、タップされたと判断して親ビューのタップジェスチャーが呼び出されてしまうということです。
こんな感じになってしまいます・・・↓
こうなっちゃう

###試したこと
UIGestureRecognizerDelegateを批准してshouldReceiveTouchメソッドで親ビュー以外がタップされた時にfalseを返すようにしたのですが、今度は親ビュー部分をタップしても子ビューをタップしてもfalseを返されてしまうようになってしまいました・・・

###詳細なコード

swift

1class ViewController: UIViewController, UIGestureRecognizerDelegate { 2 //デリゲートに批准する。 3 override func viewDidLoad() { 4 super.viewDidLoad() 5 //省略 6 let tapGesture = UITapGestureRecognizer(target: self, action: #selector(dismissKoView)) 7 self.oyaView.addGestureRecognizer(tapGesture) 8 //親ビュー(oyaView)にジェスチャーをadd 9 tapGesture.cancelsTouchesInView = false 10 tapGesture.delegate = self 11 //デリゲートを指定する。 12 } 13 14 func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldReceiveTouch touch: UITouch) -> Bool { 15 if (touch.view?.isDescendant(of: oyaView))! { 16 return false 17 } 18 return true 19 } 20 //メソッドを導入 21 func dismissKoView() { 22 //以下略

###補足情報(言語/FW/ツール等のバージョンなど)
swift3 xcode8

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

こんな感じでどうでしょうか

環境
Swift4
Xcode9.1

swift

1class ViewController: UIViewController, UIGestureRecognizerDelegate { 2 3 @IBOutlet weak var parentView: UIVisualEffectView! 4 @IBOutlet weak var childrenView: UIVisualEffectView! 5 6 7 @IBAction func slide(_ sender: UISlider) { 8 print("slide") 9 } 10 11 override func viewDidLoad() { 12 super.viewDidLoad() 13 14 let tapGesture = UITapGestureRecognizer(target: self, action: #selector(dismissChildrenView)) 15 tapGesture.delegate = self 16 self.parentView.addGestureRecognizer(tapGesture) 17 18 // Do any additional setup after loading the view, typically from a nib. 19 } 20 21 override func didReceiveMemoryWarning() { 22 super.didReceiveMemoryWarning() 23 // Dispose of any resources that can be recreated. 24 } 25 26 func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool { 27 28 guard let targetView = touch.view else { 29 fatalError() 30 } 31 32 if targetView == parentView.contentView { 33 return true 34 } else { 35 return false 36 } 37 } 38 39 @objc func dismissChildrenView() { 40 print("dismissChildren") 41 } 42 43}

投稿2017/11/20 04:41

xAxis

総合スコア1349

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mitci

2017/11/21 12:46

スマートに完璧に、再現できました! まだ、どうしてそうなるのかの理屈の部分ではつまずいてはおりますが、とりあえずは使いたい使い方ができています。 が、しかし、それに際して別の問題が発生してしまったため、 新たに質問をさせていただきました。 https://teratail.com/questions/101464?modal=q-comp 無効化した子ビュー内のUISliderの挙動がどうにもおかしいのです・・・ UISliderのツマミをほんのすこし動かしただけでは、 タップされた->shouldRecieveで無効化 というのが先立ってしまい、UISliderのtouchUpInsideメソッドが呼ばれなくなってしまうのです・・・
xAxis

2017/11/21 13:34

どこでつまづいているのかにもよる気がしますが、 今回のコードのgestureRecognizerっていう関数の引数gestureRecognizerとかtouchってどのviewをtouchしたか取得出来ますよね。 んでUIVisualEffectViewってUITableViewCellみたいに内側にcontentViewを持ってて、そのcontentViewをタッチしてるかどうかっていうコードですかね。
mitci

2017/11/22 13:50

なぜなんでしょうね・・・ ツマミをタップした瞬間、touchDownメソッドは呼ばれますので(ValueChangedメソッドもちゃんと呼ばれているようですので)、それからわずかにツマミごと指ごと動かしても、「内側のcontentViewをタップした」という判断になるというのは微妙に違うような気もします・・・
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.49%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問