Share via


TextKit in Xamarin.iOS

TextKit è una nuova API che offre potenti funzionalità di layout e rendering del testo. Si basa sul framework core text di basso livello, ma è molto più facile da usare rispetto al core text.

Per rendere disponibili le funzionalità di TextKit per i controlli standard, sono stati implementati diversi controlli di testo iOS per l'uso di TextKit, tra cui:

  • UITextView
  • UITextField
  • UILabel

Architettura

TextKit offre un'architettura a più livelli che separa l'archiviazione del testo dal layout e dalla visualizzazione, incluse le classi seguenti:

  • NSTextContainer : fornisce il sistema di coordinate e la geometria utilizzati per il layout del testo.
  • NSLayoutManager – Dispone il testo trasformando il testo in glifi.
  • NSTextStorage : contiene i dati di testo, nonché gestisce gli aggiornamenti delle proprietà di testo batch. Tutti gli aggiornamenti batch vengono passati al gestore layout per l'elaborazione effettiva delle modifiche, ad esempio ricalcolare il layout e ridisegnare il testo.

Queste tre classi vengono applicate a una visualizzazione che esegue il rendering del testo. Le viste di gestione del testo predefinite, ad esempio UITextView, UITextFielde UILabel le hanno già impostate, ma è possibile crearle e applicarle anche a qualsiasi UIView istanza.

La figura seguente illustra questa architettura:

Questa figura illustra l'architettura TextKit

Archiviazione e attributi di testo

La NSTextStorage classe contiene il testo visualizzato da una visualizzazione. Comunica inoltre le modifiche apportate al testo, ad esempio le modifiche apportate ai caratteri o ai relativi attributi, al gestore layout per la visualizzazione. NSTextStorage eredita da MSMutableAttributed stringa, consentendo di specificare le modifiche agli attributi di testo in batch tra BeginEditing e EndEditing chiamate.

Ad esempio, il frammento di codice seguente specifica una modifica ai colori di primo piano e di sfondo, rispettivamente e a intervalli specifici:

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

Dopo EndEditing la chiamata, le modifiche vengono inviate al gestore layout, che a sua volta esegue tutti i calcoli di layout e rendering necessari per il testo da visualizzare nella visualizzazione.

Layout con percorso di esclusione

TextKit supporta anche il layout e consente scenari complessi, ad esempio testo a più colonne e testo scorrevole in percorsi specificati denominati percorsi di esclusione. I percorsi di esclusione vengono applicati al contenitore di testo, che modifica la geometria del layout di testo, causando il flusso del testo nei percorsi specificati.

L'aggiunta di un percorso di esclusione richiede l'impostazione della ExclusionPaths proprietà nel gestore layout. Impostando questa proprietà, il gestore layout invalida il layout di testo e scorre il testo intorno al percorso di esclusione.

Esclusione basata su CGPath

Si consideri l'implementazione della sottoclasse seguente UITextView :

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

Questo codice aggiunge il supporto per il disegno nella visualizzazione testo usando Core Graphics. Poiché la UITextView classe è ora compilata per usare TextKit per il rendering e il layout del testo, può usare tutte le funzionalità di TextKit, ad esempio l'impostazione dei percorsi di esclusione.

Importante

Questa sottoclasse UITextView di esempio consente di aggiungere il supporto per il disegno tocco. La sottoclasse UITextView non è necessaria per ottenere le funzionalità di TextKit.

Dopo che l'utente disegna sulla visualizzazione testo, il disegno CGPath viene applicato a un'istanza UIBezierPath impostando la UIBezierPath.CGPath proprietà :

bezierPath.CGPath = exclusionPath;

L'aggiornamento della riga di codice seguente consente di aggiornare il layout del testo intorno al percorso:

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

Lo screenshot seguente illustra il modo in cui il layout del testo cambia per scorrere il percorso disegnato:

Questo screenshot illustra il modo in cui il layout del testo cambia per scorrere il percorso disegnato

Si noti che la proprietà del AllowsNonContiguousLayout gestore layout è impostata su false in questo caso. In questo modo il layout viene ricalcolato per tutti i casi in cui il testo cambia. L'impostazione di questa proprietà su true può migliorare le prestazioni evitando un aggiornamento con layout completo, in particolare nel caso di documenti di grandi dimensioni. Tuttavia, l'impostazione su AllowsNonContiguousLayout true impedisce al percorso di esclusione di aggiornare il layout in alcune circostanze, ad esempio se il testo viene immesso in fase di esecuzione senza un ritorno a capo finale prima del percorso impostato.