TextKit dans Xamarin.iOS
TextKit est une nouvelle API qui offre de puissantes fonctionnalités de disposition et de rendu de texte. Il s’appuie sur l’infrastructure texte de base de bas niveau, mais il est beaucoup plus facile à utiliser que le texte principal.
Pour rendre les fonctionnalités de TextKit disponibles pour les contrôles standard, plusieurs contrôles de texte iOS ont été réinscrits pour utiliser TextKit, notamment :
- UITextView
- UITextField
- UILabel
Architecture
TextKit fournit une architecture en couches qui sépare le stockage de texte de la disposition et de l’affichage, y compris les classes suivantes :
NSTextContainer
: fournit le système de coordonnées et la géométrie utilisés pour la disposition du texte.NSLayoutManager
: met en place le texte en transformant le texte en glyphes.NSTextStorage
: contient les données de texte et gère les mises à jour des propriétés de texte par lot. Toutes les mises à jour par lots sont transmises au gestionnaire de disposition pour le traitement réel des modifications, comme le recalcul de la disposition et le redessinage du texte.
Ces trois classes sont appliquées à une vue qui affiche le texte. Les vues de gestion de texte intégrées, telles que UITextView
, UITextField
et UILabel
les ont déjà définies, mais vous pouvez également les créer et les appliquer à n’importe quel UIView
instance.
La figure suivante illustre cette architecture :
Stockage de texte et attributs
La NSTextStorage
classe contient le texte affiché par une vue. Il communique également toutes les modifications apportées au texte (par exemple, les modifications apportées aux caractères ou à leurs attributs) au gestionnaire de disposition pour l’affichage. NSTextStorage
hérite de MSMutableAttributed
la chaîne, ce qui permet de spécifier les modifications apportées aux attributs de texte dans les lots entre BeginEditing
les appels et .EndEditing
Par exemple, l’extrait de code suivant spécifie une modification des couleurs de premier plan et d’arrière-plan, respectivement, et cible des plages particulières :
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 ();
Après EndEditing
avoir été appelées, les modifications sont envoyées au gestionnaire de disposition, qui effectue à son tour les calculs de disposition et de rendu nécessaires pour que le texte soit affiché dans la vue.
Disposition avec chemin d’exclusion
TextKit prend également en charge la disposition et permet des scénarios complexes tels que le texte à plusieurs colonnes et le texte circulant autour des chemins d’accès spécifiés appelés chemins d’exclusion. Les chemins d’exclusion sont appliqués au conteneur de texte, ce qui modifie la géométrie de la disposition du texte, ce qui entraîne la circulation du texte autour des chemins spécifiés.
L’ajout d’un chemin d’exclusion nécessite la définition de la ExclusionPaths
propriété sur le gestionnaire de disposition. La définition de cette propriété entraîne l’invalidation de la disposition du texte par le gestionnaire de disposition et le déplacement du texte autour du chemin d’exclusion.
Exclusion basée sur un CGPath
Envisagez l’implémentation de la sous-classe suivante 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);
}
}
}
}
Ce code ajoute la prise en charge du dessin sur l’affichage texte à l’aide de Core Graphics. Étant donné que la UITextView
classe est désormais conçue pour utiliser TextKit pour son rendu et sa disposition de texte, elle peut utiliser toutes les fonctionnalités de TextKit, telles que la définition de chemins d’exclusion.
Important
Cet exemple de sous-classes UITextView
pour ajouter la prise en charge du dessin tactile. La sous-classe UITextView
n’est pas nécessaire pour obtenir les fonctionnalités de TextKit.
Une fois que l’utilisateur dessine sur la vue texte, le dessin CGPath
est appliqué à un UIBezierPath
instance en définissant la UIBezierPath.CGPath
propriété :
bezierPath.CGPath = exclusionPath;
La mise à jour de la ligne de code suivante met à jour la disposition du texte autour du chemin d’accès :
TextContainer.ExclusionPaths = new UIBezierPath[] { bezierPath };
La capture d’écran suivante montre comment la disposition du texte change pour circuler dans le chemin dessiné :
Notez que la propriété du gestionnaire de AllowsNonContiguousLayout
disposition a la valeur false dans ce cas. Cela entraîne le recalcul de la disposition pour tous les cas où le texte est modifié. La définition de cette valeur sur true peut améliorer les performances en évitant une actualisation complète de la mise en page, en particulier dans le cas de documents volumineux. Toutefois, la définition de la valeur AllowsNonContiguousLayout
true empêche le chemin d’exclusion de mettre à jour la disposition dans certaines circonstances, par exemple, si du texte est entré au moment de l’exécution sans retour chariot de fin avant la définition du chemin d’accès.