TextKit v Xamarin. iOSTextKit in Xamarin.iOS

TextKit je nové rozhraní API, které nabízí výkonné funkce pro rozložení textu a vykreslování.TextKit is a new API that offers powerful text layout and rendering features. Je postaven na vrcholu základní textové architektury nízké úrovně, ale je mnohem jednodušší použít než základní text.It is built on top of the low-level Core Text framework, but is much easier to use than Core Text.

Pro zpřístupnění funkcí TextKit standardním ovládacím prvkům byly znovu implementovány některé ovládací prvky pro iOS, aby používaly TextKit, včetně:To make the features of TextKit available to standard controls, several iOS text controls have been re-implemented to use TextKit, including:

  • UITextViewUITextView
  • UITextFieldUITextField
  • UILabelUILabel

ArchitekturaArchitecture

TextKit poskytuje vrstvenou architekturu, která odděluje úložiště textu od rozložení a zobrazení, včetně následujících tříd:TextKit provides a layered architecture that separates the text storage from the layout and display, including the following classes:

  • NSTextContainer – Poskytuje souřadnicový systém a geometrii, která se používá k rozložení textu.NSTextContainer – Provides the coordinate system and geometry that is used to layout text.
  • NSLayoutManager – Rozloží text tak, že přepíná text na glyfy.NSLayoutManager – Lays out text by turning text into glyphs.
  • NSTextStorage – Obsahuje textová data a také zpracovává aktualizace vlastností textu v dávce.NSTextStorage – Holds the text data, as well as handles batch text property updates. Všechny aktualizace služby Batch jsou předávány správci rozložení pro skutečné zpracování změn, jako je přepočítání rozložení a překreslení textu.Any batch updates are handed to the layout manager for the actual processing of the changes, such as recalculating the layout and redrawing the text.

Tyto tři třídy jsou aplikovány na zobrazení, které vykresluje text.These three classes are applied to a view that renders text. Integrovaná zobrazení pro zpracování textu, jako například UITextView , UITextField a UILabel již jsou nastavena, ale můžete je vytvořit a použít i u libovolné UIView instance.The built-in text handling views, such as UITextView, UITextField, and UILabel already have them set, but you can create and apply them to any UIView instance as well.

Následující obrázek znázorňuje tuto architekturu:The following figure illustrates this architecture:

Tento obrázek ilustruje architekturu TextKit.

Textové úložiště a atributyText Storage and Attributes

NSTextStorageTřída obsahuje text, který je zobrazen v zobrazení.The NSTextStorage class holds the text that is displayed by a view. Také sděluje všechny změny textu, například změny znaků nebo jejich atributů – do Správce rozložení pro zobrazení.It also communicates any changes to the text - such as changes to characters or their attributes - to the layout manager for display. NSTextStorage dědí z MSMutableAttributed řetězce, což umožňuje, aby byly změny atributů textu zadány v dávkách mezi BeginEditing a EndEditing voláními.NSTextStorage inherits from MSMutableAttributed string, allowing changes to text attributes to be specified in batches between BeginEditing and EndEditing calls.

Například následující fragment kódu určuje změnu barvy popředí a pozadí a cílí na konkrétní rozsahy:For example, the following code snippet specifies a change to the foreground and background colors, respectively, and targets particular ranges:

textView.TextStorage.BeginEditing ();
textView.TextStorage.AddAttribute(UIStringAttributeKey.ForegroundColor, UIColor.Green, new NSRange(200, 400));
textView.TextStorage.AddAttribute(UIStringAttributeKey.BackgroundColor, UIColor.Black, new NSRange(210, 300));
textView.TextStorage.EndEditing ();

Po EndEditing volání se změny odešlou do Správce rozložení, který zase provede všechny potřebné výpočty rozložení a vykreslování pro text, který se má zobrazit v zobrazení.After EndEditing is called, the changes are sent to the layout manager, which in turn performs any necessary layout and rendering calculations for the text to be displayed in the view.

Rozložení s cestou vyloučeníLayout with Exclusion Path

TextKit podporuje také rozložení a umožňuje složitým scénářům, jako je například text ve více sloupcích a přetékání textu kolem zadaných cest s názvem cesty vyloučení.TextKit also supports layout, and allows for complex scenarios such as multi-column text and flowing text around specified paths called exclusion paths. Cesty vyloučení se aplikují na textový kontejner, který upraví geometrii rozložení textu, což způsobí, že se text přesměruje kolem určených cest.Exclusion paths are applied to the text container, which modifies the geometry of the text layout, causing the text to flow around the specified paths.

Přidání cesty vyloučení vyžaduje nastavení ExclusionPaths vlastnosti ve správci rozložení.Adding an exclusion path requires setting the ExclusionPaths property on the layout manager. Nastavení této vlastnosti způsobí, že Správce rozložení neověří rozložení textu a natéká text kolem cesty pro vyloučení.Setting this property causes the layout manager to invalidate the text layout and flow the text around the exclusion path.

