如何为UITextField实现类似NSLineBreakByTruncatingHead的东西?

时间:2014-06-04 08:11:31

标签: ios objective-c uitextfield

我需要为此NSLineBreakByTruncatingHead获得与UITextField完全相同的内容。让我们假设原始文本是:

  

这是无法在UITextField

中显示的长文本

我需要它:

  

...无法在UITextField中显示

但目前我得到的结果如下:

  

这是长篇文章,不能......

只是开头的截断。 lineBreakMode未提供UITextField属性。我怎样才能实现它?

2 个答案:

答案 0 :(得分:2)

我采用了解决方案here并对其进行了修改,以截断字符串的头部而不是尾部。知道它只在未编辑字段时显示省略号。

注意:此解决方案仅适用于iOS 7+。要在iOS 6中使用,请在 NSString + TruncateToWidth.m 文件中使用sizeWithFont:代替sizeWithAttributes:
编辑:添加了对iOS 6的支持

<强>的NSString + TruncateToWidth.h

@interface NSString (TruncateToWidth)
- (NSString*)stringByTruncatingToWidth:(CGFloat)width withFont:(UIFont *)font;
@end

<强>的NSString + TruncateToWidth.m

#import "NSString+TruncateToWidth.h"

#define ellipsis @"…"

@implementation NSString (TruncateToWidth)

- (NSString*)stringByTruncatingToWidth:(CGFloat)width withFont:(UIFont *)font
{
    // Create copy that will be the returned result
    NSMutableString *truncatedString = [self mutableCopy];

    // Make sure string is longer than requested width
    if ([self widthWithFont:font] > width)
    {
        // Accommodate for ellipsis we'll tack on the beginning
        width -= [ellipsis widthWithFont:font];

        // Get range for first character in string
        NSRange range = {0, 1};

        // Loop, deleting characters until string fits within width
        while ([truncatedString widthWithFont:font] > width)
        {
            // Delete character at beginning
            [truncatedString deleteCharactersInRange:range];
        }

        // Append ellipsis
        [truncatedString replaceCharactersInRange:NSMakeRange(0, 0) withString:ellipsis];
    }

    return truncatedString;
}

- (CGFloat)widthWithFont:(UIFont *)font
{
    if([self respondsToSelector:@selector(sizeWithAttributes:)])
        return [self sizeWithAttributes:@{NSFontAttributeName:font}].width;
    return [self sizeWithFont:font].width;
}

使用它:

...
// Make sure to import the header file where you want to use it
// assumes instance variable holds your string that populates the field
fieldString = @"abcdefghijklmnopqrstuvwxyz1234567890";
// Size will need to be less than text field's width to account for padding
_myTextField.text = [fieldString stringByTruncatingToWidth:(_myTextField.frame.size.width - 15) withFont:_myTextField.font];
...

// use textFieldShouldBeginEditing to make it animate from the start of the field to the end of the string if you prefer that. I found it a little distracting
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
    textField.text = fieldString;
}

- (BOOL)textFieldShouldEndEditing:(UITextField *)textField
{
    fieldString = textField.text;
    textField.text = [textField.text stringByTruncatingToWidth:(textField.frame.size.width - 15) withFont:textField.font];

    return YES;
}

答案 1 :(得分:0)

我有一个类似的要求,我写了一个@ Stonz2解决方案的Swift版本,它在大多数情况下都有效,尚未在生产中使用,但后来又删除了该要求...无论如何都将其发布在这里

    extension String {

    func stringByTruncatingLeadingForWidth(width: CGFloat, withFont font: UIFont) -> String{

        var modifiedString = self
        var mutableWidth = width
        let ellipsis = "..."
        if (self.widthOfString(usingFont: font) > width) {
            let ellipsisWidth = ellipsis.widthOfString(usingFont: font)

            // else this will go for infinite loop...mutable width will go -ve
            if mutableWidth > ellipsisWidth {
                mutableWidth -= ellipsis.widthOfString(usingFont: font)
            }
            let range = NSMakeRange(0, 1)

            while modifiedString.widthOfString(usingFont: font) > mutableWidth {
                modifiedString.deleteCharactersInRange(range: range)
                print(modifiedString)
                print(mutableWidth)
            }
            guard let swiftRange = Range(NSMakeRange(0, 3), in: modifiedString) else { return ""  }
            modifiedString.replaceSubrange(swiftRange, with: [".",".","."])
        }
        return modifiedString
    }
    func widthOfString(usingFont font: UIFont) -> CGFloat {
        let fontAttributes = [NSAttributedString.Key.font: font]
        let size = self.size(withAttributes: fontAttributes)
        return size.width
    }

    mutating func deleteCharactersInRange(range: NSRange) {
        guard let swiftRange = Range(range, in: self) else { return  }
        self.removeSubrange(swiftRange)
    }
}

var str1 = "Hello how are you"

let newStr = str1.stringByTruncatingLeadingForWidth(width: 100, withFont: .systemFont(ofSize: 15))