Bagaimana cara membuat UILabel URL / Telepon dapat diklik?

Jawaban:

134

Anda dapat menggunakan UITextViewdan memilih Deteksi untuk Tautan, Nomor Telepon, dan hal-hal lain di inspektur.

Basel
sumber
2
Saya memiliki label pengubah ukuran sendiri yang dapat menampung N baris teks. Bagaimana cara membuat tautan di label ini dapat diklik tanpa menerapkan UITextView.
bibscy
@bibscy maka Anda dapat menggunakan NSAttributedText. Lihat stackoverflow.com/questions/1256887/…
Basel
95

Gunakan UITextViewsebagai gantiUILabel dan ini memiliki properti untuk mengonversi teks Anda menjadi hyperlink.

Objective-C:

yourTextView.editable = NO;
yourTextView.dataDetectorTypes = UIDataDetectorTypeAll;

Cepat:

yourTextView.editable = false; 
yourTextView.dataDetectorTypes = UIDataDetectorTypes.All;

Ini akan mendeteksi tautan secara otomatis.

Lihat dokumentasi untuk detailnya.

Sameera Chathuranga
sumber
5
ini mewarnai tautan dengan warna biru dan menggarisbawahi, tetapi tampaknya membuatnya dapat diklik, setidaknya di iOS 7.
Ben H
1
Kode Swift: yourTextView.editable = false; yourTextView.dataDetectorTypes = UIDataDetectorTypes.All;
Thiago Arreguy
5
pertanyaannya adalah tentang UILabel, bukan UITextView.
swift2geek
28

https://github.com/mattt/TTTAttributedLabel

Itu pasti yang Anda butuhkan. Anda juga dapat menerapkan atribut untuk label Anda, seperti garis bawah, dan menerapkan warna yang berbeda padanya. Cukup periksa petunjuk untuk url yang dapat diklik.

Terutama, Anda melakukan sesuatu seperti berikut:

NSRange range = [label.text rangeOfString:@"me"];
[label addLinkToURL:[NSURL URLWithString:@"http://github.com/mattt/"] withRange:range]; // Embedding a custom link in a substring
Ramy Kfoury
sumber
12

Anda dapat membuat UIButton dan setText kustom apa pun yang Anda inginkan dan menambahkan metode dengannya.

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
}
Rohit Dhawan
sumber
Pengaturan font sekarang dilakukan dengan: button.titleLabel.font = [UIFont systemFontOfSize: size];
Leon
10

Jika Anda ingin ini ditangani oleh UILabel dan bukan UITextView, Anda dapat membuat subclass UILabel, seperti ini:

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)!)
            }
        }
    })

}}

Kelas ini dibuat dengan menggunakan kembali kode dari jawaban ini . Untuk membuat string yang diatribusikan, periksa jawaban ini . Dan di sini Anda dapat menemukan cara membuat url telepon.

Bojan Bozovic
sumber
6

Gunakan ini saya sangat menyukainya karena membuat tautan dengan warna biru ke teks tertentu saja tidak pada seluruh teks label: FRHyperLabel

Menerapkan hyperlink dengan cerdas pada Ketentuan Penggunaan

Melakukan:

  1. Unduh dari tautan di atas dan salin FRHyperLabel.h, FRHyperLabel.mke proyek Anda.

  2. Drag drop UILabeldi Anda Storyboarddan tentukan nama kelas khusus untuk FRHyperLabelmengidentifikasi inspektur seperti yang ditunjukkan pada gambar.

masukkan deskripsi gambar di sini

  1. Hubungkan UILabel Anda dari storyboard ke file viewController.h Anda

@property (weak, nonatomic) IBOutlet FRHyperLabel *label;

  1. Sekarang di file viewController.m Anda tambahkan kode berikut.

`NSString * string = @" Dengan mengunggah saya setuju dengan Syarat Penggunaan "; Atribut NSDictionary * = @ {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"]];
}];`
  1. Dan jalankan.
karan
sumber
6

Gunakan UITextView sebagai ganti UILabel dan ini memiliki properti untuk mengubah teks Anda menjadi hyperlink

Tukar Kode:

yourTextView.editable = false
yourTextView.dataDetectorTypes = UIDataDetectorTypes.All
//or
yourTextView.dataDetectorTypes = UIDataDetectorTypes.PhoneNumber
//or
yourTextView.dataDetectorTypes = UIDataDetectorTypes.Link
Thiago Arreguy
sumber
4
pertanyaan bagaimana menggunakan di UILabel, daripada TextView. Terima kasih.
swift2geek
0
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)
        }
    }
}
Harman
sumber
0

Mengapa tidak menggunakan NSMutableAttributedString saja ?

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

Anda dapat menemukan detail selengkapnya di sini

MANN
sumber
Saya baru saja mencoba hari ini untuk membuat panggilan dari UILabel dan kode di atas tidak berfungsi. Saya telah mengganti dev.appl.com dengan tel: // 1234567. Mungkin jawaban ini perlu diperbarui.
Pratik Somaiya
-1

Versi 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)!)
                }
            }
        })

    }}
swift2geek
sumber
-3

Solusi Swift 4.0 yang mungkin menggunakan 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)


    }
Fidel
sumber