Vyloučení na základě CGPathExclusion based on a CGPath

Zvažte následující UITextView implementaci podtříd:Consider the following UITextView subclass implementation:

public class ExclusionPathView : UITextView
{
    CGPath exclusionPath;
    CGPoint initialPoint;
    CGPoint latestPoint;
    UIBezierPath bezierPath;

    public ExclusionPathView (string text)
    {
        Text = text;
        ContentInset = new UIEdgeInsets (20, 0, 0, 0);
        BackgroundColor = UIColor.White;
        exclusionPath = new CGPath ();
        bezierPath = UIBezierPath.Create ();

        LayoutManager.AllowsNonContiguousLayout = false;
    }

    public override void TouchesBegan (NSSet touches, UIEvent evt)
    {
        base.TouchesBegan (touches, evt);

        var touch = touches.AnyObject as UITouch;

        if (touch != null) {
            initialPoint = touch.LocationInView (this);
        }
    }

    public override void TouchesMoved (NSSet touches, UIEvent evt)
    {
        base.TouchesMoved (touches, evt);

        UITouch touch = touches.AnyObject as UITouch;

        if (touch != null) {
            latestPoint = touch.LocationInView (this);
            SetNeedsDisplay ();
        }
    }

    public override void TouchesEnded (NSSet touches, UIEvent evt)
    {
        base.TouchesEnded (touches, evt);

        bezierPath.CGPath = exclusionPath;
        TextContainer.ExclusionPaths = new UIBezierPath[] { bezierPath };
    }

    public override void Draw (CGRect rect)
    {
        base.Draw (rect);

        if (!initialPoint.IsEmpty) {

            using (var g = UIGraphics.GetCurrentContext ()) {

                g.SetLineWidth (4);
                UIColor.Blue.SetStroke ();

                if (exclusionPath.IsEmpty) {
                    exclusionPath.AddLines (new CGPoint[] { initialPoint, latestPoint });
                } else {
                    exclusionPath.AddLineToPoint (latestPoint);
                }

                g.AddPath (exclusionPath);
                g.DrawPath (CGPathDrawingMode.Stroke);
            }
        }
    }
}

Tento kód přidá podporu pro kreslení v zobrazení textu pomocí základní grafiky.This code adds support for drawing on the text view using Core Graphics. Vzhledem UITextView k tomu, že třída je nyní sestavena tak, aby pro vykreslování a rozložení textu používala TextKit, může použít všechny funkce TextKit, jako je například nastavení cest vyloučení.Since the UITextView class is now built to use TextKit for its text rendering and layout, it can use all the features of TextKit, such as setting exclusion paths.

Důležité

Tento příklad podtříd UITextView pro přidání podpory dotykové vykreslování.This example subclasses UITextView to add touch drawing support. Podtříd UITextView není nutné pro získání funkcí TextKit.Subclassing UITextView isn’t necessary to get the features of TextKit.

Poté, co uživatel nakreslí v zobrazení textu, se na instanci použije nakreslený objekt CGPath UIBezierPath nastavením UIBezierPath.CGPath vlastnosti:After the user draws on the text view, the drawn CGPath is applied to a UIBezierPath instance by setting the UIBezierPath.CGPath property:

bezierPath.CGPath = exclusionPath;

Aktualizace následujícího řádku kódu provede aktualizaci rozložení textu kolem cesty:Updating the following line of code makes the text layout update around the path:

TextContainer.ExclusionPaths = new UIBezierPath[] { bezierPath };

Následující snímek obrazovky ukazuje, jak se mění rozložení textu pro tok kolem vykreslené cesty:The following screenshot illustrates how the text layout changes to flow around the drawn path:

Tento snímek obrazovky ukazuje, jak se mění rozložení textu pro tok kolem vykreslené cesty.This screenshot illustrates how the text layout changes to flow around the drawn path

Všimněte si, že AllowsNonContiguousLayout v tomto případě je vlastnost Správce rozložení v tomto případě nastavena na hodnotu false.Notice that the layout manager’s AllowsNonContiguousLayout property is set to false in this case. Tím dojde k přepočítání rozložení pro všechny případy, kdy se text změní.This causes the layout to be recalculated for all cases where the text changes. Nastavení této hodnoty na true může přinést výkon tím, že se vyhne úplné aktualizaci rozložení, zejména v případě rozsáhlých dokumentů.Setting this to true may benefit performance by avoiding a full-layout refresh, especially in the case of large documents. Nastavení AllowsNonContiguousLayout na hodnotu true však zabrání v tom, aby cesta vyloučení v některých případech aktualizovala rozložení. například pokud je text zadán za běhu bez koncového znaku návratu na začátek před nastavenou cestou.However, setting AllowsNonContiguousLayout to true would prevent the exclusion path from updating the layout in some circumstances - for example, if text is entered at runtime without a trailing carriage return prior to the path being set.