ios - 一个字的固定宽度(倒数计时器 3 :45) in UIlabel

标签 ios swift uilabel nsattributedstring

我想在 UILabel 中显示倒数计时器,但是当我更新计时器时,下一个句子/单词的位置会发生变化。计时器向左、向右移动后完成句子。 enter image description here 我想修复定时器(4:47)的宽度,这样只有定时器值应该更新而不改变任何其他单词的位置。任何想法都将有助于解决这个问题。我不能使用三个标签,因为文本是多行的。

这是我使用的代码:

override func viewDidLoad() {
    super.viewDidLoad()

    Timer.scheduledTimer(withTimeInterval: 1, repeats: true) {[weak self] timer in
        self?.updateText()
        if let time = self?.reservedTimeInSeconds, time < 0 {
            timer.invalidate()
            self?.reservedTimeInSeconds = 300
        }
    }
}

func updateText() {
    let minutes: Int = self.reservedTimeInSeconds / 60
    let seconds: Int = self.reservedTimeInSeconds % 60
    let timer = String(format: "%d:%02d", minutes, seconds)

    self.textLabel.text = "Price valid for: \(timer). All prices inclusive of 3% gst."

    self.reservedTimeInSeconds -= 1
}

我尝试使用属性字符串但没有运气,这段代码有点工作但是当我尝试设置自定义字体和字体大小时它中断了。

func updateText() {
    let minutes: Int = self.reservedTimeInSeconds / 60
    let seconds: Int = self.reservedTimeInSeconds % 60
    let timer = String(format: "%d:%02d", minutes, seconds)
    let html = "<div>%@ <div style=\"color: %@;text-align: center;display: inline-block; overflow: hidden;\">%@</div>. %@</div>"
    let htmlFilledString = String(format: html, "Price valid for: ", "green", timer, "All price inclusive of 3% gst. All price inclusive of 3% gst")
    self.textLabel.attributedText = htmlFilledString.html2AttributedString

    self.reservedTimeInSeconds -= 1
}


extension Data {
    var html2AttributedString: NSAttributedString? {
        do {
            return try NSAttributedString(data: self, options: [.documentType: NSAttributedString.DocumentType.html, .characterEncoding: String.Encoding.utf8.rawValue], documentAttributes: nil)
        } catch {
            print("error:", error)
            return  nil
        }
    }
    var html2String: String {
        return html2AttributedString?.string ?? ""
    }
}

extension String {
    var html2AttributedString: NSAttributedString? {
        return Data(utf8).html2AttributedString
    }
    var html2String: String {
        return html2AttributedString?.string ?? ""
    }
}

最佳答案

如果你不能使用三个标签,我认为你可以使用两个标签来解决这个问题;)。

  • 在倒计时之前计算文本的宽度和高度。在这种情况下,它是“Price valid for”。您可以使用下面的扩展来做到这一点。

    extension String {
      func widthOfString(usingFont font: UIFont) -> CGFloat {
        let fontAttributes = [NSAttributedStringKey.font: font];
        let size = self.size(withAttributes: fontAttributes);
        return size.width
      }
    
      func heightWithConstrainedWidth(width: CGFloat, font: UIFont) -> CGFloat {
        let constraintRect = CGSize(width: width, height: .greatestFiniteMagnitude)
        let boundingBox = self.boundingRect(with: constraintRect, options: [.usesLineFragmentOrigin, .usesFontLeading], attributes: [NSAttributedStringKey.font: font], context: nil)
        return boundingBox.height
      }
    }
    
  • 再创建一个与 mainLabel 字体相同的 UILabel (countDownLabel),给它绿色 textColor
  • 使 coundDownLabelmainLabel 重叠。
  • 代替设置

    mainLabel.text = "Price valid for 4:36. All prices are inclusive of 9234% GST.";
    

    使用

    mainLabel.text = "Price valid for          . All prices are inclusive of 9234% GST.";
    
  • 最后,给countDown一个右前导和顶约束。

    let displayedText = "Price valid valid valid valid for _counDownTimer_. All prices are inclusive of 9234% GST.";
    let labelWidth : CGFloat = 200;
    
    // Add main label
    let textLabel = UILabel.init();
    textLabel.translatesAutoresizingMaskIntoConstraints = false;
    textLabel.textColor = UIColor.darkGray;
    textLabel.numberOfLines = 0;
    textLabel.text = displayedText.replacingOccurrences(of: "_counDownTimer_", with: "         ");
    self.view.addSubview(textLabel);
    
    // Update constraints for |textLabel|
    textLabel.topAnchor.constraint(equalTo: self.view.topAnchor, constant: 50).isActive = true;
    textLabel.leadingAnchor.constraint(equalTo: self.view.leadingAnchor, constant: 10).isActive = true;
    textLabel.widthAnchor.constraint(equalToConstant: 200).isActive = true;
    
    // Add timer label
    let countDownLabel = UILabel.init();
    countDownLabel.textColor = UIColor.green;
    countDownLabel.translatesAutoresizingMaskIntoConstraints = false;
    self.view.addSubview(countDownLabel);
    
    // Calculate position and update constraints of |countDownLabel|
    let timerTextRange = displayedText.range(of: "_counDownTimer_");
    let textBeforeTimer = displayedText.substring(to: (timerTextRange?.lowerBound)!);
    let textWidth = textBeforeTimer.widthOfString(usingFont: textLabel.font);
    let textHeight = textBeforeTimer.heightWithConstrainedWidth(width: labelWidth, font: textLabel.font);
    
    var leadingConstant = textWidth;
    let topConstant = textHeight - textLabel.font.lineHeight;
    
    let indexOfCountDownLine = NSInteger(textHeight / textLabel.font.lineHeight) - 1;
    
    if indexOfCountDownLine > 0 {
      leadingConstant = leadingConstant - CGFloat(indexOfCountDownLine) * labelWidth;
    }
    
    countDownLabel.topAnchor.constraint(equalTo: textLabel.topAnchor, constant: topConstant).isActive = true;
    countDownLabel.leadingAnchor.constraint(equalTo: textLabel.leadingAnchor, constant: leadingConstant).isActive = true;
    

结果

enter link description here

有关更多详细信息,您可以查看我的演示库 here .

关于ios - 一个字的固定宽度(倒数计时器 3 :45) in UIlabel,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49583232/

相关文章:

ios - 如何在 UIImage 上显示标签?

iphone - numberOfLines=2 的 UILabel 使用什么约束高度? (使用 [NSString sizeWithFont...])

ios - 烦人的 Xcode 错误 "file not found"#import <openssl/pkcs7.h>

ios - Swift - 使用 SwiftyJSON 从 JSON 获取字符串数组

ios - 如果我使用仅自 iOS 10 起可用的内容,这是否意味着我无法在 iOS 9 上安装该应用程序?

ios - 如何将可选的 NSData 转换为可选的 Bool

iphone - 以编程方式调用 segue 不起作用

ios - 将 VCard 转换为 CNContact

arrays - 对一维字符串数组进行排序

swift - 随着我的 UILabel 尺寸的增加,在它周围获得额外的空间