Tôi muốn tạo một nhãn có thể nhấp trên ứng dụng của mình dẫn tôi đến trang web Safari. Tôi cũng muốn người dùng có thể gọi các số chỉ bằng cách nhấp vào chúng?
Cảm ơn lời khuyên của bạn
Tôi muốn tạo một nhãn có thể nhấp trên ứng dụng của mình dẫn tôi đến trang web Safari. Tôi cũng muốn người dùng có thể gọi các số chỉ bằng cách nhấp vào chúng?
Cảm ơn lời khuyên của bạn
Câu trả lời:
Bạn có thể sử dụng a UITextView
và chọn Dò tìm liên kết, Số điện thoại và những thứ khác trong trình kiểm tra.
Sử dụng UITextView
thay vì UILabel
và nó có thuộc tính để chuyển đổi văn bản của bạn thành siêu liên kết.
yourTextView.editable = NO;
yourTextView.dataDetectorTypes = UIDataDetectorTypeAll;
yourTextView.editable = false;
yourTextView.dataDetectorTypes = UIDataDetectorTypes.All;
Điều này sẽ tự động phát hiện các liên kết.
Xem tài liệu để biết chi tiết.
https://github.com/mattt/TTTAttributedLabel
Đó chắc chắn là những gì bạn cần. Bạn cũng có thể áp dụng các thuộc tính cho nhãn của mình, như gạch dưới và áp dụng các màu khác nhau cho nhãn. Chỉ cần kiểm tra hướng dẫn cho các url có thể nhấp.
Chủ yếu, bạn thực hiện một số việc như sau:
NSRange range = [label.text rangeOfString:@"me"];
[label addLinkToURL:[NSURL URLWithString:@"http://github.com/mattt/"] withRange:range]; // Embedding a custom link in a substring
Bạn có thể tạo UIButton và setText tùy chỉnh những gì bạn muốn và thêm một phương thức với điều đó.
UIButton *sampleButton = [UIButton buttonWithType:UIButtonTypeCustom];
[sampleButton setFrame:CGRectMake(kLeftMargin, 10, self.view.bounds.size.width - kLeftMargin - kRightMargin, 52)];
[sampleButton setTitle:@"URL Text" forState:UIControlStateNormal];
[sampleButton setFont:[UIFont boldSystemFontOfSize:20]];
[sampleButton addTarget:self action:@selector(buttonPressed) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:sampleButton];
-(void)buttonPressed:(id)sender{
// open url
}
Nếu bạn muốn điều này được xử lý bởi UILabel chứ không phải UITextView, bạn có thể tạo lớp con của UILabel, như sau:
class LinkedLabel: UILabel {
fileprivate let layoutManager = NSLayoutManager()
fileprivate let textContainer = NSTextContainer(size: CGSize.zero)
fileprivate var textStorage: NSTextStorage?
override init(frame aRect:CGRect){
super.init(frame: aRect)
self.initialize()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.initialize()
}
func initialize(){
let tap = UITapGestureRecognizer(target: self, action: #selector(LinkedLabel.handleTapOnLabel))
self.isUserInteractionEnabled = true
self.addGestureRecognizer(tap)
}
override var attributedText: NSAttributedString?{
didSet{
if let _attributedText = attributedText{
self.textStorage = NSTextStorage(attributedString: _attributedText)
self.layoutManager.addTextContainer(self.textContainer)
self.textStorage?.addLayoutManager(self.layoutManager)
self.textContainer.lineFragmentPadding = 0.0;
self.textContainer.lineBreakMode = self.lineBreakMode;
self.textContainer.maximumNumberOfLines = self.numberOfLines;
}
}
}
func handleTapOnLabel(tapGesture:UITapGestureRecognizer){
let locationOfTouchInLabel = tapGesture.location(in: tapGesture.view)
let labelSize = tapGesture.view?.bounds.size
let textBoundingBox = self.layoutManager.usedRect(for: self.textContainer)
let textContainerOffset = CGPoint(x: ((labelSize?.width)! - textBoundingBox.size.width) * 0.5 - textBoundingBox.origin.x, y: ((labelSize?.height)! - textBoundingBox.size.height) * 0.5 - textBoundingBox.origin.y)
let locationOfTouchInTextContainer = CGPoint(x: locationOfTouchInLabel.x - textContainerOffset.x, y: locationOfTouchInLabel.y - textContainerOffset.y)
let indexOfCharacter = self.layoutManager.characterIndex(for: locationOfTouchInTextContainer, in: self.textContainer, fractionOfDistanceBetweenInsertionPoints: nil)
self.attributedText?.enumerateAttribute(NSLinkAttributeName, in: NSMakeRange(0, (self.attributedText?.length)!), options: NSAttributedString.EnumerationOptions(rawValue: UInt(0)), using:{
(attrs: Any?, range: NSRange, stop: UnsafeMutablePointer<ObjCBool>) in
if NSLocationInRange(indexOfCharacter, range){
if let _attrs = attrs{
UIApplication.shared.openURL(URL(string: _attrs as! String)!)
}
}
})
}}
Lớp này được tạo bằng cách sử dụng lại mã từ câu trả lời này . Để tạo chuỗi phân bổ, hãy kiểm tra câu trả lời này . Và ở đây bạn có thể tìm thấy cách tạo url điện thoại.
Sử dụng cái này, tôi rất thích nó vì chỉ tạo liên kết với màu xanh lam đến văn bản cụ thể chứ không phải trên toàn bộ văn bản nhãn: FRHyperLabel
Làm:
Tải về từ liên kết ở trên và bản sao FRHyperLabel.h
, FRHyperLabel.m
để dự án của bạn.
Kéo thả UILabel
vào của bạn Storyboard
và xác định tên lớp tùy chỉnh để FRHyperLabel
xác định trình kiểm tra như thể hiện trong hình ảnh.
@property (weak, nonatomic) IBOutlet FRHyperLabel *label;
`NSString * string = @" Bằng cách tải lên, tôi đồng ý với Điều khoản sử dụng "; NSDictionary * thuộc tính = @ {NSFontAttributeName: [UIFont preferFontForTextStyle: UIFontTextStyleHeadline]};
_label.attributedText = [[NSAttributedString alloc]initWithString:string attributes:attributes];
[_label setFont:[_label.font fontWithSize:13.0]];
[_label setLinkForSubstring:@"Terms of Use" withLinkHandler:^(FRHyperLabel *label, NSString *substring){
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"http://www.google.com"]];
}];`
Sử dụng UITextView thay vì UILabel và nó có thuộc tính để chuyển đổi văn bản của bạn thành siêu liên kết
Mã Swift:
yourTextView.editable = false
yourTextView.dataDetectorTypes = UIDataDetectorTypes.All
//or
yourTextView.dataDetectorTypes = UIDataDetectorTypes.PhoneNumber
//or
yourTextView.dataDetectorTypes = UIDataDetectorTypes.Link
extension UITapGestureRecognizer {
func didTapAttributedTextInLabel(label: UILabel, inRange targetRange: NSRange) -> Bool {
let layoutManager = NSLayoutManager()
let textContainer = NSTextContainer(size: CGSize.zero)
let textStorage = NSTextStorage(attributedString: label.attributedText!)
// Configure layoutManager and textStorage
layoutManager.addTextContainer(textContainer)
textStorage.addLayoutManager(layoutManager)
// Configure textContainer
textContainer.lineFragmentPadding = 0.0
textContainer.lineBreakMode = label.lineBreakMode
textContainer.maximumNumberOfLines = label.numberOfLines
textContainer.size = label.bounds.size
// main code
let locationOfTouchInLabel = self.location(in: label)
let indexOfCharacter = layoutManager.characterIndex(for: locationOfTouchInLabel, in: textContainer, fractionOfDistanceBetweenInsertionPoints: nil)
let indexOfCharacterRange = NSRange(location: indexOfCharacter, length: 1)
let indexOfCharacterRect = layoutManager.boundingRect(forGlyphRange: indexOfCharacterRange, in: textContainer)
let deltaOffsetCharacter = indexOfCharacterRect.origin.x + indexOfCharacterRect.size.width
if locationOfTouchInLabel.x > deltaOffsetCharacter {
return false
} else {
return NSLocationInRange(indexOfCharacter, targetRange)
}
}
}
Tại sao không chỉ sử dụng NSMutableAttributedString ?
let attributedString = NSMutableAttributedString(string: "Want to learn iOS? Just visit developer.apple.com!")
attributedString.addAttribute(.link, value: "https://developer.apple.com", range: NSRange(location: 30, length: 50))
myView.attributedText = attributedString
Bạn có thể tìm thêm thông tin chi tiết tại đây
Phiên bản Swift 4.2, Xcode 9.3
class LinkedLabel: UILabel {
fileprivate let layoutManager = NSLayoutManager()
fileprivate let textContainer = NSTextContainer(size: CGSize.zero)
fileprivate var textStorage: NSTextStorage?
override init(frame aRect:CGRect){
super.init(frame: aRect)
self.initialize()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.initialize()
}
func initialize(){
let tap = UITapGestureRecognizer(target: self, action: #selector(self.handleTapOnLabel))
self.isUserInteractionEnabled = true
self.addGestureRecognizer(tap)
}
override var attributedText: NSAttributedString?{
didSet{
if let _attributedText = attributedText{
self.textStorage = NSTextStorage(attributedString: _attributedText)
self.layoutManager.addTextContainer(self.textContainer)
self.textStorage?.addLayoutManager(self.layoutManager)
self.textContainer.lineFragmentPadding = 0.0;
self.textContainer.lineBreakMode = self.lineBreakMode;
self.textContainer.maximumNumberOfLines = self.numberOfLines;
}
}
}
@objc func handleTapOnLabel(tapGesture:UITapGestureRecognizer){
let locationOfTouchInLabel = tapGesture.location(in: tapGesture.view)
let labelSize = tapGesture.view?.bounds.size
let textBoundingBox = self.layoutManager.usedRect(for: self.textContainer)
let textContainerOffset = CGPoint(x: ((labelSize?.width)! - textBoundingBox.size.width) * 0.5 - textBoundingBox.origin.x, y: ((labelSize?.height)! - textBoundingBox.size.height) * 0.5 - textBoundingBox.origin.y)
let locationOfTouchInTextContainer = CGPoint(x: locationOfTouchInLabel.x - textContainerOffset.x, y: locationOfTouchInLabel.y - textContainerOffset.y)
let indexOfCharacter = self.layoutManager.characterIndex(for: locationOfTouchInTextContainer, in: self.textContainer, fractionOfDistanceBetweenInsertionPoints: nil)
self.attributedText?.enumerateAttribute(NSAttributedStringKey.link, in: NSMakeRange(0, (self.attributedText?.length)!), options: NSAttributedString.EnumerationOptions(rawValue: UInt(0)), using:{
(attrs: Any?, range: NSRange, stop: UnsafeMutablePointer<ObjCBool>) in
if NSLocationInRange(indexOfCharacter, range){
if let _attrs = attrs{
UIApplication.shared.openURL(URL(string: _attrs as! String)!)
}
}
})
}}
Swift 4.0 giải pháp khả thi sử dụng UIButton
phoneButton = UIButton(frame: CGRect(x: view.frame.width * 0, y: view.frame.height * 0.1, width: view.frame.width * 1, height: view.frame.height * 0.05))
phoneButton.setTitle("333-333-3333", for: .normal )
phoneButton.setTitleColor(UIColor(red: 0 / 255, green: 0 / 255, blue: 238 / 255, alpha: 1.0), for: .normal)
phoneButton.addTarget(self, action: #selector(self.callPhone), for: .touchUpInside )
@objc func callPhone(){
UIApplication.shared.open(URL(string:"tel://3333333333")!, options: [:] , completionHandler: nil)
}