Make view draggable but not tappable
I have a label in my view controller that I set like this in viewDidLoad
:
var label: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
label = UILabel()
view.add(label)
label.frame = CGRect(x: 0, y, 0, width: 20, height: 20)
label.text = "A"
let recognizer = UIPanGestureRecognizer(target: self, action: #selector(didDrag(_:))
label.addGestureRecognizer(recognizer)
label.isUserInteractionEnabled = true
}
I want the label to be draggable, so I implemented didDrag
like this:
@objc func didDrag(_ gesture: UIPanGestureRecognizer) {
let center = label.center
let translation = gesture.translation(in: view)
label.center = CGPoint(x: center.x + translation.x, y: center.y + translation.y)
gesture.setTranslation(.zero, in: view)
}
It works perfectly and I can drag my label around.
However, if the label is over a button in my view and I try to tap the button, the button does not get the touch. I have tried:
label.isUserInteractionEnabled = false // then I can't also drag around
recognizer.cancelsTouchesInView = false // nothing changes
label.isMultipleTouchEnabled = false // nothing changes
Any idea how I can let single or double taps be passed/be ignored by the label's pan recognisers, but still be able to drag it?
I can delete this question if it's a duplicate, but I have not found any other that asks exactly the same.
Edit
Following Pass taps through a UIPanGestureRecognizer, the closest question I've found so far, I also tried:
recognizer.delaysTouchesBegan = true
recognizer.maximumNumberOfTouches = 1
recognizer.cancelsTouchesInView = true
But it, unfortunately, did not work.
Update
The view has all sorts of button and textfields, so comparing with each of them is not really possible, mostly because there are also stack views that contain buttons and sometimes they are there and somethings they are not.
ios swift uipangesturerecognizer
add a comment |
I have a label in my view controller that I set like this in viewDidLoad
:
var label: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
label = UILabel()
view.add(label)
label.frame = CGRect(x: 0, y, 0, width: 20, height: 20)
label.text = "A"
let recognizer = UIPanGestureRecognizer(target: self, action: #selector(didDrag(_:))
label.addGestureRecognizer(recognizer)
label.isUserInteractionEnabled = true
}
I want the label to be draggable, so I implemented didDrag
like this:
@objc func didDrag(_ gesture: UIPanGestureRecognizer) {
let center = label.center
let translation = gesture.translation(in: view)
label.center = CGPoint(x: center.x + translation.x, y: center.y + translation.y)
gesture.setTranslation(.zero, in: view)
}
It works perfectly and I can drag my label around.
However, if the label is over a button in my view and I try to tap the button, the button does not get the touch. I have tried:
label.isUserInteractionEnabled = false // then I can't also drag around
recognizer.cancelsTouchesInView = false // nothing changes
label.isMultipleTouchEnabled = false // nothing changes
Any idea how I can let single or double taps be passed/be ignored by the label's pan recognisers, but still be able to drag it?
I can delete this question if it's a duplicate, but I have not found any other that asks exactly the same.
Edit
Following Pass taps through a UIPanGestureRecognizer, the closest question I've found so far, I also tried:
recognizer.delaysTouchesBegan = true
recognizer.maximumNumberOfTouches = 1
recognizer.cancelsTouchesInView = true
But it, unfortunately, did not work.
Update
The view has all sorts of button and textfields, so comparing with each of them is not really possible, mostly because there are also stack views that contain buttons and sometimes they are there and somethings they are not.
ios swift uipangesturerecognizer
cancelsTouchesInView = true
is default behavior, try set it tofalse
– inokey
Nov 21 '18 at 15:32
Just triedrecognizer.cancelsTouchesInView = false
. Still nothing changes. Thanks, though.
– regina_fallangi
Nov 21 '18 at 15:39
add a comment |
I have a label in my view controller that I set like this in viewDidLoad
:
var label: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
label = UILabel()
view.add(label)
label.frame = CGRect(x: 0, y, 0, width: 20, height: 20)
label.text = "A"
let recognizer = UIPanGestureRecognizer(target: self, action: #selector(didDrag(_:))
label.addGestureRecognizer(recognizer)
label.isUserInteractionEnabled = true
}
I want the label to be draggable, so I implemented didDrag
like this:
@objc func didDrag(_ gesture: UIPanGestureRecognizer) {
let center = label.center
let translation = gesture.translation(in: view)
label.center = CGPoint(x: center.x + translation.x, y: center.y + translation.y)
gesture.setTranslation(.zero, in: view)
}
It works perfectly and I can drag my label around.
However, if the label is over a button in my view and I try to tap the button, the button does not get the touch. I have tried:
label.isUserInteractionEnabled = false // then I can't also drag around
recognizer.cancelsTouchesInView = false // nothing changes
label.isMultipleTouchEnabled = false // nothing changes
Any idea how I can let single or double taps be passed/be ignored by the label's pan recognisers, but still be able to drag it?
I can delete this question if it's a duplicate, but I have not found any other that asks exactly the same.
Edit
Following Pass taps through a UIPanGestureRecognizer, the closest question I've found so far, I also tried:
recognizer.delaysTouchesBegan = true
recognizer.maximumNumberOfTouches = 1
recognizer.cancelsTouchesInView = true
But it, unfortunately, did not work.
Update
The view has all sorts of button and textfields, so comparing with each of them is not really possible, mostly because there are also stack views that contain buttons and sometimes they are there and somethings they are not.
ios swift uipangesturerecognizer
I have a label in my view controller that I set like this in viewDidLoad
:
var label: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
label = UILabel()
view.add(label)
label.frame = CGRect(x: 0, y, 0, width: 20, height: 20)
label.text = "A"
let recognizer = UIPanGestureRecognizer(target: self, action: #selector(didDrag(_:))
label.addGestureRecognizer(recognizer)
label.isUserInteractionEnabled = true
}
I want the label to be draggable, so I implemented didDrag
like this:
@objc func didDrag(_ gesture: UIPanGestureRecognizer) {
let center = label.center
let translation = gesture.translation(in: view)
label.center = CGPoint(x: center.x + translation.x, y: center.y + translation.y)
gesture.setTranslation(.zero, in: view)
}
It works perfectly and I can drag my label around.
However, if the label is over a button in my view and I try to tap the button, the button does not get the touch. I have tried:
label.isUserInteractionEnabled = false // then I can't also drag around
recognizer.cancelsTouchesInView = false // nothing changes
label.isMultipleTouchEnabled = false // nothing changes
Any idea how I can let single or double taps be passed/be ignored by the label's pan recognisers, but still be able to drag it?
I can delete this question if it's a duplicate, but I have not found any other that asks exactly the same.
Edit
Following Pass taps through a UIPanGestureRecognizer, the closest question I've found so far, I also tried:
recognizer.delaysTouchesBegan = true
recognizer.maximumNumberOfTouches = 1
recognizer.cancelsTouchesInView = true
But it, unfortunately, did not work.
Update
The view has all sorts of button and textfields, so comparing with each of them is not really possible, mostly because there are also stack views that contain buttons and sometimes they are there and somethings they are not.
ios swift uipangesturerecognizer
ios swift uipangesturerecognizer
edited Nov 22 '18 at 10:36
regina_fallangi
asked Nov 21 '18 at 15:19
regina_fallangiregina_fallangi
911824
911824
cancelsTouchesInView = true
is default behavior, try set it tofalse
– inokey
Nov 21 '18 at 15:32
Just triedrecognizer.cancelsTouchesInView = false
. Still nothing changes. Thanks, though.
– regina_fallangi
Nov 21 '18 at 15:39
add a comment |
cancelsTouchesInView = true
is default behavior, try set it tofalse
– inokey
Nov 21 '18 at 15:32
Just triedrecognizer.cancelsTouchesInView = false
. Still nothing changes. Thanks, though.
– regina_fallangi
Nov 21 '18 at 15:39
cancelsTouchesInView = true
is default behavior, try set it to false
– inokey
Nov 21 '18 at 15:32
cancelsTouchesInView = true
is default behavior, try set it to false
– inokey
Nov 21 '18 at 15:32
Just tried
recognizer.cancelsTouchesInView = false
. Still nothing changes. Thanks, though.– regina_fallangi
Nov 21 '18 at 15:39
Just tried
recognizer.cancelsTouchesInView = false
. Still nothing changes. Thanks, though.– regina_fallangi
Nov 21 '18 at 15:39
add a comment |
1 Answer
1
active
oldest
votes
After thinking I came up with the solution that might work. The idea is playing around with touch events. Every view has a set of methods like touchesBegan()
, touchesMoved()
etc. Now what you can do is when touchesBegan is invoked you can check the location of the touch that is happening and if this location contained in the frame of the button, call the function manually.
Here's the pseudocode so you get the concept. Not tested but from my experience something like that should work
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
touches.forEach { touch in
let touchLocation = touch.location(in: myButton) // that may need to be self instead of myButton
if myButton.frame.contains($0.location) {
//invoke button method here
}
}
}
I have a lot of different buttons and textfields. I would have to compare with each subview, and each subview of every subview.
– regina_fallangi
Nov 21 '18 at 18:03
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53415202%2fmake-view-draggable-but-not-tappable%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
After thinking I came up with the solution that might work. The idea is playing around with touch events. Every view has a set of methods like touchesBegan()
, touchesMoved()
etc. Now what you can do is when touchesBegan is invoked you can check the location of the touch that is happening and if this location contained in the frame of the button, call the function manually.
Here's the pseudocode so you get the concept. Not tested but from my experience something like that should work
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
touches.forEach { touch in
let touchLocation = touch.location(in: myButton) // that may need to be self instead of myButton
if myButton.frame.contains($0.location) {
//invoke button method here
}
}
}
I have a lot of different buttons and textfields. I would have to compare with each subview, and each subview of every subview.
– regina_fallangi
Nov 21 '18 at 18:03
add a comment |
After thinking I came up with the solution that might work. The idea is playing around with touch events. Every view has a set of methods like touchesBegan()
, touchesMoved()
etc. Now what you can do is when touchesBegan is invoked you can check the location of the touch that is happening and if this location contained in the frame of the button, call the function manually.
Here's the pseudocode so you get the concept. Not tested but from my experience something like that should work
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
touches.forEach { touch in
let touchLocation = touch.location(in: myButton) // that may need to be self instead of myButton
if myButton.frame.contains($0.location) {
//invoke button method here
}
}
}
I have a lot of different buttons and textfields. I would have to compare with each subview, and each subview of every subview.
– regina_fallangi
Nov 21 '18 at 18:03
add a comment |
After thinking I came up with the solution that might work. The idea is playing around with touch events. Every view has a set of methods like touchesBegan()
, touchesMoved()
etc. Now what you can do is when touchesBegan is invoked you can check the location of the touch that is happening and if this location contained in the frame of the button, call the function manually.
Here's the pseudocode so you get the concept. Not tested but from my experience something like that should work
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
touches.forEach { touch in
let touchLocation = touch.location(in: myButton) // that may need to be self instead of myButton
if myButton.frame.contains($0.location) {
//invoke button method here
}
}
}
After thinking I came up with the solution that might work. The idea is playing around with touch events. Every view has a set of methods like touchesBegan()
, touchesMoved()
etc. Now what you can do is when touchesBegan is invoked you can check the location of the touch that is happening and if this location contained in the frame of the button, call the function manually.
Here's the pseudocode so you get the concept. Not tested but from my experience something like that should work
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
touches.forEach { touch in
let touchLocation = touch.location(in: myButton) // that may need to be self instead of myButton
if myButton.frame.contains($0.location) {
//invoke button method here
}
}
}
answered Nov 21 '18 at 17:57
inokeyinokey
1,105919
1,105919
I have a lot of different buttons and textfields. I would have to compare with each subview, and each subview of every subview.
– regina_fallangi
Nov 21 '18 at 18:03
add a comment |
I have a lot of different buttons and textfields. I would have to compare with each subview, and each subview of every subview.
– regina_fallangi
Nov 21 '18 at 18:03
I have a lot of different buttons and textfields. I would have to compare with each subview, and each subview of every subview.
– regina_fallangi
Nov 21 '18 at 18:03
I have a lot of different buttons and textfields. I would have to compare with each subview, and each subview of every subview.
– regina_fallangi
Nov 21 '18 at 18:03
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53415202%2fmake-view-draggable-but-not-tappable%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
cancelsTouchesInView = true
is default behavior, try set it tofalse
– inokey
Nov 21 '18 at 15:32
Just tried
recognizer.cancelsTouchesInView = false
. Still nothing changes. Thanks, though.– regina_fallangi
Nov 21 '18 at 15:39