سؤال

I need to draw a label that has some words in bold, consists of several paragraphs with different paddings and may contain small inline images (e.g. icons and bullets) from resources.

I know I could use NSAttributedString for bold and italic but it doesn't support paragraph margins or line limiting, and I'd rather use HTML/CSS-like solution because I'm getting the styles from server. It also won't allow me to insert my custom images in text without resorting to wrapping them in custom fonts.

Finally, I don't want to use UIWebView for performance reasons.
What MonoTouch libraries or bindings can I use to achieve this?

هل كانت مفيدة؟

المحلول

I was happy to find out Hulu engineers wrote an iOS library that does exactly that. It's called GSFancyText.

In their own words:

Of course we considered other options such as directly using HTML in a UIWebView or using NSAttributedString. But we decided to make our own style/markup parsing and rich-text drawing system, because of the following advantages:

  • It’s faster and consumes less memory than UIWebViews.
  • We can reuse the styles and parsing results in many places.
  • We can easily modify the style or text of a small part of a paragraph.
  • We can potentially extend the system with more fancy features, like Quartz 2D features, animations, gestures, etc.
  • It makes localization simple. For example, a phrase marked as bold might be at a different position in the sentence in Japanese. In this case we can use a single NSLocalizableString to represent a sentence with various styles.
  • It’s easy to extract the plain text, on which we can enable the VoiceOver support.

The library is awesome so we went with creating MonoTouch bindings for it.

Example

First define the styles using a CSS-like string:

var stylesheet = @"
    .green { color: #00ff00; font-weight:bold }
    .gray { color: gray; font-weight:bold }
";

GSFancyText.ParseStyleAndSetGlobal (stylesheet);

Then create a GSFancyText object with a markup string:

var fancyText = new GSFancyText ("<span class=green>Hulu</span> <span class=gray>Plus</span>");

Then you can directly draw this in a customized view:

fancyText.drawInRect (rect);

Or create a GSFancyTextView object to display it

var fancyView = new GSFancyTextView (frame, fancyText);

You can find more examples in GSFancyTextView documentation.

My favorite feature are lambda blocks which allow you to specify a delegate to be called to render a <lambda id=yourhandler width=50 height=50> pseudoelement.

This allows you to insert custom images or do advanced inline drawing yourself.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top