更改 UITextView 字体而不删除粗体/下划线/斜体格式



我在iOS应用程序中有一个UITextView,我想允许用户随意加粗/斜体/下划线/等,所以我在文本视图上将allowsEditTextAttributes属性设置为true。但是,我也想允许用户更改字体和颜色等内容。目前,似乎即使更改UITextView的颜色属性也会重置UITextView的格式(即摆脱粗体/斜体/等)。有没有办法在不重置格式的情况下更改此设置?作为参考,我目前正在这样做来更改颜色:

self.textView.textColor = colorTheUserPicked //a UIColor picked by the user

编辑:实际上,这是我的错,当我更改颜色时,我也在重置文本属性本身的值。删除它允许我根据需要更改颜色。但是,如果不删除粗体/斜体/等,我仍然无法更改字体甚至字体大小。不过,我意识到这可能是不可能的...

我会用 Objective-C 解决方案来回答,因为我不会用 Swift 编码,但它应该很容易翻译成 Swift。

NSAttributedString"效果"存储在NSDictionary中。所以它是一个键:值系统(键的单一性)。
粗体/斜体(从您的示例中)在NSFontAttributedName的值内。这就是为什么你不能像这样再次设置它。

主要关键是使用enumerateAttributesInRange:options:usingBlock:

[attr enumerateAttributesInRange:NSMakeRange(0, [attr length])
                         options:NSAttributedStringEnumerationLongestEffectiveRangeNotRequired
                      usingBlock:^(NSDictionary *attributes, NSRange range, BOOL *stop)
 {
     NSMutableDictionary *newAttributes = [attributes mutableCopy];
    //Do changes
    [attr addAttributes:newAttributes range:range]; //Apply effects
 }];

以下行位于"//执行更改"位置。因此,如果要更改字体大小:

if ([newAttributes objectForKey:NSFontAttributeName])
{
    UIFont *currentFont = (UIFont *)[attributes objectForKey:NSFontAttributeName];
    UIFont *newFont = [UIFont fontWithName:[currentFont fontName] size:[currentFont pointSize]*0.5];//Here, I multiplied the previous size with 0.5
    [newAttributes setValue:newFont forKey:NSFontAttributeName];
}

如果你想粗体/斜体等字体你可能感兴趣的UIFontDescriptor,以及一个相关的问题。

它向您展示了如何获取以前的字体并更改获取具有前一个字体的一些共同点的新字体。

如果要更改颜色:

if ([newAttributes objectForKey:NSForegroundColorAttributeName])//In case if there is some part of the text without color that you don't want to override, or some custom- things
{
     UIColor *newColor = [UIColor blueColor];
    [newAttributes setValue:newColor forKey:NSForegroundColorAttributeName];
}

下划线效果在 NSUnderlineStyleAttributeName 的值中。所以可以做类比的改变。

谢谢@Larme!你的解决方案是正确的,所以我接受了它!以下是 Swift 版本供参考:

//needs to be a mutable attributed string
var mutableCopy = NSMutableAttributedString(attributedString: textView.attributedText)
//make range
var textRange = NSMakeRange(0, textView.attributedText.length)
//get all the string attributes
textView.attributedText.enumerateAttributesInRange(textRange, options: NSAttributedStringEnumerationOptions.LongestEffectiveRangeNotRequired, usingBlock: { (attributes, range, stop) -> Void in
    //make a copy of the attributes we can edit
    var newAttributes = attributes as [NSObject : AnyObject]
    if newAttributes[NSFontAttributeName] != nil { //if the font attr exists
        //create a new font with the old font name and new size
        let currentFont = newAttributes[NSFontAttributeName] as UIFont
        let newFont = UIFont(name: currentFont.fontName, size: currentFont.pointSize * 0.5) //set new font size to half of old size
        //replace the nsfontattribute's font with the new one
        newAttributes[NSFontAttributeName] = newFont
    }
    //replace the old attributes with the new attributes to the mutable version
    mutableCopy.addAttributes(newAttributes, range: range)
})
//replace the old attributed text with the newly attributed text
textView.attributedText = mutableCopy

为 Xamarin.IOS 的 C# 实现类似。

    NSError error = null;
        var htmlString = new NSAttributedString(NSUrl.FromFilename(
            "About.html"),
            new NSAttributedStringDocumentAttributes {DocumentType = NSDocumentType.HTML},
            ref error);
        var mutableCopy = new NSMutableAttributedString(htmlString);
        htmlString.EnumerateAttributes(new NSRange(0, htmlString.Length),
            NSAttributedStringEnumeration.LongestEffectiveRangeNotRequired,
            (NSDictionary attributes, NSRange range, ref bool stop) =>
            {
                var newMutableAttributes = new NSMutableDictionary(attributes);
                if (newMutableAttributes[UIStringAttributeKey.Font] != null)
                {
                    var currentFont = newMutableAttributes[UIStringAttributeKey.Font] as UIFont;
                    if (currentFont != null)
                    {
                            var newFontName = currentFont.Name;
                            if (currentFont.Name.Equals("TimesNewRomanPS-BoldItalicMT"))
                            {
                                newFontName = "HelveticaNeue-BoldItalic";
                            }
                            else if (currentFont.Name.Equals("TimesNewRomanPS-ItalicMT"))
                            {
                                newFontName = "HelveticaNeue-Italic";
                            }
                            else if (currentFont.Name.Equals("TimesNewRomanPS-BoldMT"))
                            {
                                newFontName = "HelveticaNeue-Bold";
                            }
                            else if (currentFont.Name.Equals("TimesNewRomanPSMT"))
                            {
                                newFontName = "HelveticaNeue";
                            }
                            newMutableAttributes.SetValueForKey(UIFont.FromName(newFontName, currentFont.PointSize * 1.5f), UIStringAttributeKey.Font); //  = newFont;
                    }
                    else
                    {
                        newMutableAttributes.SetValueForKey(UIFont.FromName("HelveticaNeue", 14), UIStringAttributeKey.Font); //  Default to something.
                    }
                }
                mutableCopy.AddAttributes(newMutableAttributes, range);
            });
        aboutTextView.AttributedText = mutableCopy;

相关内容

最新更新