Créer appuyez sur-mesure “liens” dans la NSAttributedString d'un UILabel?
J'ai été chercher cela pendant des heures, mais j'ai échoué. Je ne sais même pas ce que je devrais être à la recherche pour.
De nombreuses applications, le texte et dans le texte sont web des hyperliens dans les arrondis rect. Lorsque je clique sur eux UIWebView
s'ouvre. Ce qui m'intrigue, c'est qu'ils ont souvent des liens personnalisés, par exemple si les mots commence par # il est également cliquables et l'application répond par l'ouverture d'un autre point de vue. Comment puis-je le faire? Est-il possible avec UILabel
, ou dois-je UITextView
ou autre chose?
- Voir: stackoverflow.com/questions/50505334/... pour un travail entièrement
Swift 4
solution. Il utiliseUITextView
mais lui permet de se comporter comme unUILabel
. J'ai essayé les solutions ici, et impossible d'obtenir la précision de détection de liaison.
Vous devez vous connecter pour publier un commentaire.
En général, si nous voulons avoir un lien cliquable dans le texte affiché par UILabel, nous aurions besoin de résoudre deux tâches indépendantes:
Le premier est facile. À partir de iOS 6 UILabel prend en charge l'affichage de l'attribuée cordes. Tout ce que vous devez faire est de créer et configurer une instance de NSMutableAttributedString:
Que c'est! Le code ci-dessus fait UILabel pour afficher Chaîne avec un lien
Maintenant, nous devons détecter les touches sur ce lien. L'idée est d'attraper tous les robinets à l'intérieur de UILabel et de déterminer si l'emplacement du robinet était assez proche pour le lien. Pour attraper touche, nous pouvons ajouter robinet geste de reconnaissance à l'étiquette. Assurez-vous d'activer userInteraction pour l'étiquette, c'est désactivée par défaut:
Maintenant, le plus sophistiqué des trucs: savoir si le robinet était l'endroit où le lien est affiché et non pas sur toute autre partie de l'étiquette. Si nous avions une seule bordée UILabel, cette tâche pourrait être résolu assez facile de coder en dur le domaine de limites, où le lien est affiché, mais nous allons résoudre ce problème de manière plus élégante et pour le cas général - multiline UILabel sans connaissances préalables sur le lien mise en page.
L'une des approches consiste à utiliser les capacités de Texte du Kit API introduites dans iOS 7:
Enregistrer créé et configuré les instances de NSLayoutManager, NSTextContainer et NSTextStorage dans les propriétés de votre classe (le plus probable UIViewController descendant) - nous aurons besoin d'eux dans d'autres méthodes.
Maintenant, chaque fois que l'étiquette change son image, de mise à jour textContainer taille:
Et enfin, de détecter si le robinet était exactement sur le lien:
cellForRowAtIndexPath
? Je suis la création et la configuration des instances au seincellForRowAtIndexPath
et l'hébergement de l'handleTapOnLabel
fonction aussi. Mais àcell.textLabel.addGestureRecognizer(UITapGestureRecognizer(target: cell, action: "handleTapOnLabel:"))
, je suisunrecognized selector
.textAlignment
de définir l'attributNSTextAlignmentCenter
. Si vous êtes à l'aide de non-texte centré, vous aurez besoin d'ajuster le calcul de votretextContainerOffset
dans le code ci-dessus.textContainerOffset
?x
valeur detextContainerOffset
, la constante0.5
est utilisé. Cela permettra de calculer la position correcte pourNSTextAlignmentCenter
. Pour aligner à gauche, naturel ou justifié, utilisez une valeur de0.0
. Pour aligner à droite, utilisez1.0
.indexOfCharacter
est toujours de retour0
ettextBoundingBox.size
est toujours0, 0
. Je ne peux pas comprendre ce que je fais mal.self.textContainer.size = self.myLabel.bounds.size;
n'est pas la mise à jour de latextContainer.size
. C'est en continuant de retour à zéro, même si mon étiquette de limites de taille n'est pas zéro.Je suis l'extension de @NAlexN originale détaillée de la solution, avec @zekel excellente extension de
UITapGestureRecognizer
, et de fournir dans Swift.L'Extension De UITapGestureRecognizer
Utilisation
Installation
UIGestureRecognizer
à envoyer des actions àtapLabel:
, et vous pouvez détecter si la cible plages est exploité dansmyLabel
.IMPORTANT: Le
UILabel
saut de ligne, vous devez sélectionner un mode d'envelopper par word/char. En quelque sorte,NSTextContainer
suppose que le texte est en ligne uniquement si le saut de ligne mode est le contraire.targetRange1
ettargetRange2
.NSMutableAttributedString(attributedString: text)
où "texte" est unNSAttributedString
Une vieille question, mais si quelqu'un peut utiliser un
UITextView
au lieu d'unUILabel
, alors c'est facile. Standard d'Url, numéros de téléphone etc sera automatiquement détecté (et être cliquable).Toutefois, si vous avez besoin de détection personnalisé, qui est, si vous voulez être en mesure d'appeler n'importe quelle méthode personnalisée après qu'un utilisateur clique sur un mot en particulier, vous devez utiliser
NSAttributedStrings
avec unNSLinkAttributeName
attribut qui pointe vers une URL personnalisée(régime plutôt que d'avoir le schéma d'url http par défaut). Ray Wenderlich a couvert iciCitant le code à partir du lien ci-dessus:
Pour détecter les lier, de clics, de mettre en œuvre cette:
PS: assurez-vous que votre
UITextView
estselectable
.La UIButtonTypeCustom cliquable étiquette si vous ne définissez pas les images pour elle.
(Ma réponse s'appuie sur @NAlexN de excellente réponse. Je ne vais pas dupliquer son explication détaillée de chaque étape ici.)
Je l'ai trouvé plus pratique et simple pour ajouter le support pour tap-mesure UILabel texte comme une catégorie à UITapGestureRecognizer. (Vous n'avez pas ont à utiliser UITextView de détecteurs de données, que certaines réponses suggèrent.)
Ajoutez la méthode suivante à votre UITapGestureRecognizer catégorie:
Exemple De Code
Geste De Rappel
plainText.length
.UITapGestureRecognizer
. Voici quelques infos sur l'ajout de catégories.extensions
en Swift. Im la mise en œuvre de cette utilisation de Swift maintenant et n'ont aucune expérience préalable avec ObjC, donc il n'était pas sûr de ce que sur.UITextView
prend en charge les détecteurs de OS3.0, alors que laUILabel
ne le fait pas.Si vous activez les données des détecteurs de
UITextView
et votre texte contient des Url, numéros de téléphone, etc. ils apparaissent sous forme de liens.hashtag://
ou quelque chose, puis utiliser lestextView(_:shouldInteractWith:in:interaction:)
pour le détecter. Voir la réponse ci-dessous: stackoverflow.com/a/34014655/1161906La traduction @samwize de l'Extension de Swift 4:
Pour configurer le module de reconnaissance (une fois que vous avez la couleur du texte et des trucs):
...puis le geste de reconnaissance:
didTapAttributedTextInLabel
besoin d'unNSRange
comme un argument maisrangeTerms
renvoie quelque chose de différent. Aussi lahandleTapOnLabel
fonction doit être marqué avec@objc
dans Swift 4.Comme je l'ai mentionné dans ce post,
voici une lumière pondérée de la bibliothèque que j'ai créé spécialement pour les liens dans UILabel FRHyperLabel.
Parvenir à un résultat comme ceci:
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque quis blandit eros, sit amet vehicula justo. Nam à urna neque. Maecenas ac sem ue sem porta dictum nec vel tellus.
utilisez le code:
J'ai créé UILabel sous-classe nommée ResponsiveLabel qui est basé sur textkit API introduites dans iOS 7. Il utilise la même approche suggérée par NAlexN. Il offre de la souplesse pour spécifier un modèle pour la recherche dans le texte. On peut spécifier des styles de ces modèles ainsi que l'action à effectuer sur tapant sur les modèles.
Si vous voulez faire une chaîne cliquable, vous pouvez le faire de cette façon. Ce code s'applique attributs pour chaque occurrence de la chaîne "texte".
Travaillé dans Swift 3, coller tout le code ici
Voici un exemple de code pour ajouter un lien hypertexte UILabel:
Source:http://sickprogrammersarea.blogspot.in/2014/03/adding-links-to-uilabel.html
Ici est une swift version de NAlexN de réponse.
}
Vous pouvez ensuite créer une instance de cette classe à l'intérieur de votre
viewDidLoad
méthode comme ceci:C'est mieux d'avoir un attribut personnalisé à utiliser lorsqu'un personnage est exploité. Maintenant, c'est le
NSLinkAttributeName
, mais pourrait être n'importe quoi, et vous pouvez utiliser cette valeur pour faire d'autres choses autre que de l'ouverture d'une url, vous pouvez faire n'importe quelle action personnalisée.Comme il est signalé dans de précédents awnser la UITextView est capable de gérer des touches sur les liens. Cela peut facilement être étendue par la fabrication d'autres parties du texte fonctionnent comme des liens. Le AttributedTextView bibliothèque est un UITextView sous-classe qui le rend très facile à manipuler ces. Pour plus d'infos, voir: https://github.com/evermeer/AttributedTextView
Vous pouvez faire n'importe quelle partie du texte interagir comme ceci (où textView1 est un UITextView IBoutlet):
Et pour le traitement des hashtags et mentionne, vous pouvez utiliser le code comme ceci:
J'ai eu un moment difficile de traiter avec ce... UILabel avec des liens sur sur attribuée texte... il est juste un mal de tête donc j'ai fini par utiliser ZSWTappableLabel.
Je suis l'extension @samwize, la réponse à la poignée multi-ligne UILabel et de donner un exemple sur l'utilisation d'un UIButton
Pour pleinement des liens personnalisés, vous aurez besoin d'utiliser une UIWebView - vous pouvez intercepter l'appel, de sorte que vous pouvez aller à une autre partie de votre application au lieu de cela, lorsque le lien est cliqué.
Voici une liste (Objective-C, catégorie qui permet des liens cliquables dans existant
UILabel.attributedText
chaînes, l'exploitation de l'existantNSLinkAttributeName
attribut.Ce serait un peu plus propre fait par l'intermédiaire d'un UILabel sous-classe (c'est à dire aucun des objc_getAssociatedObject mess), mais si vous êtes comme moi, vous préférez éviter d'avoir à rendre inutile (3ème partie) les sous-classes juste pour ajouter un peu de fonction supplémentaire à l'existant, UIKit classes. Aussi, c'est la beauté qu'il ajoute cliquables liens pour tout existant UILabel, par exemple, existant
UITableViewCells
!J'ai essayé de le rendre aussi peu invasive que possible, en utilisant l'existant
NSLinkAttributeName
attribut trucs déjà disponible en NSAttributedString. Si son aussi simple que:Fondamentalement, il fonctionne en ajoutant un
UIGestureRecognizer
à votre UILabel. Le travail dur est fait dansgestureRecognizerShouldBegin:
, qui re-présentation le attributedText chaîne de trouver le caractère qui a été tapé sur. Si ce personnage a été le cadre d'un NSLinkAttributeName puis le gestureRecognizer sera par la suite d'incendie, de récupérer l'URL correspondante (à partir de la NSLinkAttributeName valeur), et ouvrir le lien par l'habitude[UIApplication.sharedApplication openURL:url]
processus.Remarque - en faisant tout cela dans
gestureRecognizerShouldBegin:
, si vous ne vous arrive de cliquer sur un lien dans l'étiquette, l'événement est passé le long. Ainsi, par exemple, votre UITableViewCell permettra de capturer des robinets sur les liens, mais sinon se comporter normalement (sélectionnez la cellule, désélectionner, de défilement, ...).Je l'ai mis dans un dépôt GitHub ici.
Adapté de Kai Burghardt est TELLEMENT affichage ici.
J'ai suivi cette version,
Swift 4:
Appel Exemple:
Créer la classe avec le suivant .h et .m fichiers. Dans l' .m fichier il y a la fonction suivante
L'intérieur de cette fonction, nous allons vérifier les gammes de sous-chaînes pour lesquelles nous avons besoin de donner des actions. Utilisez votre propre logique de mettre vos gammes.
Et à la suite de l'utilisation de la sous-classe
est le suivant .h fichier
est le suivant .m fichier
Je recommanderais fortement à l'aide d'une bibliothèque qui détecte automatiquement les Url dans le texte et les convertit en liens.
Essayez:
Les deux sont sous licence MIT.
basé sur Charles Gamble réponse, ce que j'ai utilisé (j'ai enlevé quelques lignes qui me confond et m'a donné mal indexé) :
Voici une mise en œuvre rapide qui est aussi minime que possible, qui comprend également le retour tactile. Mises en garde:
"\u{a0}"
).link
clés.
Cette méthode générique fonctionne aussi !
Et vous pouvez appeler la méthode avec
UITapGestureRecognizer
viennent? Est-ce une prise de courant? Une propriété de configuration?Ici est ma réponse basée sur @Luca Davanzo de réponse, remplacer la
touchesBegan
événement à la place d'un robinet geste:J'ai trouvé une autre solution:
Je trouve un moyen de détecter le lien dans un texte html que vous trouverez à partir de l'internet, vous transformer en nsattributeString avec :
Ma méthode permet de détecter l'hyperlien sans avoir à les spécifier.
d'abord, vous créez une extension de la tapgesturerecognizer :
}
dans vous-vue-contrôleur que vous avez créé une liste d'url et des plages à stocker tous les liens et la gamme que le texte de l'attribut contient:
pour trouver l'URL et le URLRange vous pouvez utiliser :
puis vous la mise en œuvre de la poignée robinet :
et nous y voilà!
J'espère que cette solution vous aider comme il m'aider.
TAGS #Swift2.0
- Je prendre inspiration sur - excellent - @NAlexN la réponse de me décider à l'écrire moi-même un wrapper de UILabel.
J'ai aussi essayé TTTAttributedLabel mais je ne peux pas faire cela fonctionne.
Espère que vous pourrez apprécier ce code, toutes les suggestions sont les bienvenues!
0
cause quelocationOfTouchInTextContainer.x
a été négative. J'essaie d'utiliserlet indexOfCharacter = layoutManager.glyphIndex(for: locationOfTouch, in: textContainer)
au lieu de cela, et fonctionne bien.Goutte dans la solution de la catégorie sur
UILabel
(cela suppose que votreUILabel
utilise un attribuées chaîne avec quelquesNSLinkAttributeName
attributs dans celui-ci):