How to make a UILabel clickable?
Have you tried to set isUserInteractionEnabled
to true
on the tripDetails
label? This should work.
How can I make a clickable UILabel in Swift 3?
Problem is with your Label memory allocation. You have created IBOutlet
of label but not connected it with Interface from your Storyboard/XIB view controller.
Go to your Interface Builder: (Storyboard/XIB) View Controller ▶ Select 'Connection Inspector' ▶ Connect label outlet 'back' with Label interface element
How to customize UILabel clickable
The most simple way is to just add a gesture recognizer to the actual view (be it a UILabel or some custom view of your own). In order for the gesture recognizer to work, the view must be set userInteractionEnabled.
Here's an example, assuming that your label view (or whatever it is) is called labelView:
UITapGestureRecognizer* gesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(userTappedOnLink:)];
// if labelView is not set userInteractionEnabled, you must do so
[labelView setUserInteractionEnabled:YES];
[labelView addGestureRecognizer:gesture];
In this example, an action message will be sent to self
and the message would be defined as
- (void)userTappedOnLink:(UIGestureRecognizer*)gestureRecognizer;
This works the same as wiring up any other UIControl subclass, such as a button.
Other notes: don't try to add the same gesture recognizer to multiple views, it won't work. Don't add more than one copy of the gesture recognizer to multiple views (it doesn't replace them, it just stacks them up and wastes memory). You should add the gesture recognizer when you initially create and configure your view.
For more information, see the documentation for UIGestureRecognizer.
Create tap-able links in the NSAttributedString of a UILabel?
In general, if we want to have a clickable link in text displayed by UILabel, we would need to resolve two independent tasks:
- Changing the appearance of a portion of the text to look like a link
- Detecting and handling touches on the link (opening an URL is a particular case)
The first one is easy. Starting from iOS 6 UILabel supports display of attributed strings. All you need to do is to create and configure an instance of NSMutableAttributedString:
NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:@"String with a link" attributes:nil];
NSRange linkRange = NSMakeRange(14, 4); // for the word "link" in the string above
NSDictionary *linkAttributes = @{ NSForegroundColorAttributeName : [UIColor colorWithRed:0.05 green:0.4 blue:0.65 alpha:1.0],
NSUnderlineStyleAttributeName : @(NSUnderlineStyleSingle) };
[attributedString setAttributes:linkAttributes range:linkRange];
// Assign attributedText to UILabel
label.attributedText = attributedString;
That's it! The code above makes UILabel to display String with a link
Now we should detect touches on this link. The idea is to catch all taps within UILabel and figure out whether the location of the tap was close enough to the link. To catch touches we can add tap gesture recognizer to the label. Make sure to enable userInteraction for the label, it's turned off by default:
label.userInteractionEnabled = YES;
[label addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTapOnLabel:)]];
Now the most sophisticated stuff: finding out whether the tap was on where the link is displayed and not on any other portion of the label. If we had single-lined UILabel, this task could be solved relatively easy by hardcoding the area bounds where the link is displayed, but let's solve this problem more elegantly and for general case - multiline UILabel without preliminary knowledge about the link layout.
One of the approaches is to use capabilities of Text Kit API introduced in iOS 7:
// Create instances of NSLayoutManager, NSTextContainer and NSTextStorage
NSLayoutManager *layoutManager = [[NSLayoutManager alloc] init];
NSTextContainer *textContainer = [[NSTextContainer alloc] initWithSize:CGSizeZero];
NSTextStorage *textStorage = [[NSTextStorage alloc] initWithAttributedString:attributedString];
// Configure layoutManager and textStorage
[layoutManager addTextContainer:textContainer];
[textStorage addLayoutManager:layoutManager];
// Configure textContainer
textContainer.lineFragmentPadding = 0.0;
textContainer.lineBreakMode = label.lineBreakMode;
textContainer.maximumNumberOfLines = label.numberOfLines;
Save created and configured instances of NSLayoutManager, NSTextContainer and NSTextStorage in properties in your class (most likely UIViewController's descendant) - we'll need them in other methods.
Now, each time the label changes its frame, update textContainer's size:
- (void)viewDidLayoutSubviews
{
[super viewDidLayoutSubviews];
self.textContainer.size = self.label.bounds.size;
}
And finally, detect whether the tap was exactly on the link:
- (void)handleTapOnLabel:(UITapGestureRecognizer *)tapGesture
{
CGPoint locationOfTouchInLabel = [tapGesture locationInView:tapGesture.view];
CGSize labelSize = tapGesture.view.bounds.size;
CGRect textBoundingBox = [self.layoutManager usedRectForTextContainer:self.textContainer];
CGPoint textContainerOffset = CGPointMake((labelSize.width - textBoundingBox.size.width) * 0.5 - textBoundingBox.origin.x,
(labelSize.height - textBoundingBox.size.height) * 0.5 - textBoundingBox.origin.y);
CGPoint locationOfTouchInTextContainer = CGPointMake(locationOfTouchInLabel.x - textContainerOffset.x,
locationOfTouchInLabel.y - textContainerOffset.y);
NSInteger indexOfCharacter = [self.layoutManager characterIndexForPoint:locationOfTouchInTextContainer
inTextContainer:self.textContainer
fractionOfDistanceBetweenInsertionPoints:nil];
NSRange linkRange = NSMakeRange(14, 4); // it's better to save the range somewhere when it was originally used for marking link in attributed string
if (NSLocationInRange(indexOfCharacter, linkRange)) {
// Open an URL, or handle the tap on the link in any other way
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"https://stackoverflow.com/"]];
}
}
Make a part of UILabel clickable
The easiest way I achieved this was by using tttatributed label.
Clickable UILabel
Use this code, It's worked. Tested.
UILabel * clickMeLbl=[[UILabel alloc] initWithFrame:CGRectMake(75,30,170,30)];
clickMeLbl.text = @"Click Me";
clickMeLbl.font = [UIFont fontWithName:@"Helvetica-Bold" size: 18.0f ];
clickMeLbl.textAlignment = NSTextAlignmentCenter;
clickMeLbl.textColor = [UIColor blackColor];
[self.view addSubview:clickMeLbl];
clickMeLbl.userInteractionEnabled = YES;
UITapGestureRecognizer *tapGesture =[[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(didTapLabelWithGesture:)];
[clickMeLbl addGestureRecognizer:tapGesture];
- (void)didTapLabelWithGesture:(UITapGestureRecognizer *)tapGesture {
NSLog(@"Click Me Label Clicked");
}
How to make URL/Phone-clickable UILabel?
You can use a UITextView
and select Detection for Links, Phone Numbers and other things in the inspector.
Related Topics
Core Data Background Context Best Practice
How to Remove the Default Navigation Bar Space in Swiftui Navigationview
How to Display .Svg Image Using Swift
What Is the '' Is or the ':' at the Equation When Coding in Swift
Swift Programmatically Navigate to Another View Controller/Scene
Custom Mkannotation Callout Bubble with Button
Custom Init for Uiviewcontroller in Swift with Interface Setup in Storyboard
Best Way to Cache Images on iOS App
Xcode 6.1 Missing Required Architecture X86_64 in File
Ios9 Does Not Load Insecure Resources from a Secure Page (Ssl/Https)
How to Create a Uiview Bounce Animation
Get Device Token for Push Notification
iOS 8 - Can't Install Enterprise App
How to Release a Cgimageref in iOS