I'm creating a view where its subviews can be re-arranged with drag and drop, after activating the "edition mode" via a long tap.
I use for that two gesture reconizer a UILongPressGestureRecognizer and a UIPanGestureRecognizer.
Everything works great, but i wanna be able to start dragging my subviews without having to tap again on my view (like when you re-arrange your icon on the springboard).
Is there any way to do such a thing ?
EDIT :
I've tried :
func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWithGestureRecognizer otherGestureRecognizer: UIGestureRecognizer) -> Bool {
var res = false
if ((gestureRecognizer == longTapGesture && otherGestureRecognizer == panGesture) || (gestureRecognizer == panGesture && otherGestureRecognizer == panGesture)) {
res = true
println("š·")
}
return true
}
without success.
First of all those 2 gesture recognizers should work nicely together. Normally one of them would cancel the other one. To prevent that you can use UIGestureRecognizerDelegate method gestureRecognizer: shouldRecognizeSimultaneouslyWithGestureRecognizer: and return YES for both recognizers.
After that you need to have a boolean property to lock your pan effect before long press occurs. UILongPressGestureRecognizer target method should only perform something if this property is set to YES. Remember to set this property to NO, when pan gesture finishes/resets.
Related
In my iOS app I have an instance of an MKMapView and on single tap, I want to add a marker to the map. I've added a UITapGestureRecognizer and immediately noticed that it would fire even when a user double taps to zoom (or other interactions with the map).
I've implemented the UIGestureRecognizerDelegate method like this and this works, but makes the interaction very sluggish, because it obviously waits for the other gesture recognizers to fail.
func gestureRecognizer(
_ gestureRecognizer: UIGestureRecognizer,
shouldRequireFailureOf otherGestureRecognizer: UIGestureRecognizer
) -> Bool {
guard gestureRecognizer == self.mapGestureRecognizer else {
return false
}
return !(otherGestureRecognizer is UITapGestureRecognizer) && otherGestureRecognizer.state == .possible
}
Is there any way to act quickly on a tap, without breaking the native gestures on the map view?
Not sure there is a direct solution to this as the mapView can't know if your tap is part of another gesture until it's waited to check. My usual workaround for this is to use a long tap for adding markers to the map as this is a discrete event
I'm using a UIView with a UITapGestureRecognizer.
On the other hand I have a tap recognizer on ViewController's container view,
Now when i tap on my inner view, it calls handler,
BUT when I tap on for example 40 upper points of it, it doesn't work and container's tap recognizer fires!!!, actually i'm sure it's inside the UIView, i'm sure as I changed it's background to a different color, and on the other hand, there isn't any other views on this view, too!
It's really annoying, i've tested everything, hiding all views, disabling other recognizers and so on! And it's not my first time using this U I TAP RECOGNIZER :///
view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(viewController.dismissKeyboard(_:))))
viewWrite.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(viewController.viewPressed(_:))))
EDIT::
I found that even when i touch here on my UITextView, the main container's tap event loads!! but other points of view, no! ::
You can try implementing UIGestureRecognizerDelegate
eg.
func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldReceiveTouch touch: UITouch) -> Bool {
if (gestureRecognizer == recoginiser1 && wrongview1) return false
if (gestureRecognizer == recoginiser2 && wrongview2) return false
else return true;
}
wrongview means something like this.
func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldReceiveTouch touch: UITouch) -> Bool {
if (gestureRecognizer == recognizer1){
let point = touch.locationInView(self.view)
if CGRectContainsPoint(textView.frame, point) == true {
return false
}
}
return true
}
I am a beginner in Swift, and am trying to add a swipe gesture recognizer to my UIView. I have inserted a gradient CALayer to index 0 to have a gradient background.
My problem is:
Swipe gestures for right and left work fine, but for Down it doesn't work, why?
Set the delegate of swipe gestures that you are adding to the view.
let swipeGesture = UISwipeGestureRecognizer(target: self, action: Selector("handleSwipe:"))
swipeGesture.delegate = self
self.view.addGestureRecognizer(swipeGesture)
self.mySwipeGesture = swipeGesture
GestureRecognizerDelegate asks if two gesture recognizers should be allowed to recognize gestures simultaneously. Return true to allow both gestureRecognizer and otherGestureRecognizer to recognize their gestures simultaneously. The default implementation returns falseāno two gestures can be recognized simultaneously. Implement the following delegate to achieve this.
extension ViewController : UIGestureRecognizerDelegate {
func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWithGestureRecognizer otherGestureRecognizer: UIGestureRecognizer) -> Bool {
//Identify gesture recognizer and return true else false.
return gestureRecognizer.isEqual(self.mySwipeGesture) ? true : false
}
}
Swiping Up & Down are the default property of table view. I would suggest you to disable the scrolling of the table view whenever you want to do something on the overlay.
tableView.scrollEnabled = NO;
If you are performing dragging of a particular cell then long press on it and then start dragging.
This is how you can achieve this.
Hope this helps.
I have a collection view of bars that can slide up and down. Each cell in the collection view is using a UIPanGestureRecognizer to control the blue bar sliding up and down. The collection view does not scroll here.
There is an "edit mode" which disables the pan gesture controlling the bars. The hope here is that in "edit mode", the collection view can then scroll left and right.
My attempt at doing this was to disabled the pan gesture in each of the cells. I also tried using the UIGestureRecognizerDelegate methods to try to disable touches and fail the cell's pan gesture in favor of the collection view's pan gesture. It seems that the collection view's pan gesture is not forwarded to any of the cell's gesture delegate calls.
These delegate calls got me the closest (delegate for cell's pan gesture):
func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWithGestureRecognizer otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return true
}
func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldReceiveTouch touch: UITouch) -> Bool {
return !self.editMode // bar doesn't need to pan in edit mode
}
With this implemented, I could pan the collection view if I started the pan in the white space between cells. Starting a pan on a cell would not do anything, though.
EDIT: I uploaded a sample project of the issue to github.
If I understand this correctly, I think the problem could be as follows:
Your UICollectionView will listen for pan gestures. So far so good.
In KBHBarSlider you add UIPanGestureRecognizer for you sliders. They have "priority" over the underlaying UICollectionView.
This actually makes sense as your BarSliders are above the CollectionView. My best take would be to let the BarSliders add the UIPanGestureRecognizer when needed, and have them completely removed when editing.
So first try and remove the gestureRecognizer you added in VOLBarSliderCell.
Then in KBHBarSlider add something like: (and make sure your init calls addPanRecognizer() instead of setup())
func addPanRecognizer() {
let panGesture = UIPanGestureRecognizer(target: self, action: "viewDidPan:")
self.gestureRecognizers = [panGesture]
}
func removePanRecognizer() {
self.gestureRecognizers = []
}
It is now possible to add and remove the gestures on demand, do so from your edit get/set overrides in VOLBarSliderCell:
var editing: Bool = false {
didSet {
if !self.editing {
self.barSlider.addPanRecognizer()
// Removed code, to keep this example short...
} else {
self.barSlider.removePanRecognizer()
// Removed code, to keep this example short...
}
}
}
Try adding this code at VOLBarSliderCell:29:
self.panGesture.enabled = !self.editing
And remove:
func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWithGestureRecognizer otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return true
}
func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldReceiveTouch touch: UITouch) -> Bool {
if self.editing && gestureRecognizer == self.panGesture {
return false
}
return true
}
To be fair your problem was not clear to me, so I gave a try as an answer anyway since I cannot comment yet to request clarifications.
I understood you wanna scroll your UICollectionView while you are in edit mode. So that's what the code above does. If you wish to disable scrolling altogether UICollectionView while NOT editing then you can use scrollEnabled = false on the UICollectionView.
Clarify a bit better what is the problem you are trying to solve. That way you might be able to bring precise answers.
You're on the right track. Keep a reference to your leftRight gestureRecognizer. Then in shouldReceiveTouch, check if editing and the gestureRecognizer is your leftRight recognizer
func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldReceiveTouch touch: UITouch) -> Bool {
if(self.editing && gestureRecognizer != self.leftRightRecognizer){
return 0;
}
return 1;
}
My app has a table view (with a scroll-into of course) and this view slides on and off with a gesture recognizer (like on the Facebook app).
If I use a button to slide [the table view onto the screen], it works fine but when I use a gesture recognizer, the table view can't be scrolled anymore.
Here is the code of gesture recognizer with the problem:
[self.view addGestureRecognizer:self.slidingViewController.panGesture];
Somebody have an idea?
Your gesture is probably preventing the scroll view gesture from working because by default only 1 gesture can be recognising at a time. Try adding yourself as the delegate of your gesture and implementing:
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
return YES;
}
self.slidingViewController.panGesture.delegate = self;
also, add <UIGestureRecognizerDelegate> to the list of protocols you implement
I have used UIPangesture in my UItableview and to avoid this gesture I have used below delegate,
//This method helped me stopped up/down pangesture of UITableviewCell and allow only vertical scroll
override func gestureRecognizerShouldBegin(gestureRecognizer: UIGestureRecognizer) -> Bool {
if let panGestureRecognizer = gestureRecognizer as? UIPanGestureRecognizer {
let translation = panGestureRecognizer.translationInView(superview)
if fabs(translation.x) > fabs(translation.y) {
return true
}
return false
}
return false
}
Here is the swift version:
func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWithGestureRecognizer otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return true
}
I had same issue of defining long press gesture on table view and not being able to scroll table when I long press on it.
Fixed by:
1- adding
UIGestureRecognizerDelegate
2- adding
gesture.delegate = self (after you defined the long press gesture)
3- adding this function:
func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWithGestureRecognizer otherGestureRecognizer: UIGestureRecognizer) -> Bool {return true}
If I get it right the view that you're adding the gesture recognizer to is the table view. By default the UIScrollView (and implicitly UITableView) class uses the pan gesture recognizer for the scroll and your gesture recognizer interferes with that. If you use another view as a container for the table view and you're adding the pan gesture recognizer to it should work.