Freigeben über


TextKit in Xamarin.iOS

TextKit ist eine neue API, die leistungsstarke Textlayout- und Renderingfunktionen bietet. Es basiert auf dem Core-Text-Framework auf niedriger Ebene, ist aber viel einfacher zu verwenden als Core Text.

Um die Features von TextKit für Standardsteuerelemente verfügbar zu machen, wurden mehrere iOS-Textsteuerelemente für die Verwendung von TextKit neu implementiert, darunter:

  • UITextView
  • UITextField
  • UILabel

Aufbau

TextKit bietet eine mehrschichtige Architektur, die den Textspeicher vom Layout und der Anzeige trennt, einschließlich der folgenden Klassen:

  • NSTextContainer – Stellt das Koordinatensystem und die Geometrie bereit, das zum Layouttext verwendet wird.
  • NSLayoutManager – Gliedert Text, indem Text in Glyphen umgewandelt wird.
  • NSTextStorage – Enthält die Textdaten sowie behandelt Batch-Texteigenschaftenaktualisierungen. Alle Batchaktualisierungen werden dem Layout-Manager zur tatsächlichen Verarbeitung der Änderungen übergeben, z. B. das Neuberechnen des Layouts und das Neurapen des Texts.

Diese drei Klassen werden auf eine Ansicht angewendet, die Text rendert. Die integrierten Textverarbeitungsansichten, zUITextViewUITextField. B. , und UILabel sie sind bereits festgelegt, sie können aber auch auf jede UIView Instanz erstellt und angewendet werden.

Die folgende Abbildung veranschaulicht diese Architektur:

In dieser Abbildung wird die TextKit-Architektur veranschaulicht.

Textspeicher und Attribute

Die NSTextStorage Klasse enthält den Text, der von einer Ansicht angezeigt wird. Außerdem werden änderungen an dem Text , z. B. Änderungen an Zeichen oder deren Attributen, an den Layout-Manager für die Anzeige übermittelt. NSTextStorage erbt von einer MSMutableAttributed Zeichenfolge, sodass Änderungen an Textattributen in Batches zwischen BeginEditing und EndEditing Aufrufen angegeben werden können.

Der folgende Codeausschnitt gibt beispielsweise eine Änderung der Vordergrund- bzw. Hintergrundfarben an und zielt auf bestimmte Bereiche ab:

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 ();

Nach EndEditing dem Aufruf werden die Änderungen an den Layout-Manager gesendet, wodurch wiederum alle erforderlichen Layout- und Renderingberechnungen ausgeführt werden, damit der Text in der Ansicht angezeigt wird.

Layout mit Ausschlusspfad

TextKit unterstützt auch das Layout und ermöglicht komplexe Szenarien wie mehrspaltigen Text und fließenden Text um angegebene Pfade, die als Ausschlusspfade bezeichnet werden. Ausschlusspfade werden auf den Textcontainer angewendet, der die Geometrie des Textlayouts ändert, wodurch der Text um die angegebenen Pfade fließt.

Zum Hinzufügen eines Ausschlusspfads muss die ExclusionPaths Eigenschaft im Layout-Manager festgelegt werden. Das Festlegen dieser Eigenschaft bewirkt, dass der Layout-Manager das Textlayout ungültig macht und den Text um den Ausschlusspfad fließt.

Ausschluss basierend auf einem CGPath

Berücksichtigen Sie die folgende UITextView Unterklassenimplementierung:

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);
            }
        }
    }
}

Dieser Code fügt Unterstützung für das Zeichnen in der Textansicht mithilfe von Core Graphics hinzu. Da die Klasse jetzt für die UITextView Verwendung von TextKit für das Textrendering und -layout erstellt wurde, kann sie alle Features von TextKit verwenden, z. B. das Festlegen von Ausschlusspfaden.

Wichtig

In diesem Beispiel werden Unterklassen zum Hinzufügen von Touchzeichnungsunterstützung verwendet UITextView . Unterklassen UITextView sind nicht erforderlich, um die Features von TextKit abzurufen.

Nachdem der Benutzer die Textansicht gezeichnet hat, wird das Zeichnen CGPath auf eine UIBezierPath Instanz angewendet, indem die UIBezierPath.CGPath Eigenschaft festgelegt wird:

bezierPath.CGPath = exclusionPath;

Durch das Aktualisieren der folgenden Codezeile wird das Textlayout um den Pfad aktualisiert:

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

Der folgende Screenshot veranschaulicht, wie sich das Textlayout um den gezeichneten Pfad ändert:

Dieser Screenshot veranschaulicht, wie sich das Textlayout ändert, um den gezeichneten Pfad zu fließen.

Beachten Sie, dass die Eigenschaft des AllowsNonContiguousLayout Layout-Managers in diesem Fall auf "false" festgelegt ist. Dadurch wird das Layout für alle Fälle neu berechnet, in denen sich der Text ändert. Wenn Sie dies auf "true" festlegen, kann dies von der Leistung profitieren, indem Sie eine Volllayoutaktualisierung vermeiden, insbesondere bei großen Dokumenten. Die Einstellung AllowsNonContiguousLayout auf "true" würde jedoch verhindern, dass der Ausschlusspfad das Layout unter bestimmten Umständen aktualisiert, z. B. wenn Text zur Laufzeit ohne nachfolgende Wagenrücklauf vor dem Festlegen des Pfads eingegeben wird.