Comment mettre en évidence CoreText avec des colors de surbrillance changeantes?

J'ai une sous-class de UIView qui implémente le code pour dessiner CoreText. Dans l'application, ce UIView est dessiné dans un UIScrollView. Voici le code que j'utilise actuellement dans drawRect: pour rendre un NSAtsortingbutedSsortingng:

CGContextRef context = UIGraphicsGetCurrentContext(); float viewHeight = self.bounds.size.height; CGContextTranslateCTM(context, 0, viewHeight); CGContextScaleCTM(context, 1.0, -1.0); CGContextSetTextMasortingx(context, CGAffineTransformMakeScale(1.0, 1.0)); CGMutablePathRef path = CGPathCreateMutable(); CGRect bounds = CGRectMake(PADDING_LEFT, -PADDING_TOP, self.bounds.size.width-20.0, self.bounds.size.height); CGPathAddRect(path, NULL, bounds); CTFramesetterRef framesetter = CTFramesetterCreateWithAtsortingbutedSsortingng((CFMutableAtsortingbutedSsortingngRef)attrSsortingng); CTFrameRef frame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, 0), path, NULL); CFRelease(framesetter); CFRelease(path); CTFrameDraw(frame, context); 

Dans mon NSAtsortingbutedSsortingng, j'ai certains attributes de text pour colorier le text.

Ce dont j'ai besoin d'aide est conceptuellement, comment cela devrait-il être accompli? Je suis confus par toutes les différentes methods de dessin des frameworks, couches, etc. J'ai essayé de passer en revue plusieurs livres et d'autres ressources, mais j'ai l'printing qu'il me manque des choses de base.

Voici mes exigences:

  1. Les faits saillants doivent évidemment être redessinés au nouvel location lors d'un changement d'orientation.
  2. La couleur de surlignage doit pouvoir être modifiée par programme sur une base de surbrillance individuelle.
  3. Idéalement, pour les performances, je ne veux pas avoir à redessiner tout l'UIView CoreText lorsque je viens de changer la couleur de surbrillance d'une surbrillance.
  4. Les Rects individuels doivent pouvoir être regroupés pour former un seul point culminant puisque les faits saillants peuvent couvrir une gamme qui dépasse une seule ligne CTLine.
  5. Finalement, je veux implémenter UIMenuController sur la vue CoreText donc je crois que les points forts doivent être dessinés sous le CoreIVext UIView?

J'apprécierais grandement toute aide.

Voici ce que j'ai essayé jusqu'ici:

J'ai ajouté un nouveau UIView comme une sous-vue à l'UIScrollView pour contenir les faits saillants. J'ajoute ensuite des UIViews individuels pour les points forts eux-mêmes. Lorsque je crée des surlignages "test" factices, ils apparaissent correctement dans la vue CoreText. Je peux aussi facilement changer la couleur de surbrillance. Cependant, quand je vais acquérir des informations réelles sur les lignes de la vue CoreText pour créer des faits saillants réels, il renvoie zéro lignes. Serait-ce parce que drawRect n'a pas encore fini de dessiner ou quelque chose d'autre?

Voici quelques questions:

  1. Dois-je append un UIView sous forme de sous-vue à UIScrollView pour contenir tous les points forts avec des sous-vues supplémentaires pour chaque surbrillance individuelle? Ensuite, stockez chaque surlignage UIView dans un NSArray nested?
  2. Si je change la couleur d'un surlignage sous l'UIView de CoreText, cela provoquera-t-il le redessin de l'UIView entier? Si oui, comment puis-je concevoir autour de cela?
  3. Il est vrai que si je veux que le CoreText UIView reçoive l'input pour UIMenuController, que je doive placer les objects en surbrillance sous l'UIView de CoreText?

J'ai vu ce projet open source:

https://github.com/Cocoanetics/NSAtsortingbutedSsortingng-Additions-for-HTML

C'est incroyable ce qu'il peut faire, mais c'est beaucoup plus complexe et détaillé que ce dont j'ai besoin. Le code rend chaque exécution de glyphe individuelle en utilisant CoreText et permet la mise en évidence, ce qui est génial. Cependant, j'essaie de garder mon code simple et léger. Je connais très peu de choses sur CoreGraphics, CoreAnimation ou CoreText.

J'ai également vu cette question:

Core Text – Obtenir les coordonnées pixel de NSRange

La réponse à la question fournit les appels pour déterminer les limites d'un Rect pour une gamme donnée dans une ligne donnée. Je pense que je peux comprendre ces appels.

METTRE À JOUR

Voici ce que j'ai fait maintenant. Je suis sûr que c'est faux, mais c'est le seul moyen que j'ai trouvé pour le faire fonctionner …

  1. Créez un UIView en tant que conteneur à append à UIScrollView en tant que sous-vue.
  2. Passez UIView à CoreTextView. Je passe également un tableau de plages de strings à CoreTextView pour indiquer quelles strings doivent être mises en évidence.
  3. Ajoutez CoreTextView en tant que sous-vue de UIScrollView. De cette façon, UIView est sous CoreTextView.
  4. Dans la fonction drawRect: de CoreTextView, je dessine le CoreText. J'appelle ensuite une fonction pour calculer les points forts.
  5. Chaque NSRange est vérifiée par rapport aux lignes et le CGRect de chaque correspondance dans la ligne est calculé.
  6. CGRect est utilisé pour créer un nouvel UIView. Cet UIView est ajouté en tant que sous-vue du conteneur UIView. Il est également ajouté à un NSArray afin que je puisse en garder la trace et modifier la couleur de surbrillance d'une surbrillance individuelle au besoin.

Cela n'appelle pas drawRect chaque fois qu'une surbrillance est ajoutée au conteneur ou que la couleur est modifiée. Cependant, je sais que ce n'est pas une solution idéale. Des problèmes avec cette solution:

  1. Lorsque UIViewController appelle setNeedsDisplay sur le CoreTextView, il n'y a aucun moyen de savoir quand il a fini de dessiner. Je ne peux toujours pas find un moyen de faire un callback pour dire au ViewController qu'il est correct de passer à la tâche suivante.
  2. En ajoutant UIViews à l'autre conteneur UIView, drawRect dessine techniquement des éléments en dehors de son propre rect, ce que je sais est un non non.
  3. Je suis sûr que ce n'est pas la façon la plus performante de le faire, même si cela semble fonctionner plutôt bien.

Votre idée de base n'est pas trop mauvaise pour la mise en évidence. Je ne sais pas si c'est vraiment plus facile que de simplement mettre en évidence les glyphes pendant que vous dessinez, mais ce n'est pas une mauvaise idée, et cela facilite l'activation et la désactivation de la mise en surbrillance, alors c'est plutôt sympa.

Plutôt que de créer beaucoup de vues, placez votre text de base sur un CALayer place. Vous pouvez ensuite créer des couches de mise en évidence supplémentaires pour mettre le text en surbrillance. Cela garde tout à l'intérieur d'une seule vue. Les calques sont beaucoup less chers que les vues. Si vous essayez simplement de mettre en surbrillance le style "surligneur", vous pouvez simplement définir le backgroundColor et le frame pour les calques et vous avez terminé.