如何仅为Swift 3中的UILabel的特定范围设置点击手势

问题描述 投票:2回答:2

我有一个attributed string设置为UILabelmultiple underlinescolors像下面的图像

enter image description here

我知道如何为整个标签设置一个水龙头手势(启用user interaction),下面是我所做的代码,包括设置underline和为font colors设置multiple ranges

import UIKit

class ViewController: UIViewController {


    @IBOutlet weak var mylabel: UILabel!

    var theString = "I have agree with the terms and conditions and privacy policy"

    override func viewDidLoad() {
        super.viewDidLoad()

        mylabel.text = theString


        let tap = UITapGestureRecognizer(target: self, action: #selector(ViewController.printme))
        mylabel.addGestureRecognizer(tap)

        setUnderline(theText: theString)

        // Do any additional setup after loading the view, typically from a nib.
    }

    func printme() {
        print("print this")
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    func setUnderline(theText : String) {
        //set up underline
        let textRange1 = NSMakeRange(22, 19)
        let textRange2 = NSMakeRange(47, (theText.characters.count-47))
        let attributedText = NSMutableAttributedString(string : theText)
        attributedText.addAttribute(NSUnderlineStyleAttributeName, value: NSUnderlineStyle.styleSingle.rawValue, range: textRange1)
        attributedText.addAttribute(NSUnderlineStyleAttributeName, value: NSUnderlineStyle.styleSingle.rawValue, range: textRange2)


        //setup colors
        attributedText.addAttribute(NSForegroundColorAttributeName, value: UIColor.red, range: NSRange(location: 22,length: 20))
        attributedText.addAttribute(NSForegroundColorAttributeName, value: UIColor.red, range: NSRange(location: 47,length: (theText.characters.count-47)))

        mylabel.attributedText = attributedText

    }
  • tap手势为whole label工作。我想要的是当用户点击“条款和条件”时触发不同的功能,并且当用户点击“隐私政策”时触发另一个不同的功能。我怎样才能做到这一点。

注意:我想激活两个不同的功能,一个用于“条款和条件”点击,另一个用于“隐私政策”点击,并且不想只打开链接

ios swift3 nsattributedstring uitapgesturerecognizer nsrange
2个回答
1
投票
    import UIKit

    protocol SSGastureDelegate:NSObjectProtocol {
        func callBack()
    }
    class SSUnderLineLabel: UILabel {
        var tapGesture: UITapGestureRecognizer?

      //Make weak refernece for SSGastureDelegate
       weak var delegate:SSGastureDelegate?

        required init(coder aDecoder: NSCoder) {
            super.init(coder: aDecoder)!
            self.initialization()
        }
        override init(frame: CGRect) {
            super.init(frame: frame)
            self.initialization()
        }

        func initialization(){
            let newsString: NSMutableAttributedString = NSMutableAttributedString(string: self.text!)
            let textRange = NSString(string: self.text!)
            let substringRange = textRange.range(of: "Terms and Conditions") // You can add here for own specific under line substring
            newsString.addAttribute(NSUnderlineStyleAttributeName, value: NSUnderlineStyle.styleSingle.rawValue, range: substringRange)
           // self.attributedText = newsString.copy() as? NSAttributedString
            self.attributedText = newsString
            self.tapGesture = UITapGestureRecognizer(target: self, action: #selector(tapResponse))
            self.isUserInteractionEnabled =  true
            self.addGestureRecognizer(tapGesture!)

        }

        func tapResponse(recognizer: UITapGestureRecognizer) {

            let text = (self.text)!
            let termsRange = (text as NSString).range(of: "Terms and Conditions")
            if (tapGesture?.didTapAttributedTextInLabel(label: self, inRange: termsRange))! {
                print("Tapped terms conditions")
                self.delegate?.callBack()
            }
            else {
                print("Tapped none ")
            }
        }

    }

    //MARK:UITapGestureRecognizer Extension
    //MARK:
    extension UITapGestureRecognizer {

        func didTapAttributedTextInLabel(label: UILabel, inRange targetRange: NSRange) -> Bool {
            // Create instances of NSLayoutManager, NSTextContainer and NSTextStorage
            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
            let labelSize = label.bounds.size
            textContainer.size = labelSize
            // Find the tapped character location and compare it to the specified range
            let locationOfTouchInLabel = self.location(in: label)
            let textBoundingBox = layoutManager.usedRect(for: 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 = layoutManager.characterIndex(for: locationOfTouchInTextContainer, in: textContainer, fractionOfDistanceBetweenInsertionPoints: nil)
            return NSLocationInRange(indexOfCharacter, targetRange)
        }

    }*`enter code here`




**How to use it:**
Assign this class for your label and follow these steps:
Demo for use class:

ViewController.swift
//===============

class ViewController: UIViewController,SSGastureDelegate {
 @IBOutlet var underlineLbl: SSUnderLineLabel!

 override func viewDidLoad() {
      super.viewDidLoad()
     self.underlineLbl.delegate = self
 }
//Implement Delegate Method
 func callBack()
    {
//Open a specific vc for underline tap are`enter code here`a.
        let termsconditionsVC = storyboard?.instantiateViewController(withIdentifier: "TermsConditionsVC") as! TermsConditionsVC
        self.present(termsconditions, animated: true, completion: nil)

    }
}*

0
投票

我发现你需要你的条款和隐私链接是可点击的,ios给出的简单方法是AttributedString,使用以下代码:

let theString = "I have agree with the terms and conditions and privacy policy"
let someAttributedString = NSMutableAttributedString(string: theString)
someAttributedString.addAttribute(NSLinkAttributeName, value: "http://www.google.com", range: NSMakeRange(22, 20))
titleLabel.attributedText = someAttributedString

TTTAttributedLabel可能是您最好的解决方案:https://github.com/TTTAttributedLabel/TTTAttributedLabel

TTTAttributedLabel有以下代表

- (void)attributedLabel:(__unused TTTAttributedLabel *)label
   didSelectLinkWithURL:(NSURL *)url
{
 //do whatever you want
}

此外,如果您需要点击手势的解决方案,您可以在手势点击上找到该点并进行计算以检查点击它的位置以通过gestureRecognizer.locationInView方法执行您的操作

© www.soinside.com 2019 - 2024. All rights reserved.