TextKit y Aplicaciones

En el desarrollo de iOS, a menudo utilizamos la UITextView UIKit, UITextField, UILabel al texto de la pantalla. Se basan en el motor de gran alcance llamada subyacente de TextKit. Por TextKit, podemos fácilmente modificar el estilo de texto y el diseño, sin necesidad de complejas operaciones directamente Core texto.

Aquí Insertar imagen Descripción

1. ¿Cuál es TextKit

En iOS7, Apple presentó el texto Kit-- un motor de tipografía y el renderizado de texto rápido y moderno. Kit de texto en marco UIKit define un número de clases y acuerdos relacionados, su función principal es proporcionar a la disposición del texto y las funciones de representación para el programa. El texto puede ser almacenada (tienda) por Kit de texto, diseño (diseñar), y con la composición tipográfica más sofisticados (por ejemplo, el espaciado del texto, alineación y envolver similares) para visualizar el contenido del texto.
Kit de Apple texto introducido no está destinado a reemplazar el texto existente Core, Core texto es también un papel importante para el diseño de texto y la representación, que es una tecnología avanzada, pero en la parte inferior, si tenemos que hacer que el contenido de texto directamente cuando el contexto gráfico (contexto gráfico), de rendimiento y facilidad de uso a tener en cuenta, la mejor opción es utilizar Core texto. Y si el uso directo de algunos controles proporcionados por Apple (por ejemplo UITextView, UILabel y UITextField, etc.) para componer el texto, no hay duda de medios marco UIKit API en el kit de texto proporciona.

El papel de 2.TextKit

Las dos funciones más importantes:

  1. diseño de texto
  2. la representación de texto

3.TextKit en clase

Para aprender TextKit necesidad de entender algunas clases que contiene:

Aquí Insertar imagen Descripción

1.Text almacenamiento (NSTextStorage): NSMutableAttributedString subclase, la necesidad de guardar propiedades gráficos y de texto.
2.TextContainer (NSTextContainer): determinar el diseño del área de texto. Generalmente rectangular, pero puede tener subclases para crear otra NSTextContainer como patrón irregular circular, pentagonal, o de otro tipo.
3.Layout Manager (NSLayoutManager): responsable de la representación de texto NSStorage NSTextContainer información de diseño de acuerdo con.
4.TextView generalmente UITextView, etc.

TextKit es un MVC típica (modelo-vista-controlador) Ejemplo:

  1. El controlador : NSLayoutManager. Responsable de la conversión de caracteres NSTextStorage en símbolos de texto, símbolos de texto de acuerdo NSTextContainer de diseño y visualización a la vista
  2. Modelar : NSTextStorage y NSTextContainer. Los primeros tienen que guardar mensajes de texto y la correspondiente fuente, color, tamaño y otros atributos. Este último contiene el texto del área de dibujo.
  3. Ver : la UITextView u otra subclase de UIView

En circunstancias normales, un NSTextStorage, NSLayoutManager, NSTextContainer a-uno:
Aquí Insertar imagen Descripción

También puede haber más NSTextContainer:
Aquí Insertar imagen Descripción

O más NSLayoutManager:
Aquí Insertar imagen Descripción

La aplicación práctica de Demo1: Resalte

efecto:
Aquí Insertar imagen Descripción

  1. Nueva clase HYHighlightTextStorage, heredado de NSTextStorage
  2. subclases NSTextStorage necesitan nuestra propia tienda atribuye cadena variable declarada en HYHighlightTextStorage
NSMutableAttributedString *_mutableAttributedString;

Y reescribe los siguientes cuatro métodos abstractos:

 - (NSString *)string;
 - (NSDictionary *)attributesAtIndex:(NSUInteger)location effectiveRange:(NSRangePointer)range;

 - (void)replaceCharactersInRange:(NSRange)range withString:(NSString *)str;
 - (void)setAttributes:(NSDictionary *)attrs range:(NSRange)range;
  1. Cuando el contenido del almacenamiento de texto, requiere tres pasos:
    (1) primeras llamadas beginEditing método.
    (2) llamando replaceCharactersInRange: withString: o SetAttributes: rango: variando un atributo de carácter o
    endEditing llamada (3) se modifica, el agente llama el caso textStorage Método: willProcessEditing: rango: changeInLength: processEditing y métodos.

