Afin de supporter le protocole UIAccessibilityReadingContent
, j'ai besoin de mon UITextView pour répondre à mes questions sur ses lignes. Ce sont les methods du protocole que j'ai besoin de mettre en œuvre:
accessibilityLineNumberForPoint:
<- Fourni une coordonnée, returnne un numéro de ligne accessibilityContentForLineNumber:
<- Retourne le text d'une ligne donnée accessibilityFrameForLineNumber:
<- Étant donné un numéro de ligne, returnne son cadre accessibilityPageContent
<- Tout le contenu du text. Que j'ai. 🙂 Je pense que NSLayoutManager peut m'aider, mais je n'en ai pas l'expérience. J'en ai compris quelques-uns (je pense), mais j'ai quand même besoin d'aide.
Apple a un exemple de code ( ici ) qui peut me donner le nombre de lignes dans la vue du text:
NSLayoutManager *layoutManager = [textView layoutManager]; unsigned numberOfLines, index, numberOfGlyphs = [layoutManager numberOfGlyphs]; NSRange lineRange; for (numberOfLines = 0, index = 0; index < numberOfGlyphs; numberOfLines++){ (void) [layoutManager lineFragmentRectForGlyphAtIndex:index effectiveRange:&lineRange]; index = NSMaxRange(lineRange); }
Je me lineRange
qu'avec lineRange
ci-dessus, je peux calculer les rects de ligne en utilisant cette méthode sur NSLayoutManager
:
- (NSRect)boundingRectForGlyphRange:(NSRange)glyphRange inTextContainer:(NSTextContainer *)container
Et étant donné lineRanges
je devrais être capable de calculer le numéro de ligne pour un point en utilisant (en trouvant le lineRange
qui contient l'index glyphe:
- (NSUInteger)glyphIndexForPoint:(CGPoint)point inTextContainer:(NSTextContainer *)container fractionOfDistanceThroughGlyph:(CGFloat *)partialFraction
Donc ce qui rest est, comment puis-je get le contenu d'une ligne (comme un NSSsortingng
), donné un numéro de ligne?
en pensant à une solution facile, voici un petit code qui reproduit ce dont vous avez besoin
- (void)parsing:(UITextView *)textView { NSLayoutManager *layoutManager = [textView layoutManager]; NSSsortingng *ssortingng = textView.text; unsigned numberOfLines, index, ssortingngLength = [ssortingng length]; NSMutableArray *ranges = [NSMutableArray new]; NSMutableArray *frames = [NSMutableArray new]; for (index = 0, numberOfLines = 0; index < ssortingngLength; numberOfLines++) { NSRange tmprange; NSRange range = [ssortingng lineRangeForRange:NSMakeRange(index, 0)]; CGRect rect = [layoutManager lineFragmentRectForGlyphAtIndex:index effectiveRange:&tmprange]; [ranges addObject:[NSValue valueWithRange:range]]; [frames addObject:[NSValue valueWithCGRect:rect]]; index = NSMaxRange(range); } self.ranges = ranges; self.frames = frames; self.numberOfLines = numberOfLines; }
S'il vous plaît jeter un oeil des propriétés:
self.ranges = ranges; self.frames = frames; self.numberOfLines = numberOfLines;
Vous pouvez avoir les éléments suivants dans votre class pour créer ces propriétés:
@property (nonatomic) NSInteger numberOfLines; @property (strong, nonatomic) NSArray *ranges; @property (strong, nonatomic) NSArray *frames;
Je vous suggère d'append l'appel d'parsing dans le délégué suivant:
- (void)textViewDidChange:(UITextView *)textView
Vous pouvez par exemple après l'parsing get le cadre de la 2ème ligne en train de faire: self.frames [1]
Ou get le text de la deuxième ligne en train de faire: [textView.text subssortingngWithRange: [self.ranges [1] rangeValue]]
Par exemple comme ceci:
if (self.numberOfLines > 1) { NSRange range = [self.ranges[1] rangeValue]; NSLog(@"2nd line = %@", [textView.text subssortingngWithRange:range]); NSLog(@"2nd line frame = %@", self.frames[1]); }
Ayant tous les frameworks dans self.frames je pense que vous pouvez facilement faire l'autre chose, devinez le numéro de ligne en utilisant une coordonnée.