【问题标题】:Turn some parts of UILabel to act like a UIButton? [duplicate]将 UILabel 的某些部分变成 UIButton? [复制]
【发布时间】:2016-10-22 21:45:49
【问题描述】:

我有一个属性字符串UILabel,我可以为文本的某些部分着色

let text = "Why did \(event) give \(event2) a 5 stars review? Details here. "
let linkTextWithColor = "Why did"
let range = (text as NSString).rangeOfString(linkTextWithColor)

let attributedString = NSMutableAttributedString(string:text)
attributedString.addAttribute(NSForegroundColorAttributeName, value: UIColor.blackColor() , range: range)

labelEvent.attributedText = attributedString

现在我想让文本的某些部分可以点击,比如UIButton,该怎么做?

示例 1

示例 2

我需要有蓝色文本来响应触摸并运行特定功能,例如UIButton。 非常感谢您的帮助,谢谢。

【问题讨论】:

标签: ios swift uibutton uilabel


【解决方案1】:

您想要做的是使用带有文本视图的属性字符串来创建一个充当按钮的链接。

let attributedString = NSMutableAttributedString(string: "Some string with link", attributes: [<attributes>])

然后将其中的一部分设置为链接,并使用文本视图的linkAttributes 属性自定义其外观。因为这是一个按钮而不是实际链接,所以我们只是在链接中放置了一个虚拟 url,以便我们稍后在代理中处理它。

attributedString.setSubstringAsLink(substring: "link", linkURL: "CUSTOM://WHATEVER")
let linkAttributes: [String : AnyObject] = [NSForegroundColorAttributeName : .redColor(), NSUnderlineColorAttributeName : .redColor(), NSUnderlineStyleAttributeName : NSUnderlineStyle.StyleSingle.rawValue]
textView.linkTextAttributes = linkAttributes
textView.attributedText = attributedString
textView.selectable = true
textView.editable = false
textView.userInteractionEnabled = true

最后,在文本视图委托中,我们将检查方案并执行一些操作。

func textView(textView: UITextView, shouldInteractWithURL URL: NSURL, inRange characterRange: NSRange) -> Bool {
    if URL.scheme == "CUSTOM" {
       // Do your button actions here
    }
    return true
}

setSubstringAsLink 的扩展:

extension NSMutableAttributedString {
    // Set part of string as URL
    public func setSubstringAsLink(substring substring: String, linkURL: String) -> Bool {
        let range = self.mutableString.rangeOfString(substring)
        if range.location != NSNotFound {
            self.addAttribute(NSLinkAttributeName, value: linkURL, range: range)
            return true
        }
        return false
    }
}

【讨论】:

  • setSubstringAsLink 在整个 ios 库中不存在,这很奇怪,有人试过吗?
  • 另外,这将需要长按,这并不适用于所有情况:(
  • 编辑了用于设置子字符串的扩展名。它不需要长按。
  • 我收到“调用 'setSubstringAsLink(substring:linkURL:) 的结果未使用,因此 shouldInteractWithURL 没有被触发。
  • 这有一些副作用。当长按链接时,它会在 UITextView 上显示链接文本,这似乎是 UIKit 的原生功能。
【解决方案2】:

假设您有一个带有文本“abc123”的UILabel,并且您希望“abc”充当UIButton

  • 计算并存储包含“abc”的矩形。
  • UITapGestureRecognizer 添加到UILabel
  • UILabel被点击时,检查点击是否在矩形内。

static func getRect(str: NSAttributedString, range: NSRange, maxWidth: CGFloat) -> CGRect {
    let textStorage = NSTextStorage(attributedString: str)
    let textContainer = NSTextContainer(size: CGSize(width: maxWidth, height: CGFloat.max))
    let layoutManager = NSLayoutManager()       
    layoutManager.addTextContainer(textContainer)
    textStorage.addLayoutManager(layoutManager)     
    textContainer.lineFragmentPadding = 0       
    let pointer = UnsafeMutablePointer<NSRange>.alloc(1)
    layoutManager.characterRangeForGlyphRange(range, actualGlyphRange: pointer)     
    return layoutManager.boundingRectForGlyphRange(pointer.move(), inTextContainer: textContainer)
}

let rect1 = getRect(label.attributedText!, range: NSMakeRange(0, 3), maxWidth: label.frame.width)

label.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(MyClass.tappedLabel(_:))))

func tappedLabel(sender: UITapGestureRecognizer) {
    if rect1.contains(sender.locationInView(sender.view)) {
        // ...
    }
}

