TextKit w środowisku Xamarin.iOS
TextKit to nowy interfejs API, który oferuje zaawansowany układ tekstu i funkcje renderowania. Jest on oparty na strukturze tekstu podstawowego niskiego poziomu, ale jest znacznie łatwiejszy w użyciu niż podstawowy tekst.
Aby udostępnić funkcje zestawu TextKit do standardowych kontrolek, kilka kontrolek tekstu systemu iOS zostało ponownie zaimplementowanych w celu użycia zestawu TextKit, w tym:
- UITextView
- UITextField
- UILabel
Architektura
TextKit udostępnia architekturę warstwową, która oddziela magazyn tekstu od układu i wyświetlania, w tym następujące klasy:
NSTextContainer
— udostępnia układ współrzędnych i geometrię używaną do układu tekstu.NSLayoutManager
— Określa tekst, zamieniając tekst na glify.NSTextStorage
— przechowuje dane tekstowe, a także obsługuje aktualizacje właściwości tekstu wsadowego. Wszystkie aktualizacje wsadowe są przekazywane do menedżera układu w celu rzeczywistego przetwarzania zmian, takich jak ponowne obliczanie układu i ponowne rysowanie tekstu.
Te trzy klasy są stosowane do widoku, który renderuje tekst. Wbudowane widoki obsługi tekstu, takie jak UITextView
, UITextField
i UILabel
mają już ustawione, ale można je również utworzyć i zastosować do dowolnego UIView
wystąpienia.
Na poniższej ilustracji przedstawiono tę architekturę:
Magazyn tekstu i atrybuty
Klasa NSTextStorage
przechowuje tekst wyświetlany przez widok. Komunikuje również wszelkie zmiany w tekście — takie jak zmiany znaków lub ich atrybutów — do menedżera układu na potrzeby wyświetlania. NSTextStorage
dziedziczy z MSMutableAttributed
ciągu, co umożliwia określenie zmian atrybutów tekstowych w partiach między wywołaniami BeginEditing
i EndEditing
.
Na przykład poniższy fragment kodu określa zmianę odpowiednio kolorów pierwszego planu i tła oraz elementów docelowych dla określonych zakresów:
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
wywołaniu zmiany są wysyłane do menedżera układu, co z kolei wykonuje wszelkie niezbędne obliczenia układu i renderowania tekstu, które mają być wyświetlane w widoku.
Układ ze ścieżką wykluczenia
Zestaw TextKit obsługuje również układ i umożliwia wykonywanie złożonych scenariuszy, takich jak tekst wielokolumny i przepływ tekstu wokół określonych ścieżek nazywanych ścieżkami wykluczeń. Ścieżki wykluczeń są stosowane do kontenera tekstowego, który modyfikuje geometrię układu tekstu, co powoduje przepływ tekstu wokół określonych ścieżek.
Dodanie ścieżki wykluczenia wymaga ustawienia ExclusionPaths
właściwości w menedżerze układu. Ustawienie tej właściwości powoduje, że menedżer układu unieważnia układ tekstu i przepływa tekstu wokół ścieżki wykluczenia.
Wykluczenie oparte na CGPath
Rozważmy następującą UITextView
implementację podklasy:
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);
}
}
}
}
Ten kod dodaje obsługę rysowania w widoku tekstowym przy użyciu podstawowej grafiki. UITextView
Ponieważ klasa jest teraz kompilowana do używania zestawu TextKit do renderowania i układu tekstu, może używać wszystkich funkcji zestawu TextKit, takich jak ustawianie ścieżek wykluczeń.
Ważne
Te przykładowe podklasy UITextView
do dodawania obsługi rysunku dotykowego. Podklasy UITextView
nie jest konieczne, aby uzyskać funkcje zestawu TextKit.
Gdy użytkownik narysuje widok tekstu, zostanie CGPath
zastosowany do UIBezierPath
wystąpienia, ustawiając UIBezierPath.CGPath
właściwość :
bezierPath.CGPath = exclusionPath;
Aktualizacja następującego wiersza kodu powoduje, że układ tekstu jest aktualizowany wokół ścieżki:
TextContainer.ExclusionPaths = new UIBezierPath[] { bezierPath };
Na poniższym zrzucie ekranu pokazano, jak układ tekstu zmienia się w przepływie wokół narysowanej ścieżki:
Zwróć uwagę, że właściwość menedżera układów AllowsNonContiguousLayout
jest ustawiona na wartość false w tym przypadku. Powoduje to ponowne obliczenie układu we wszystkich przypadkach, w których zmienia się tekst. Ustawienie wartości true może przynieść wydajność, unikając pełnego odświeżania układu, zwłaszcza w przypadku dużych dokumentów. Jednak ustawienie AllowsNonContiguousLayout
wartości true uniemożliwiłoby zaktualizowanie układu przez ścieżkę wykluczenia w pewnych okolicznościach — na przykład jeśli tekst zostanie wprowadzony w czasie wykonywania bez końcowego powrotu karetki przed ustawieniem ścieżki.