I am using Slack Text View Controller https://github.com/slackhq/SlackTextViewController inside essentially a scroll view and its not liking it. I'm using this library https://github.com/maxep/MXSegmentedPager which handles vanilla collection and table view controllers fine but not the Slack one.
so slack is the child, and segmentedPager is the parent controller.
I have textView.delegate = self and set
func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWithGestureRecognizer otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return true
}
method to true in both child and parent or one or the other to no avail. Not sure if this is an issue or if I am doing it wrong, any ideas? Specifically after scrolling down it wont scroll back up
Related
I have a UIView within a UIScrollView. I want the view to do something when a tap on it begins, and do something different when the tap ends. Therefor I used a UILongPressGestureRecognizer. I set the minimumPressDuration to zero. This works fine, but my problem is that I can't use the scroll view properly anymore because every touch within the view now fires the gesture recognizer.
Has anyone an idea how to solve this?
Can I tell the LongPressGestureRecognizer not to react on swipe gestures?
Have you tried setting:
let gesture = UILongPressGestureRecognizer()
gesture.cancelsTouchesInView = false
Also try using a UILongPressGestureRecogniser with:
extension ViewController: UIGestureRecognizerDelegate {
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return true
}
}
Where ViewController is the delegate of your gesture recogniser.
I have the following setup.
A main view controller (MainViewController) contains another view controller (ListViewController) in a parent-child view controllers configuration.
The ListVC starts somewhere along the bottom of the MainVC. The ListVC contains UIView at the top and a table view at the bottom. The table view has a pan gesture recogniser attached to it.
What I wanted to achieve is as I pull the ListVC upwards via the pan gesture, it goes up towards the top of the screen. When it reaches the top (or to be more precisely, some distance below the top layout guide), the listVC stops moving in mainVC and the table view starts scrolling. It's almost like the I've transferred control from the pan gesture to the table view's gestures.
The way I'm doing this now is implementing the UIGestureRecognizerDelegate protocol.
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return true
}
and
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldBeRequiredToFailBy otherGestureRecognizer: UIGestureRecognizer) -> Bool {
if gestureRecognizer == pullGesture {
return pullGestureIsPriority
}
return false
}
and
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRequireFailureOf otherGestureRecognizer: UIGestureRecognizer) -> Bool {
if gestureRecognizer == pullGesture {
return !pullGestureIsPriority
}
return false
}
pullGesutre is a priority if the listVC hasn't reached the top. And I fail the pullGesture by setting self.pullGesture.isEnabled = false followed immediately by self.pullGesture.isEnabled = true.
Now it all works fine; I was able to pull it up without the table view scrolling up, when listVC reaches the top, I fail the pull gesture, so table view starts scrolling up. The problem came when I scrolled the table view down until the top of the table view was reached, at which point, I'd hoped that the listVC would come down via the pull gesture. But this wasn't happening. Somehow, the pullGesture has been removed from the chain of touch events.
Anybody has an idea how I could achieve this?
Note, effectively I'm trying to replicate how Apple does to their Map in iOS 10. I've also attached a little gif to demonstrate what I meant.
demo image
A demo project can be found here.
demo project
If what you are looking to do is send an "event" or "action" between two view controllers, you can use a sendAction.
(1) Add a UIButton, set the frame to CGRect.zero, add it to you ListVC.
(2) In your ListVC code where you want to contact the MainVC, add this line:
myButton.sendAction(Selector(("tapFound")), to: nil, for: nil)
(3) In your MainVC, add this function:
func tapFound() {
}
I've done this before in a few apps to tell a main VC to add something a new subview. You can even pass the sender (which a UITapRecognizer isn't) to a new view controller, with the tag property set to have the VC know exactly what is needed.
I solved this by adding this in my pan gesture function
guard scrollView.contentOffset.y == 0 else{return}
so whenever it reaches the top(scrollview) it will start panning down
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;
}
I'm trying to use a UIPageViewController for standard pagination with the Scroll transition style while having an gestures starting from the edge trigger a different action. Currently I'm trying to do this with a UIScreenEdgePanGestureRecognizer. However, no matter what I do, the UIPageViewController's gesture recognizer overrides the UIScreenEdgePanGestureRecognizer, which never gets activated. Any ideas?
To get multiple gesture recognizers to work simultaneously you have to indicate that by overriding shouldRecognizeSimultaneouslyWithGestureRecognizer from the UIGestureRecognizerProtocol:
func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWithGestureRecognizer otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return true
}
This example returns true for all gesture recognizers, you can limit/configure the behaviour with the passed parameters.
I've got, in a UIScrollview, multiple custom subviews which inherit from UIView and which are draggable. Everything works fine with it except that i'm able to drag two or more subviews at the same time. The gesture recognizer are attached to my custom subviews and implemented inside this class.
Is there any way to prevent this behavior ?
EDIT : I've already tried to add in the delegate
func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWithGestureRecognizer otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return false
}
But it's not working since all the subviews handle themselves their own gesture recognizer.
The GestureRecognizerDelegate protocol has a function to specify whether multiple gesture recognizers can act simultaneously. I don't know if that works in your case but it is worth a try:
func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWithGestureRecognizer otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return false
}
I know it is an old question but I came across the same problem where I want only one item to be draggable at same time. You can loop through all your draggable subviews and update their properties as below.
subiew.isExclusiveTouch = true
subview.isMultipleTouchEnabled = false
Now only one subview will be draggable at same time.