código completo:
HYHighlightTextStorage.h

@interface HYHighlightTextStorage : NSTextStorage

@end

HYHighlightTextStorage.m

#import "HYHighlightTextStorage.h"

@implementation HYHighlightTextStorage{
    NSMutableAttributedString *_mutableAttributedString;
    NSRegularExpression *_expression;
}

-(instancetype)init{
    if (self = [super init]) {
        _mutableAttributedString = [[NSMutableAttributedString alloc] init];
        _expression = [NSRegularExpression regularExpressionWithPattern:@"(\\*\\w+(\\s*\\w+)*\\s*\\*)" options:0 error:NULL];
    }
    return self;
}

- (NSString *)string{
    return _mutableAttributedString.string;
}

- (NSDictionary<NSString *,id> *)attributesAtIndex:(NSUInteger)location effectiveRange:(NSRangePointer)range {
    return [_mutableAttributedString attributesAtIndex:location effectiveRange:range];
}

- (void)replaceCharactersInRange:(NSRange)range withString:(NSString *)str {
    [self beginEditing];
    [_mutableAttributedString replaceCharactersInRange:range withString:str];
    [self edited:NSTextStorageEditedCharacters range:range changeInLength:(NSInteger)str.length - (NSInteger)range.length];
    [self endEditing];
}

- (void)setAttributes:(NSDictionary<NSString *,id> *)attrs range:(NSRange)range {
    [self beginEditing];
    [_mutableAttributedString setAttributes:attrs range:range];
    [self edited:NSTextStorageEditedAttributes range:range changeInLength:0];
    [self endEditing];
}

- (void)processEditing {
    [super processEditing];
    //去除当前段落的颜色属性
    NSRange paragaphRange = [self.string paragraphRangeForRange: self.editedRange];
    [self removeAttribute:NSForegroundColorAttributeName range:paragaphRange];
    //根据正则匹配,添加新属性
    [_expression enumerateMatchesInString:self.string options:NSMatchingReportProgress range:paragaphRange usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop) {
        [self addAttribute:NSForegroundColorAttributeName value:[UIColor redColor] range:result.range];
    }];
}

HYHighlightViewController.m

#import "HYHighlightViewController.h"
#import "HYHighlightTextStorage.h"

@interface HYHighlightViewController ()

@property (nonatomic, strong) UITextView *textView;
@property (nonatomic, strong) HYHighlightTextStorage *textStorage;
@property (nonatomic, strong) NSTextContainer *textContainer;
@property (nonatomic, strong) NSLayoutManager *layoutManager;

@end

@implementation HYHighlightViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    _textContainer = [[NSTextContainer alloc] init];
    _layoutManager = [[NSLayoutManager alloc] init];
    _textStorage = [[HYHighlightTextStorage alloc] init];
    
    [_textStorage addLayoutManager:_layoutManager];
    [_layoutManager addTextContainer:_textContainer];
    _textView = [[UITextView alloc] initWithFrame:CGRectMake(10, 100, self.view.bounds.size.width-20, 300) textContainer:_textContainer];
    _textView.backgroundColor = [UIColor lightGrayColor];
    
    [self.view addSubview:_textView];
    [_textStorage replaceCharactersInRange:NSMakeRange(0, 0) withString:@"星号引起来的字符都会被*高亮*,*hello world* 星号引起来的字符都会"];
}

La aplicación práctica de Demo2: Elemento de texto y no textuales elementos de texto

Efecto:
Aquí Insertar imagen Descripción
Al establecer las propiedades exclusionPaths NSTextContainer, se puede proporcionar para llenar el área de texto está prohibido. Esta propiedad es NSArray matriz que contiene un conjunto de datos UIBezierPath, que representa se excluyen todos los caminos. Figura:

Aquí Insertar imagen Descripción

código completo:

#import "HYExclusionViewController.h"

@interface HYExclusionViewController ()

@property (nonatomic, strong) UITextView *textView;
@property (nonatomic, strong) NSTextStorage *textStorage;
@property (nonatomic, strong) NSTextContainer *textContainer;
@property (nonatomic, strong) NSLayoutManager *layoutManager;
@property (nonatomic, strong) UIView *exclusionView;

@end

@implementation HYExclusionViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    _textContainer = [[NSTextContainer alloc] init];
    _layoutManager = [[NSLayoutManager alloc] init];
    _textStorage   = [[NSTextStorage alloc] init];
    
    [_textStorage addLayoutManager:_layoutManager];
    [_layoutManager addTextContainer:_textContainer];
    _textView = [[UITextView alloc] initWithFrame:CGRectZero textContainer:_textContainer];
    _textView.frame = CGRectMake(10, 100, self.view.bounds.size.width-20, 300);
    _textView.backgroundColor = [UIColor lightGrayColor];
    
    [self.view addSubview:_textView];
    NSString *testString = @"a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a a";
    [_textStorage replaceCharactersInRange:NSMakeRange(0, 0) withString:testString];
    
    [self setupExclusion];
}


-(void)setupExclusion{
    //红圆圈
    _exclusionView = [[UIView alloc] initWithFrame:CGRectMake(140, 40, 120, 120)];
    _exclusionView.backgroundColor = [UIColor redColor];
    _exclusionView.layer.cornerRadius = 60;
    [self.textView addSubview:_exclusionView];
    
    CGRect originalPathRect = self.exclusionView.frame;
    CGFloat circle_X = originalPathRect.origin.x - self.textView.textContainerInset.left;
    CGFloat circle_Y = originalPathRect.origin.y - self.textView.textContainerInset.top;
    CGFloat circle_W = originalPathRect.size.width;
    CGFloat circle_H = originalPathRect.size.height;
    CGRect circleRect = CGRectMake(circle_X, circle_Y, circle_W, circle_H);
    
    UIBezierPath *exclusionCirclePath = [UIBezierPath bezierPathWithOvalInRect:circleRect];
    _textContainer.exclusionPaths = @[exclusionCirclePath];
}

La aplicación práctica de Demo3: área de visualización irregulares

Efecto:
Aquí Insertar imagen Descripción
NSTextContainer área de disposición de texto se determina, el valor predeterminado es rectangular, heredado de la nueva HYCustomTextContainer NSTextContainer, reescribiendo la NSTextContainer - (CGRect) lineFragmentRectForProposedRect: atIndex: writingDirection: remainingRect: devuelve el método la posición de cada línea de los tamaños de texto, puede ser región de presentación modificado a una forma deseada, tal como circular.

#import "HYCustomTextContainer.h"

@implementation HYCustomTextContainer

-(CGRect)lineFragmentRectForProposedRect:(CGRect)proposedRect atIndex:(NSUInteger)characterIndex writingDirection:(NSWritingDirection)baseWritingDirection remainingRect:(CGRect *)remainingRect{
    [super lineFragmentRectForProposedRect:proposedRect
                                                 atIndex:characterIndex
                                        writingDirection:baseWritingDirection
                                           remainingRect:remainingRect];
    CGSize size = [self size];

    //圆半径
    CGFloat radius = fmin(size.width, size.height) * 0.5;
    CGFloat y = proposedRect.origin.y;
    CGFloat height = proposedRect.size.height;
    CGFloat width = 0;
    if (proposedRect.origin.y == 0) {
        width = 40.0;
    }else if(proposedRect.origin.y <= 2*radius){
        width = 2 * sqrt(powf(radius,2.0) - powf(fabs(y-radius), 2.0));
    }

    CGFloat x = radius - width/2.0;

    return CGRectMake(x, y, width, height);
}

@end

La aplicación práctica de Demo4: personajes seleccionables UILabel