【讨论】:

  • 计算关闭,只识别上面想要的字母!
  • @DeyaEldeen 对我来说很好。你可能做错了什么。
  • 文字着色怎么样?
【解决方案3】:

我建议你试试这个库

https://github.com/null09264/FRHyperLabel

很棒的库,易于使用,并且几乎没有内置示例供您试用。 Objective-c 和 Swift 中都有示例

Swift 中的示例

 let str = "This is a random bit of text"
        let attributes = [NSForegroundColorAttributeName: UIColor.blackColor(),
                          NSFontAttributeName: UIFont.systemFontOfSize(15)]
        confirmLabel.attributedText = NSAttributedString(string: str, attributes: attributes)

        let handler = {
            (hyperLabel: FRHyperLabel!, substring: String!) -> Void in

            //action here
        }
        //Step 3: Add link substrings
        confirmLabel.setLinksForSubstrings(["random"], withLinkHandler: handler)

编辑:

如果你想去掉下划线,最好的方法是遵循 DeyaEldeen 在评论中给出的建议。

如果你去FRHyperLabel的.m文件,去这个方法

- (void)checkInitialization {
    if (!self.handlerDictionary) {
        self.handlerDictionary = [NSMutableDictionary new];
    }

    if (!self.userInteractionEnabled) {
        self.userInteractionEnabled = YES;
    }

    if (!self.linkAttributeDefault) {
        self.linkAttributeDefault = @{NSForegroundColorAttributeName: FRHyperLabelLinkColorDefault,
                                      NSUnderlineStyleAttributeName: @(NSUnderlineStyleSingle)};
    }

    if (!self.linkAttributeHighlight) {
        self.linkAttributeHighlight = @{NSForegroundColorAttributeName: FRHyperLabelLinkColorHighlight,
                                        NSUnderlineStyleAttributeName: @(NSUnderlineStyleSingle)};
    }
}

你可以删除它

NSUnderlineStyleAttributeName: @(NSUnderlineStyleSingle)

从属性

【讨论】:

  • 为什么这被否决了?这个库完全符合 OP 的要求,我在我的项目中使用过它并且效果很好
  • 虽然此链接可能会回答问题,但最好在此处包含答案的基本部分并提供链接以供参考。如果链接页面发生更改,仅链接答案可能会失效。 - From Review
  • 用示例更新答案
  • 这是最好的答案,但是如何更改标签链接部分的样式?例如,我不希望它加下划线。
  • 要删除下划线,只需在 FRHyperLabel 中像这样注释行 /*NSUnderlineStyleAttributeName: @(NSUnderlineStyleSingle)*/
【解决方案4】:

这个想法是使用诸如TTTAttributedLabel之类的库并以这种方式使用它:

考虑以下字符串“我想在 here 中被触摸”,其中 here 将在触摸时执行 segue。

  • 创建TTTAttributedLabelUILabel子类),将文本内容放入其中,就像是UILabel一样。将其委托设置为自己。然后,以这种方式添加一个单词的链接:

目标 C

NSRange rangeWord = [attributedLabel.text rangeOfString:@"here"];
[attributedLabel addLinkToURL:[NSURL URLWithString:@"anActionOnClickHere"] withRange:rangeUser];

斯威夫特

NSRange rangeWord = attributedLabel.text.rangeOfString("here")
attributedLabel.addLinkToURL(NSURL(string: "anActionOnClickHere"), withRange:rangeUser)
  • 点击单词时,它将调用此方法,您可以在其中处理点击:

目标 C

- (void)attributedLabel:(__unused TTTAttributedLabel *)label
   didSelectLinkWithURL:(NSURL *)url {
    NSString *urlToString = [url absoluteString];

    if ([urlToString containsString:@"anActionOnClickHere"]) { //perform segue for example
        [self performSegueWithIdentifier:@"hereSegue" sender:self];
    }
}

斯威夫特

func attributedLabel(label: TTTAttributedLabel!, didSelectLinkWithURL url: NSURL!) {
    NSString *urlToString = url.absoluteString()
    if (urlToString.containsString("anActionOnClickHere")) { //perform segue for example 
        self.performSegueWithIdentifier("hereSegue",sender:self)
    } 
}

使用默认链接样式,您将获得所需的蓝色。

【讨论】:

    猜你喜欢
    • 2010-11-04
    • 1970-01-01
    • 2015-02-05
    • 1970-01-01
    • 2017-05-18
    • 2017-12-01
    • 1970-01-01
    • 2011-09-20
    • 1970-01-01
    相关资源
    最近更新 更多