Monday, April 18, 2016

Disable Swipe gesture in Selected views of UIPageViewController

I used UIPageViewController for the seamless navigation of tabs through swipe gestures.Since UIPageViewController seems good for swipe gesture navigation i used this controller through out the application.

It works like a charm until i got a need to implement a custom slider inside a view of UIPageViewController.


Design of the screen is as below:




Problem was when i intend to swipe the play field slider either forward or backward,the entire screen moves,page controller eats the swipe gesture and thinks it has to navigate to next screen or previous screen.But my intention was i would like to forward the song for a few seconds or reverse for few seconds.


I tried to solve this problem by many methods.Every attempts failed but one simple and efficient solution worked wonders to me.


I created one Pan Gesture Recognizer with no handle method and added to the Slider view initially.And set CancelsTouchesInView to false.


Code snippet in Xamarin


            UIPanGestureRecognizer panGesture=new        UIPanGestureRecognizer();
            panGesture.CancelsTouchesInView=false;

            PlayfieldSlider.AddGestureRecognizer(panGesture);
           PlayfieldSlider.thumbButton.AddGestureRecognizer(panGesture);

I added the pan gesture only to the thumb portion of slider.Thumb is the one which has play/pause button on the slider of any music player.Idea is when user holds thumb and drags along the slider the page controller does not react whereas if user slides anywhere even on the slider area also makes the page to move to another screen.


Explanation


Referhttp://stackoverflow.com/questions/13042632/what-really-happens-when-call-setcancelstouchesinview

suppose you have a view with a pan gesture recognizer attached, and you have these methods in your view controller:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    NSLog(@"touchesBegan");
}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
    NSLog(@"touchesMoved");
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
    NSLog(@"touchesEnded");
}

- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
    NSLog(@"touchesCancelled");
}

- (IBAction)panGestureRecognizerDidUpdate:(UIPanGestureRecognizer *)sender {
    NSLog(@"panGesture");
}
And of course the pan gesture recognizer is configured to send the panGestureRecognizerDidUpdate: message.
Now suppose you touch the view, move your finger enough for the pan gesture to be recognized, and then lift your finger. What does the app print?
If the gesture recognizer has cancelsTouchesInView set to YES, the app will log these messages:
touchesBegan
touchesMoved
touchesCancelled
panGesture
panGesture
(etc.)
You might get more than one touchesMoved before the cancel.
So, if you set cancelsTouchesInView to YES (the default), the system will cancel the touch before it sends the first message from the gesture recognizer, and you won't get any more touch-related messages for that touch.
If the gesture recognizer has cancelsTouchesInView set to NO, the app will log these messages:
touchesBegan
touchesMoved
panGesture
touchesMoved
panGesture
touchesMoved
panGesture
(etc.)
panGesture
touchesEnded
So, if you set cancelsTouchesInView to NO, the system will continue sending touch-related messages for the gesture touch, interleaved with the gesture recognizer's messages. The touch will end normally instead of being cancelled (unless the system cancels the touch for some other reason, like the home button being pressed during the touch).

Tuesday, April 12, 2016

Find out if earphones are plugged in or not

There may be usecase where you need to check whether head phones are plugged in or not before delving into other functionality.

Here is a way to achieve that.

1.Import AVFoundation framework.

2.Include AVFoundation header file in the place where you need to check whether head phone is plugged in or not.

3.Use the below method

-(BOOL)isHeadPhonePlugged
{
    AVAudioSessionRouteDescription *route=[[AVAudioSession sharedInstance]currentRoute];
    for (AVAudioSessionPortDescription *port in [route outputs]) {

        if ([[port portType]isEqualToString:AVAudioSessionPortHeadphones]) {
            return YES;
        }
        
    }
    return NO;


}

Monday, April 11, 2016

Making hyperlinks in UITextView to respond instantly

Ever wondered why hyperlinks in UITextView responds only when you touch and hold for a few seconds,whereas hyperlink in web view works much faster.

I assume its designed in that way.Am sure you have checked those initial set ups like   textview.selectable=yes.

I solved it through help from stack overflow post http://stackoverflow.com/questions/22379595/uitextview-link-tap-recognition-is-delayed 

Solution:

1.Add a Tap gesture to UITextview.

UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tappedTextView:)];
[myTextView addGestureRecognizer:tapRecognizer];

2.In the handle method get the touch position


    CGPoint tapLocation = [tapGesture locationInView:textView];

 and get the Attributes of the text whose points closest to the touch
    UITextPosition *textPosition = [textView closestPositionToPoint:tapLocation];
    NSDictionary *attributes = [textView textStylingAtPosition:textPosition inDirection:UITextStorageDirectionForward];

3.Get URL from the attributes and open the url if its not null

    NSURL *url = attributes[NSLinkAttributeName];

    if (url) {
        [[UIApplication sharedApplication] openURL:url];
    }