efecto:
Aquí Insertar imagen Descripción

  1. Nueva HYLabel heredado de UILabel
  2. Inicialización dentro NSTextStorage, NSLayoutManager, NSTextContainer en el proceso de inicialización.
  3. Reescribir drawTextInRect: manera de dejar de lado nuestra propia NSTextContainer en lugar de los controles de la pantalla por defecto.
  4. Reescribir touchesBegan: withEvent: método, haga clic en el juez.

El código completo Código HYLabel.m:

#import "HYLabel.h"

@interface HYLabel()

@property (nonatomic, strong) NSTextStorage *textStorage;
@property (nonatomic, strong) NSLayoutManager *layoutManager;
@property (nonatomic, strong) NSTextContainer *textContainer;

@end

@implementation HYLabel

-(void)setText:(NSString *)text{
    [super setText:text];
    [self setupTextSystem];
    [self.textStorage replaceCharactersInRange:NSMakeRange(0, 0) withString:text];
}

-(void)setAttributedText:(NSAttributedString *)attributedText{
    [super setAttributedText:attributedText];
    [self setupTextSystem];
    [self.textStorage replaceCharactersInRange:NSMakeRange(0, 0) withAttributedString:attributedText];
}

-(instancetype)initWithFrame:(CGRect)frame{
    if (self = [super initWithFrame:frame]) {
        self.userInteractionEnabled = YES;
        [self setupTextSystem];
    }
    return self;
}

-(void)setupTextSystem{
    _textStorage = [[NSTextStorage alloc] init];
    _layoutManager = [[NSLayoutManager alloc] init];
    _textContainer = [[NSTextContainer alloc] init];
    
    [_textStorage addLayoutManager:_layoutManager];
    [_layoutManager addTextContainer:_textContainer];
}

-(void)drawTextInRect:(CGRect)rect{
    NSRange range = NSMakeRange(0, self.textStorage.length);
    [self.layoutManager drawBackgroundForGlyphRange:range atPoint:CGPointMake(0, 0)];
    [self.layoutManager drawGlyphsForGlyphRange:range atPoint:CGPointMake(0, 0)];
}

-(void)layoutSubviews{
    [super layoutSubviews];
    self.textContainer.size = self.bounds.size;
}

-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
    UITouch *touch = touches.anyObject;
    CGPoint point = [touch locationInView:self];
    
    //获取点击的字的index
    NSUInteger glyphIndex = [self.layoutManager glyphIndexForPoint:point inTextContainer:self.textContainer];
    //获取字的rect
    CGRect glyphRect = [self.layoutManager boundingRectForGlyphRange:NSMakeRange(glyphIndex, 1) inTextContainer:self.textContainer];
    //最后判断点击位置是否在该字的显示范围内
    if(CGRectContainsPoint(glyphRect, point)){
        NSUInteger charaterIndex = [self.layoutManager characterIndexForGlyphAtIndex:glyphIndex];
        unichar charater = [[self.textStorage string] characterAtIndex:charaterIndex];
        if ([self.delegate respondsToSelector:@selector(didClickCharater:)]) {
            [self.delegate didClickCharater:charater];
        }
    }
}

@end

La aplicación práctica de Demo5: una demostración más interesante

Internet para ver una demostración más interesante: https://www.jianshu.com/p/e72c441f14f3

参考:
TextKit探究: https://www.jianshu.com/p/3f445d7f44d6
TextKit框架: https://www.jianshu.com/p/a12ecae89d6b
utilizando el kit de texto para dibujar y manejar texto: https://developer.apple .com / biblioteca / archivo / documentación / StringsTextFonts / conceptual / TextAndWebiPhoneOS / CustomTextProcessing / CustomTextProcessing.html # // apple_ref / doc / uid / TP40009542-CH4-SW1
TextKit Buenas Prácticas: https://developer.apple.com/videos/ reproducción / wwdc2018 / 221 /

Publicados 103 artículos originales · ganado elogios 55 · vistas 380 000 +

Supongo que te gusta

Origin blog.csdn.net/dolacmeng/article/details/89095032
Recomendado
Clasificación