iOS: Calling Pan Gesture attached to a UIButton programmatically - ios

When a user highlights a button in my horizontal scrollView, an identical looking button (Different draggable subclass) is added right above. What I'm trying to achieve is similar to lifting a card off a stack like Solitaire, and having another card underneath it.
Everything is working except that right now the moment the user highlights, the touch get's canceled as the new view come's into place. The user has to lift their finger off and tap again to register that the dragging event has begin. What I want to do is to automatically pass the touch from the first button to the newly added button without the user having to remove their finger again and touching the new button. I'm not even sure if this is possible.
Maybe I'm thinking about this the wrong way, but the reason I don't make the first button the draggable button is because I reuse it in my horizontal scrollView.

Which I feel you should consider each card as a custom UIView and handle
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event;
- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event;
- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event;
to show selection, dragging and finally placing of a card. So all logic for selection and put card would in one custom UIView class. For all other validation do that in your parent UIViewController

Related

UITableView touch position or several gestures at a time

I have UITableView, and added the ability for moving cells.
http://s017.radikal.ru/i402/1503/76/3442a9517cec.png
So, if longPressGesture is recognized, i make the cell hidden, take a snapshot of cell(on picture highlighted with grey), and change it's position while longPressGestureStateChanged. But the animation of moving looks bad.
If I add panGesture while longPressGestureBegan, it doesn't work until I touch up and touch down again, and after that panGestureStateChanged begin working, and moving become smooth.
I need panGesture begin working while longPressGestureBegan, or catch the screen touch position.
But the difficulty is: (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event; etc... doesn't work on UITableView.
I read a lot, but nothing was founded. This is the custom case. I need for example to recognize pinchGesture only when longPressGesture was recognized, without touching up.
Anybody know how to solve this?
For UITableView use ready methods to move cells. You can find more information in the documentation.

Subclassing UIControl's endTracking for multitouch

I'm creating a custom control* by subclassing UIControl and overriding the following methods:
- beginTrackingWithTouch:withEvent:
- continueTrackingWithTouch:withEvent:
- endTrackingWithTouch:withEvent:
- cancelTrackingWithEvent:
This control will support multitouch interaction. Specifically, one or two fingers may touch down, drag for some duration, and then touch up, all independently.
My issue comes at the end of these multitouch events, in endTrackingWithTouch:withEvent:. The system calls this method on my control exactly once per multitouch sequence, and it is called on the first touch up that occurs. This means that the second touch, which could still be dragging, will no longer be tracked.
This sequence of actions serves as an example for this phenomenon:
Finger A touches down. beginTracking is called.
Finger A drags around. continueTracking is called repeatedly to update my control.
Finger B touches down. beginTracking is called.
Fingers A and B drag around. continueTracking is called repeatedly to update my control.
Finger B touches up. endTracking is called.
Finger A drags around. No methods are called.
Finger A touches up. No methods are called.
The issue lies in the final three steps in this sequence. The documentation for UIControl says the following of endTrackingWithTouch:withEvent::
Sent to the control when the last touch for the given event completely ends, telling it to stop tracking.
Yet it seems to me that after finger B touches up in step 5, above, the last touch for the given event has not yet completely ended. That last touch is finger A!
*A range slider, if you must ask. But there are already plenty of open source range sliders, you say. Yes, true, but this one will support multitouch and Auto Layout.
I had the same issue in custom control with multitouch.
Because UIControl is subclass of UIView that inherits from UIResponder, so feel free to use:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event;
methods.
These methods work fine in UIControl subclass.

iOS - View that handle taps, but let swipes go through to the superview

I have an app with quite a complex UI, there's a big UIView called the cover with a UITableView underneath it. The tableView is configured with a tableHeaderView of the same height as the cover. As the tableView scrolls up, the cover moves up the screen (with various fancy animations) using a UIScrollViewDelegate. To allow users to scroll the tableView by swiping the cover, I've overridden the - (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event method to always return false.
I've now added some UIButton views to the cover. I've managed to make them respond to taps by changing the way I've overriden the pointInside method like this:
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
{
BOOL isInside = [_directionsButton pointInside:[_directionsButton convertPoint:point fromView:self] withEvent:event];
return isInside;
}
The only problem now is that if you start a swipe gesture on the button, it's caught by the button and the tableView doesn't scroll. I want to be able to ignore swipe gestures on the button (so really let them pass to the view below).
Normally, I would just make the cover view the tableHeaderView, which seems to handle this kind of behaviour really well. However, I can't do this here, due to some unique animations done on the cover as the table scrolls.
Did you tried identifying the Gestures using Gesture Recognisers and doing action method that is to be called when the specified gesture is detected?
Please check this link. This may help you for that.

UISegmentedControl: how to detect click on current segment?

is there a way to detect second click on a segment in UISegmentedControl? I found:
Detect second click on a segment
however, it is stated that:
If you set a segmented control to have a momentary style, a segment doesn’t show itself as selected (blue background) when the user touches it. The disclosure button is always momentary and doesn’t affect the actual selection.
Is there a way to detect second click as well as trigger the selection action and show the segment as selected?
If there is no straight forward way to do it, what I was thinking, is that I first have the momentary flag set to YES, then upon each click, manually update the selection state, but then I also need to update/deselect other segments.
Thanks
The solution is to have a custom subclass of UISegmentedControl and check it yourself like this.
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
current = self.selectedSegmentIndex;
[super touchesBegan:touches withEvent:event];
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
[super touchesEnded:touches withEvent:event];
if (current == self.selectedSegmentIndex)
[self sendActionsForControlEvents:UIControlEventValueChanged];
}
I had an other solution all in touchesBegan, but it's not working anymore in iOS 7. There is also other solution on Stack Overflow that are not working in iOS 6 and greater.
To make a particular segment click-able again is not possible, but you can reset the whole segmentControl using UISegmentedControlNoSegment.
[self.segmentCtrlOutlet setSelectedSegmentIndex:UISegmentedControlNoSegment];
what you have to do is put the above code in the place where that code executes when you click on a particular segment of UISegmentedControl.
for eg. In my project when I click on a segment, UIPopoverController opens up and inside it I have UIPicker, so I use the above code in UIPicker delegate method "didSelectRow"

touchesBegan: withEvent: is not called when tapped on a UIButton

What I want to implement is column matching type functionality. I have three buttons on right column and three on left column with some info on them. I want to draw path from one button on right side to any of the button on left side by dragging finger.
I would use UIBezierPath path to draw path, and for that definitely a start and end point is needed.
Now the issue is how can I trigger touchesBegan, touchesMoved and touchesEnded methods by tapping on buttons so that I can get start and end points.
Another option that I am thinking about is to cover all the buttons with an invisible UIView, and somehow check if the point touched of this overlay view lies in any of the button frames.
BTW I can replace these buttons with simple UIImageView as well. I added buttons just for the sake of getting touch points.
Any help.
Create a subclass of UIButton and add this...
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[super touchesBegan:touches withEvent:event];
[self.nextResponder touchesBegan:touches withEvent:event];
}
This will get you your touches within the button.
Uncheck User Interaction Enabled checkbox of UIButton. You will get call for touchesbegan method on that button.

Resources