【问题标题】:Find the number of characters that fits in a UITextView with constant width and height with a given string?查找适合具有给定字符串的恒定宽度和高度的 UITextView 的字符数?
【发布时间】:2015-03-20 22:00:50
【问题描述】:

在我的应用程序中,如果文本输入很大,我需要在文本视图中设置 Read more。所以我的方法是找到适合文本视图的字符串范围并将 See More 添加到它。有什么办法在 Swift 中实现它。要求是模拟 read more 选项,以便在 facebook 等点击时以详细视图显示完整文本。

【问题讨论】:

    标签: ios swift nsstring uitextview nsrange


    【解决方案1】:

    您要查找的函数是CTFramesetterSuggestFrameSizeWithConstraints。从本质上讲,它允许您找出适合某个框架的字符数。您可以使用该数字切断当前文本并插入一个按钮。

    我为 UILabel 的子类编写了这个函数的实现:

    - (NSInteger)numberOfCharactersThatFitLabel {
    
        // Create an 'CTFramesetterRef' from an attributed string
        CTFontRef fontRef = CTFontCreateWithName((CFStringRef)self.font.fontName, self.font.pointSize, NULL);
        NSDictionary *attributes = [NSDictionary dictionaryWithObject:(__bridge id)fontRef forKey:(id)kCTFontAttributeName];
        CFRelease(fontRef);
        NSAttributedString *attributedString  = [[NSAttributedString alloc] initWithString:self.text attributes:attributes];
        CTFramesetterRef frameSetterRef = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)attributedString);
    
        // Get a suggested character count that would fit the attributed string
        CFRange characterFitRange;
        CTFramesetterSuggestFrameSizeWithConstraints(frameSetterRef, CFRangeMake(0,0), NULL, CGSizeMake(self.bounds.size.width, self.numberOfLines*self.font.lineHeight), &characterFitRange);
        CFRelease(frameSetterRef);
        return (NSInteger)characterFitRange.length;
    }
    

    Here's a bog post 用于将随机文本截断到指定行数并附加“查看更多”文本的完整实现。

    【讨论】:

    • 你有没有观察到它是自动换行的,它是如何进行字符换行的?
    【解决方案2】:

    kgaidis 出色答案的粗略快速翻译。

    extension UILabel {
    
        func numberOfCharactersThatFitLabel() -> Int {
            let fontRef = CTFontCreateWithName(self.font.fontName as CFStringRef, self.font.pointSize, nil)
            let attributes = NSDictionary(dictionary: [kCTFontAttributeName : fontRef])
            let attributeString = NSAttributedString(string: text!, attributes: attributes as? [String : AnyObject])
            let frameSetterRef = CTFramesetterCreateWithAttributedString(attributeString as CFAttributedStringRef)
    
            var characterFitRange:CFRange
    
            CTFramesetterSuggestFrameSizeWithConstraints(frameSetterRef, CFRangeMake(0, 0), nil, CGSizeMake(bounds.size.width, CGFloat(numberOfLines)*font.lineHeight), &characterFitRange)
    
            return characterFitRange.length
        }
    }
    

    【讨论】:

      【解决方案3】:

      这是 Swift 4 UITextView 扩展

      extension UITextView {
      
          func numberOfCharactersThatFitTextView() -> Int {
              let fontRef = CTFontCreateWithName(font!.fontName as CFString, font!.pointSize, nil)
              let attributes = [kCTFontAttributeName : fontRef]
              let attributedString = NSAttributedString(string: text!, attributes: attributes as [NSAttributedStringKey : Any])
              let frameSetterRef = CTFramesetterCreateWithAttributedString(attributedString as CFAttributedString)
      
              var characterFitRange: CFRange = CFRange()
      
              CTFramesetterSuggestFrameSizeWithConstraints(frameSetterRef, CFRangeMake(0, 0), nil, CGSize(width: bounds.size.width, height: bounds.size.height), &characterFitRange)
              return Int(characterFitRange.length)
      
          }
      }
      

      如果文本超出预期,可以尝试调整CTFramesetterSuggestFrameSizeWithConstraints函数参数中的高度值。

      【讨论】:

        【解决方案4】:

        这有点复杂,因为有些字母比其他字母宽。但是您可以使用sizeWithAttributes-方法检查字符串的宽度:

        var yourString: String = textField.text
        let myString: NSString = originalString as NSString
        
        //Set your font and add attributes if needed.
        let stringSize: CGSize = myString.sizeWithAttributes([NSFontAttributeName: yourFont])
        

        现在您会收到一个 CGSize,您可以检查宽度是否比您的文本字段宽。

        if(sizeOfYourTextfield < stringSize){
          //String is too large for your UITextField
        }
        

        【讨论】:

        • 我能得到指定大小内的字符串范围吗?
        • 是的,但我认为唯一的可能性是遍历字母并检查它们是否仍然合适。
        • 我建议您循环并删除字符串的最后一个字符,并在每个字母后检查字符串的大小是否仍然太大。
        • 要求是模仿Facebook继续阅读的行为。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-11-08
        • 2019-01-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多