更改UITextView字体没有删除粗体/下划线/斜体格式

时间:2015-03-09 11:36:42

标签: ios swift uitextview nsattributedstring

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

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

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

3 个答案:

答案 0 :(得分:2)

我会用Objective-C解决方案回答,因为我没有在Swift中编写代码,但它应该很容易转换成Swift。

NSAttributedString"效果"存储在NSDictionary中。因此,它是一个关键:价值体系(具有Key的独特性) 粗体/斜体(来自您的示例)位于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];
}

如果您想要粗体/斜体等,您可能会对UIFontDescriptora related question感兴趣的字体。

它向您展示如何获取上一个字体并更改获得一个新字体,其中包含一些与前一个字体相同的字体。

如果您想更改颜色:

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的值。所以可以进行类比的改变。

答案 1 :(得分:1)

谢谢@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

答案 2 :(得分:1)

为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;