How to Implement a Long Press Gesture for Xuni FlexGrid iOS
Recently, we had a request to add support for a long press gesture to the Xuni iOS FlexGrid. While there's nothing built into the control to handle this behavior at the moment, this got us thinking about ways of providing similar functionality to any UIView using existing tools. Apple makes it relatively easy to add new gestures to UIViews and anything deriving from them. We'll take a look at how you can use a UILongPressGestureRecognizer to add a long press gesture to a FlexGrid.
Adding a UILongPressGestureRecognizer
The UILongPressGestureRecognizer is a subclass of UIGesturerRecognizer that is specifically designed to handle a long press gesture. Any object deriving from a UIView (such as FlexGrid) should be able to add a gesture recognizer. To get started using it, first you need to implement the UIGestureRecognizerDelegate protocol for your ViewController.
@interface ViewController : UIViewController<UIGestureRecognizerDelegate>
Once the delegate is set up you can instantiate a new long press gesture. The are a few options for configuring this including the duration of press, the number of fingers that must be pressed on the view, and the amount of movement that's allowable before the gesture fails. You an also configure an action to occur when the gesture fires (which we'll get to in the next section):
UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handleLongPress:)];
longPress.numberOfTouchesRequired = 1;
longPress.minimumPressDuration = 1.0f;
longPress.allowableMovement = 10;
longPress.delegate = self;
[flex addGestureRecognizer:longPress];
Handling the Long Press
The method for handling the long press is pretty straightforward, but we'll need an interesting use case for it. FlexGrid has the ability to create a row details section, where extra information can be easily accessed for those who need it and hidden for those who don't. One interesting use of the long press gesture is to provide a "peeking" ability to the FlexGrid. In this case, a long press gesture will temporarily cause the row details section to expand when the gesture triggers, and contract once it ends. This will all be accomplished in our handleLongPress where we can capture the pressed point as a CGPoint, hit test the point against the FlexGrid to determine what element was pressed, and then use that info to show and hide the appropriate row detail section. One final note: the handleLongPress method will actually fire twice for each long press gesture. It fire on both the beginning state and the ending state of the gesture. We'll use this to show the detail section when the state begins and hide the row detail section when the state ends.
-(void)handleLongPress:(UILongPressGestureRecognizer*)sender{
CGPoint pressedPoint = [sender locationInView:flex];
FlexHitTestInfo *hit = [[FlexHitTestInfo alloc] initWithGrid:flex atPoint:pressedPoint];
if(sender.state == UIGestureRecognizerStateBegan){
[flex.detailProvider showDetail:[flex.rows objectAtIndex:hit.row]];
}
if(sender.state == UIGestureRecognizerStateEnded){
[flex.detailProvider hideDetail:[flex.rows objectAtIndex:hit.row]];
}
}
Once this is complete, you'll now have the ability to peek at the row details with a long press gesture:
Wrap Up
Adding a long press gesture to any other UIView should be similar to the process outlined above. In the future, we may consider adding more out-of-the-box support for this to the FlexGrid since it does have some interesting applications as we explored above. In the meantime, using a UIGestureRecognizer gives you some interesting options for expanding how users interact with your application.