Comment faire un texte vertical UILabel et UITextView pour iOS dans Swift?

si vous êtes venu à cette question basée sur le titre mais ne sont pas intéressés par Mongol, vous pourriez être à la recherche de cette Q&R à la place:


J'ai appris Swift afin de développer des applications iOS pour traditionnel mongol . Le problème est que le mongol traditionnel est écrit verticalement de haut en bas et de gauche à droite. Ma question Est de savoir comment afficher le texte à la verticale et avoir encore du travail d'enroulement de ligne?

si vous restez avec moi une minute, j'essaierai d'expliquer le problème plus clairement. Voici une image du type de vue de texte que je voudrais réaliser. Dans le cas où le script étranger vous jette, j'ai inclus le texte anglais qui suit le même modèle. En fait, si l'application est en anglais le texte à afficher, c'est comment il devrait ressembler.

enter image description here

pour une simple UILabel à une ligne, une rotation de 90 degrés dans le sens des aiguilles d'une montre fonctionnerait. Cependant, pour un UITextView multi-ligne, je dois m'occuper de l'enrubannage de ligne. Si je fais une rotation simple de 90 degrés, la première chose écrite finira par être sur la dernière ligne.

Jusqu'à présent j'ai fait un plan qui je pense peut surmonter ce problème:

  1. Faire une police personnalisée dans laquelle toutes les lettres sont reproduites verticalement.
  2. faites pivoter le texte de 90 degrés dans le sens des aiguilles d'une montre.
  3. miroir la vue de texte horizontale.

enter image description here

qui devrait prendre soin de l'enveloppe du texte.

je peux faire la police miroir. Cependant, je ne sais pas comment faire le codage Swift pour la rotation et le mirroring de L'UITextView. J'ai trouvé les liens suivants qui semblent pour donner des indications sur certaines parties de la solution, mais elles sont toutes dans L'Objectif C et pas dans Swift.

il y a des applications traditionnelles mongoles dans l'app store (comme this and this ) mais je n'ai encore trouvé personne qui partage son code source, donc je ne sais pas ce qu'ils font dans les coulisses pour afficher le texte. J'ai l'intention de rendre mon code open source afin qu'il ne soit pas si difficile pour d'autres à l'avenir de développer des applications pour les quelques millions de personnes qui lisent le mongol traditionnel. Toute aide que vous pouvez donner à cette entreprise serait être apprécié, non seulement par moi, mais aussi par le peuple mongol. Même si vous ne vous connaissez pas, il serait utile de revenir sur cette question pour la rendre plus visible.

mise à Jour

la réponse de @sangonz est toujours une bonne réponse, mais je ne l'ai Temporairement pas marquée comme la réponse acceptée parce que je ne pouvais pas tout faire fonctionner. Plus précisément:

  • activer le défilement (soit en incorporant la vue personnalisée dans un scrollview ou par sous-classement UIScrollView ). Dans le projet github, @sangonz dit cela devrait être facile, mais ce n'était pas pour moi.
  • obtenir un relayout (plutôt que d'étirer) des lignes de mot sur un changement d'orientation. Je pense que ça ne devrait pas être trop difficile à résoudre avec un peu plus de recherches.
  • pourquoi les lignes de texte ne vont-elles pas jusqu'au bord de la vue? Il y a un grand vide au fond.
  • Comment faire déverrouillez le NSTextStorage de la vue verticale personnalisée à partir de l'autre vue UITextView. (voir cette question )

Jusqu'à ce point j'ai utilisé la méthode originale j'ai proposé ci-dessus, mais ce que je veux vraiment est d'obtenir quelque chose comme ce que @sangonz proposé de travailler.

j'envisage aussi d'autres méthodes comme

46
demandé sur Community 2015-02-16 18:24:39

2 réponses

Edit: C'est la façon dont je l'ai enfin fait.

Voici une implémentation très basique dans mon GitHub: Vertical-Text-iOS .

Rien de fantaisie, mais il fonctionne. Finalement j'ai dû mélanger TextKit et traitement d'image. Jetez un coup d'oeil au code. Il s'agit de:

  1. sous-classement NSTextContainer pour obtenir les bonnes dimensions du texte.
  2. créant un personnalisez UIView pour rendre le texte en appliquant des transformations affine à chaque ligne et en utilisant NSLayoutManager pour conserver toutes les fonctionnalités de TextKit.

TextKit way

la bonne façon de conserver tous les avantages du texte natif (par exemple, Mise en évidence, sélection... est d'utiliser le standard TextKit Api. La méthode que vous proposez briserait tout cela ou pourrait entraîner un comportement étrange.

cependant, on dirait que TextKit dans iOS ne supporte pas encore l'orientation verticale, mais il est préparé pour cela. Comme note d'accompagnement, dans OS X il est quelque peu soutenu et vous pourriez appeler textView.setLayoutOrientation(.Vertical) , mais il a encore quelques limites.

le protocole NSTextLayoutOrientationProvider définit une interface fournir l'orientation par défaut pour le texte mis en conformité objet, en l'absence d'un NSVerticalGlyphFormAttributeName explicite" attribut. Le seul UIKit la classe qui implémente cette interface est NSTextContainer , dont l'implémentation par défaut renvoie NSTextLayoutOrientationHorizontal . Une sous-classe NSTextContainer qui poignées verticales texte pourrait définir cette propriété pour NSTextLayoutOrientationVertical pour supporter le layout personnalisé logique d'orientation.

Source: UIKit > NSTextLayoutOrientationProvider référence de protocole pour iOS

en conclusion , vous devez commencer à sousclasser NSTextContainer , et vous aurez à traiter avec NSLayoutManager et NSTextContainer beaucoup.


personnalisation de l'image traitement de la manière

Si, d'autre part, vous décidez de suivre votre texte personnalisé rendu, je propose l'approche suivante.

  1. rend le texte normal à une couche cachée avec une police normale. Donner la taille correcte pour sa boite.
  2. Obtenir les propriétés du texte , principalement le texte de la hauteur et l'espacement des lignes.
  3. traiter l'image dessiner chaque ligne dans l'ordre inverse de bas en haut comme vous pouvez le voir dans l'image ci-dessous. Vous devriez obtenir un nouveau CGImage comme résultat.
  4. tourner l'image créer un UIImage et définir la valeur correcte UIImageOrientation .
  5. insérer cette image dans un UIScrollView qui ne permet que le défilement horizontal.

Attention cette méthode rend le texte entier, donc ne l'utilisez pas pour des textes très longs. Si vous avez besoin de le faire, vous devrez tenir compte d'un carrelage approche. Regarder WWDC 2013 > 217-exploration des Scroll Views sur iOS 7 .

this image

bonne chance!

mise à Jour: (image à partir de github du projet)

enter image description here

19
répondu sangonz 2015-06-01 14:08:22

si vous voulez faire tourner le texte, je vous suggérerais d'utiliser une mise en page droite-à-gauche de sorte que vous puissiez sauter l'étape de miroir (et juste tourner dans l'autre sens).

vous devriez être en mesure de définir la propriété transform de label/textview:

view.transform = CGAffineTransformTranslate(CGAffineTransformMakeRotation(CGFloat(-M_PI_2)), view.bounds.width, view.bounds.height)

vous devez traduire après que vous tournez parce que la vue tourne autour de son origine (en haut à gauche).

La bonne nouvelle, c'est que les gestes et les robinets sont transformés en même temps les pixels sont, donc les commandes continuent à fonctionner comme vous l'attendez.

3
répondu Frank Schmitt 2015-02-26 17:26:30