Swift : How to open a link when tap on text in label? - ios

I want to add a link to some text. At the moment the text is in a UILabel. I want the link to be on the text so the user would not visually see the link. How can this be done?
In web development it looks like this.
Example 1

UILabel is not made for that, but you can link the text with an action (like tapping) in order to do whatever you like. Don't know about swift but in Objective-C is something like:
// If you have UILabel* myLabel
myLabel.userInteractionEnabled = YES;
UITapGestureRecognizer *gr = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(myAction:)];
[myLabel addGestureRecognizer:gr];
gr.numberOfTapsRequired = 1;
gr.cancelsTouchesInView = NO;
And then you can add the action:
- (void) myAction: (UITapGestureRecognizer *) gr {
// Code here
}
Maybe you can figure out how to do this in swift

You can also make a button look invisible. This could create the effect you are looking for.

Related

What is the best way to add UITapGestureRecognizer to a specific part of UILabel?

This question might have asked few times, but I'm still struggling to find best solution. addAttributes with NSMutableAttributedString won't work as I only can give a link to a part of the string.
I have a label with string "Already sign up? Login here". I can get NSRange of text "Login" but how can I give UITapGesture to it? I don't want to use 3rd party library here. Please suggest me some ideas. Thanks
You cannot add a gesture recognizer to a "part of a UILabel". For your case, I would just use two different UILabels: one that is not-tappable that says "Already signed up?", and one that is tappable that says "Sign in here". Honestly, I'd put the tappable part into a UIButton to make it clear. One more option would be to put an empty UIView as a subview of the UILabel, making it the size of the text you want to tap. Then add a gesture recognizer to THAT subview.
(In my opinion, one of the biggest traps developers get into when working with iOS is trying to force it to act differently than designed; like mimicking a web link or something. It always works best, and with a minimum of code, when written to take advantage of its design patterns)
All of the tap location nonsense can be ignored, because that is the point of a recognizer. The recognizer handles all of that for you, and will call your target with the action you set when the UIView is tapped.
So it would basically be:
UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:someObject action:#selector(someMethod:)];
[loginLabel addGestureRecognizer:tapRecognizer];
And that's it. The rest will be handled for you by the system. Your target object will be called when the label is tapped. At least, it seems simple from the problem as described in the original post. If there are other complications, please include those points in your question.
Gesture recognizers can't be added to specific parts of a UI component.
However, inside tap handler action, you might want to check
CGPoint tapLocation = [tapRecognizer locationInView:tapRecognizer.view];
You can check if the point lies in your targetRect
if(CGRectContainsPoint(myTargetRect, tapLocation))
{
// Do your action here
}
Hope it helps.
Update:
Here's the Objective-C version for getRect() from #Code 's answer as you needed.
-(CGRect)getRectForString:(NSAttributedString*)str withRange:(NSRange)textRange usingMaxWidth:(CGFloat)maxWidth
{
// Create a layoutManager
NSLayoutManager* layoutManager = [[NSLayoutManager alloc] init];
// Create a textContainer with maxWidth size and add it to layoutManager
NSTextContainer* textContainer = [[NSTextContainer alloc] initWithSize:CGSizeMake(maxWidth, CGFLOAT_MAX)];
[layoutManager addTextContainer:textContainer];
textContainer.lineFragmentPadding = 0;
// Create a textStorage with 'str' variable and add the layoutManager to this textStorage
NSTextStorage* textStorage = [[NSTextStorage alloc] initWithAttributedString:str];
[textStorage addLayoutManager:layoutManager];
// Query the actualGlyphRange from layoutManager for specified textRange
NSRange actualGlyphRange;
[layoutManager characterRangeForGlyphRange:textRange actualGlyphRange:&actualGlyphRange];
// Find out the boundingRect for actualGlyphRange
return [layoutManager boundingRectForGlyphRange:actualGlyphRange inTextContainer:textContainer];
}
You can't add tap gesture to a specific part of UILabel or if you tried to do so, you will stuck in finding frames and part of label that might help you at this point but it will be more problematic if it is inside some other view like UITableViewCell etc. It may require some calculation for point conversion with respect to parent/child view.
To keep it simple, my suggestion would be to create a UIView with a UILabel and UIButton embedded in it and button is set next to UILabel.
An example:
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
// Create label
UILabel *lbl = [[UILabel alloc] init];
[lbl setText:#"Already Sign up ? "];
[lbl sizeToFit];
// Create button
UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
[btn setTitle:#"Login Here" forState:UIControlStateNormal];
[btn addTarget:self action:#selector(didTapLink:) forControlEvents:UIControlEventTouchUpInside];
[btn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
[btn sizeToFit];
[btn setFrame:CGRectMake(lbl.frame.size.width, lbl.frame.origin.y, btn.frame.size.width, lbl.frame.size.height)];
// Create container that embeds the label and button
UIView *customLabel = [[UIView alloc] initWithFrame:CGRectMake(0, 50, lbl.frame.size.width + btn.frame.size.width, lbl.frame.size.height)];
[customLabel addSubview:lbl];
[customLabel addSubview:btn];
// Add this custom label to UI
[self.view addSubview:customLabel];
}
-(void)didTapLink:(id)sender
{
NSLog(#"Button tapped");
}
Screenshot:
Hope that helps!

How do I drag and drop a label to autocomplete textfield?

I want to drag and drop a label or something that will autocomplete the UITextfield. For example if I have an empty textfield and I drag a label with text "hello world" on top of the textfield, the textfield will have "hello world" as its text. Does anyone know how I can do this? Is a UILabel the best choice to use? or perhaps a UIButton could work?
You better read the tutorial first about IOS development. follow the tutorial
in this site http://www.appcoda.com/ios-programming-course/
For your question study the following link first then arise the questions
http://www.appcoda.com/hello-world-build-your-first-iphone-app/
http://www.appcoda.com/ios-programming-basic-how-does-the-hello-world-app-work/
Try this
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
//get position
// get label on that position
[label removeFromSuperView];
newLabel = [[UILabel alloc] init];
[self.view addSubView:newLabel]; //positioned at label
}
touchesMoved {
//getPosition
newLabel.position = position;
}
touchesEnded {
//getPosition.
self.view.subviews; // loop and find which view has the position.
UILabel *finalLabel = [[UILabel alloc] init];
finalLabel.center = newLabel.center;
[newLabel removeFromSuperView];
[viewToBeDroppedOn addSubview:finalLabel];
}
Also Check this tutorial Drag & Drop

UITapGestureRecognizer Not Getting Called

I am adding the following UITapGestureRecognizer to my view.
- (void)viewDidLoad {
_focusView = [[PBJFocusView alloc] initWithFrame:CGRectZero];
_focusTapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(_handleFocusTapGesterRecognizer:)];
_focusTapGestureRecognizer.delegate = self;
_focusTapGestureRecognizer.numberOfTapsRequired = 1;
_focusTapGestureRecognizer.enabled = NO;
[_previewView addGestureRecognizer:_focusTapGestureRecognizer];
}
- (void)_handleFocusTapGesterRecognizer:(UIGestureRecognizer *)gestureRecognizer {
NSLog(#"Focus");
}
_focusTapGestureRecognizer should be enable. Try this
_focusTapGestureRecognizer.enabled = YES;
OR
Remove this line
_focusTapGestureRecognizer.enabled = NO;
Try this inside your code
_focusView.userInteractionEnabled = YES;
May be helpfull...
_focusTapGestureRecognizer.enabled = NO;
Remove this line
To make this work check these three things as it is suggested by other guys i only writing them step by step
Check did you set the delegate of TapGesture in .h file.
Check on the UIView you are adding gesture its userInteractionEnabled is True.
Make that enable of UITapGesture Yes .//Why it is no ?
Fourth is , did you gave any size to the UIView , for checking that add some background color to it,see is it visible or not .
if these 4 doesnot help you out type your code what you used it .
You might also want to check that you're not trying to reuse the UITapGestureRecognizer object for different views.
It seems like you can because you add the gesture to the view, but in ultimately the view needs to be assigned to the view property on the gesture object so adding the gesture object to a second view will just overwrite the first.

Come back to app from an other app

Hello,
When we are phoning with us iphone and you left the call view to come back at springboard, we can come back to the call view with the status bar. (This picture can better explain : http://what-when-how.com/wp-content/uploads/2011/08/tmpB178_thumb.jpg)
Or, in the Facebook app when you go to the messenger Facebook app (not same app) we can touch status bar to comme back Facebook App too.
I would like to know if it's possible to make it in my app ? And if it's possible, how I will proceed ? (Edit: I want co come back in my app from another app such Youtube.)
Thanks
Once you become familiar with how to open another app within your current app form following link:
http://iosdevelopertips.com/cocoa/launching-your-own-application-via-a-custom-url-scheme.html
You can simply create a view that has tap gesture and use it as a button
- (void)viewDidLoad
{
[super viewDidLoad];
[self.navigationController setNavigationBarHidden:YES];
UIView *tapToReturnButton = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 40)];
tapToReturnButton.backgroundColor = [UIColor blueColor];
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self
action:#selector(tapToReturnButtonClicked)];
[tap setNumberOfTouchesRequired:1];
[tapToReturnButton addGestureRecognizer:tap];
UILabel *tapToReturnLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 20, self.view.frame.size.width, 20)];
tapToReturnLabel.text = #"Tap to return";
tapToReturnLabel.textColor = [UIColor whiteColor];
tapToReturnLabel.textAlignment = NSTextAlignmentCenter;
tapToReturnLabel.font = [UIFont fontWithName:#"ArialMT"
size:14];
[tapToReturnButton addSubview:tapToReturnLabel];
[self.view addSubview:tapToReturnButton];
}
- (void)tapToReturnButtonClicked
{
NSLog(#"Now you add your code that opens another app(URL) here");
}
Edited:
After I posted the code above I kind of realized that there will be no tap gesture on the status bar even though other bottom part (20 pixel) of tapToReturnButton has a click gesture. After I did some research, I think following link has the better solution on click gesture. I will probably use tapToReturnButton as placeholder to let users know where to touch though and remove UITapGestureRecognizer *tap.
How to detect touches in status bar
Again, I think there is multiple way to achieve your need but those links above will give you good starting point.
URL schemes will allow you to launch an app from an another app.
Check the following links for more info:
https://developer.apple.com/library/ios/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/AdvancedAppTricks/AdvancedAppTricks.html#//apple_ref/doc/uid/TP40007072-CH7-SW18
https://developer.apple.com/library/ios/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/AdvancedAppTricks/AdvancedAppTricks.html#//apple_ref/doc/uid/TP40007072-CH7-SW50
here are some system supported URL schemes
https://developer.apple.com/library/ios/featuredarticles/iPhoneURLScheme_Reference/Introduction/Introduction.html#//apple_ref/doc/uid/TP40007899

Make only part of a sentence a link (add selector)

so I am trying to implement the following. I have a view, which has a sentence. Only part of the sentence links to another view. This is what it looks like:
I am a cat. Learn More
The Learn More would be a link (blue in color), which when clicked would open another view.
Currently I am using a UILabel to write "I am a cat". I realize that the best way to add selectors is to use a button, so "Learn More" should be a button?
Is there any way to write this sentence out without using two different UIComponents?
If not, then how do I make the UILabel and the UIButton completely horizontally aligned with each other?
The following is my code for the label in -layoutSubviews:
CGSize labelSize = [_label.text sizeWithFont:_label.font constrainedToSize:bounds.size lineBreakMode:_label.lineBreakMode];
_label.frame = CGRectMake(0, 0, bounds.size.width - kMarginForText, labelSize.height);
_label.center = CGPointMake(horizontalCenter, CGRectGetMaxY(_previousLabel.frame) + kDistanceBetweenPreviousAndCurrentLabel);
And the code for the label itself.
_label = [[UILabel alloc] initWithFrame:CGRectZero];
_label.text = "I am a cat";
_label.font = [UIFont systemFontOfSize:14];
_label.textAlignment = NSTextAlignmentCenter;
_label.numberOfLines = 0;
_label.lineBreakMode = UILineBreakModeWordWrap;
[self addSubview:_label];
Any help would be appreciated!
To answer your question about a single UIComponent, you could use a UILabel in conjunction with a UITapGestureRecognizer to create the intended effect. Granted this would make the whole label tappable... but having a bigger tap target area is almost never a bad thing.
In particular you would use an NSAttributedString to set the label text (NSAttributedString change color at end of string):
UILabel *label = [[UILabel alloc] init];
//Use initwithframe or setup your constraints after initialization here
label.attributedText = (your nsattributed string here)
Then to initialize the tap recognizer onto the UILabel you would do something like this:
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(userDidTapLearnMore)];
label.userInteractionEnabled = YES;
[label addGestureRecognizer:tap];
What you want to do is to align them by their baselines, which you can easily do in Interface Builder by selecting them and choosing Editor > Align > Baselines, as shown in this illustration:

Resources