Je recherche cela depuis des heures mais j'ai échoué. Je ne sais probablement même pas ce que je devrais rechercher.
De nombreuses applications ont du texte et dans ce texte sont des hyperliens Web en rectangle arrondi. Lorsque je clique dessus, UIWebView
s'ouvre. Ce qui m'intrigue, c'est qu'ils ont souvent des liens personnalisés, par exemple si les mots commencent par # c'est aussi cliquable et l'application répond en ouvrant une autre vue. Comment puis je faire ça? Est-ce possible avec UILabel
ou ai-je besoin UITextView
ou autre chose?
Swift 4
solution entièrement fonctionnelle . Il utiliseUITextView
mais le fait se comporter comme unUILabel
. J'ai essayé les solutions ici et je n'ai pas réussi à obtenir une détection de lien précise.Réponses:
En général, si nous voulons avoir un lien cliquable dans le texte affiché par UILabel, nous devons résoudre deux tâches indépendantes:
Le premier est simple. À partir d'iOS 6, UILabel prend en charge l'affichage des chaînes attribuées. Tout ce que vous devez faire est de créer et de configurer une instance de NSMutableAttributedString:
C'est tout! Le code ci-dessus fait qu'UILabel affiche la chaîne avec un lien
Maintenant, nous devons détecter les contacts sur ce lien. L'idée est d'attraper tous les taps dans UILabel et de déterminer si l'emplacement du tap était suffisamment proche du lien. Pour attraper des touches, nous pouvons ajouter une reconnaissance des gestes du robinet à l'étiquette. Assurez-vous d'activer userInteraction pour l'étiquette, elle est désactivée par défaut:
Maintenant, le truc le plus sophistiqué: savoir si le robinet était sur l'endroit où le lien est affiché et non sur une autre partie de l'étiquette. Si nous avions un UILabel à ligne unique, cette tâche pourrait être résolue relativement facilement en codant en dur les limites de la zone où le lien est affiché, mais résolvons ce problème plus élégamment et pour le cas général - UILabel multiligne sans connaissance préalable de la disposition du lien.
L'une des approches consiste à utiliser les capacités de l'API Text Kit introduite dans iOS 7:
Enregistrez les instances créées et configurées de NSLayoutManager, NSTextContainer et NSTextStorage dans les propriétés de votre classe (très probablement le descendant de UIViewController) - nous en aurons besoin dans d'autres méthodes.
Maintenant, chaque fois que l'étiquette change de cadre, mettez à jour la taille de textContainer:
Et enfin, détectez si le robinet était exactement sur le lien:
la source
cellForRowAtIndexPath
? Je crée et configure des instances danscellForRowAtIndexPath
et héberge également lahandleTapOnLabel
fonction. Mais àcell.textLabel.addGestureRecognizer(UITapGestureRecognizer(target: cell, action: "handleTapOnLabel:"))
, je reçoisunrecognized selector
.textAlignment
attribut de l'étiquette est défini surNSTextAlignmentCenter
. Si vous utilisez du texte non centré, vous devrez ajuster le calcul de votretextContainerOffset
dans le code ci-dessus.x
valeur detextContainerOffset
, la constante0.5
est utilisée. Cela calculera la position correcte pourNSTextAlignmentCenter
. Pour aligner à gauche, naturel ou justifié, utilisez une valeur de0.0
. Pour aligner à droite, utilisez1.0
.J'étends @NAlexN solution détaillée originale, avec @zekel excellente extension de
UITapGestureRecognizer
et fournir à Swift .Extension de UITapGestureRecognizer
Usage
Configuration
UIGestureRecognizer
à laquelle envoyer des actionstapLabel:
et vous pouvez détecter si les plages cibles sont exploitées dansmyLabel
.IMPORTANT: le
UILabel
mode de saut de ligne doit être réglé pour passer à la ligne par mot / caractère. D'une manière ou d'une autre,NSTextContainer
supposera que le texte est sur une seule ligne uniquement si le mode de saut de ligne est différent.la source
targetRange1
ettargetRange2
.NSMutableAttributedString(attributedString: text)
endroit où 'texte' est unNSAttributedString
Vieille question mais si quelqu'un peut utiliser un
UITextView
au lieu d'unUILabel
, alors c'est facile. Les URL standard, numéros de téléphone, etc. seront automatiquement détectés (et pourront être cliqués).Cependant, si vous avez besoin d'une détection personnalisée, c'est-à-dire si vous voulez pouvoir appeler n'importe quelle méthode personnalisée après qu'un utilisateur a cliqué sur un mot particulier, vous devez l'utiliser
NSAttributedStrings
avec unNSLinkAttributeName
attribut qui pointera vers un schéma d'URL personnalisé (par opposition à ayant le schéma http url par défaut). Ray Wenderlich en parle iciCitant le code du lien susmentionné:
Pour détecter ces clics sur les liens, implémentez ceci:
PS: assurez-vous que vous l'
UITextView
êtesselectable
.la source
UIButtonTypeCustom est une étiquette cliquable si vous ne lui définissez aucune image.
la source
(Ma réponse s'appuie sur l' excellente réponse de @ NAlexN . Je ne reproduirai pas ici son explication détaillée de chaque étape.)
J'ai trouvé le plus pratique et le plus simple d'ajouter la prise en charge du texte UILabel utilisable en tant que catégorie à UITapGestureRecognizer. (Vous n'avez pas besoin d'utiliser les détecteurs de données d'UITextView, comme certaines réponses le suggèrent.)
Ajoutez la méthode suivante à votre catégorie UITapGestureRecognizer:
Exemple de code
Rappel de geste
la source
plainText.length
.UITapGestureRecognizer
. Voici quelques informations sur l'ajout de catégories.UITextView
prend en charge les détecteurs de données dans OS3.0, alorsUILabel
que non.Si vous activez les détecteurs de données sur le
UITextView
et que votre texte contient des URL, des numéros de téléphone, etc., ils apparaîtront sous forme de liens.la source
hashtag://
ou quelque chose, puis utilisez-letextView(_:shouldInteractWith:in:interaction:)
pour le détecter. Voir la réponse ci-dessous: stackoverflow.com/a/34014655/1161906Traduire l'extension de @ samwize en Swift 4:
Pour configurer le module de reconnaissance (une fois que vous avez coloré le texte et les éléments):
... puis le reconnaisseur de gestes:
la source
didTapAttributedTextInLabel
a besoin d'unNSRange
comme argument maisrangeTerms
renvoie quelque chose de différent. De plus, lahandleTapOnLabel
fonction doit être marquée avec@objc
dans Swift 4.Comme je l'ai mentionné dans cet article , voici une bibliothèque légère que j'ai créée spécialement pour les liens dans UILabel FRHyperLabel .
Pour obtenir un effet comme celui-ci:
Lorem ipsum dolor assis amet, élite adipiscante consectetur. Pellentesque quis blandit eros, sit amet vehicula justo. Nam à urna neque. Maecenas ac sem eu sem porta dictum nec vel tellus.
utilisez le code:
la source
J'ai créé la sous-classe UILabel nommée ResponsiveLabel qui est basée sur l'API textkit introduite dans iOS 7. Elle utilise la même approche suggérée par NAlexN . Il offre la flexibilité de spécifier un modèle à rechercher dans le texte. On peut spécifier les styles à appliquer à ces motifs ainsi que l'action à effectuer en tapant sur les motifs.
Si vous souhaitez rendre une chaîne cliquable, vous pouvez le faire de cette façon. Ce code applique des attributs à chaque occurrence de la chaîne "texte".
la source
A travaillé dans Swift 3, collant le code entier ici
la source
Voici un exemple de code pour créer un hyperlien UILabel: Source: http://sickprogrammersarea.blogspot.in/2014/03/adding-links-to-uilabel.html
la source
Voici une version rapide de la réponse de NAlexN.
Vous pouvez ensuite créer une instance de cette classe dans votre
viewDidLoad
méthode comme ceci:Il est préférable d'avoir un attribut personnalisé à utiliser lorsqu'un personnage est touché. Maintenant, c'est le
NSLinkAttributeName
, mais peut être n'importe quoi et vous pouvez utiliser cette valeur pour faire autre chose que d'ouvrir une URL, vous pouvez effectuer n'importe quelle action personnalisée.la source
J'ai eu du mal à gérer cela ... UILabel avec des liens sur le texte attribué ... c'est juste un casse-tête, donc j'ai fini par utiliser ZSWTappableLabel .
la source
Comme il est indiqué dans la réponse précédente, l'UITextView est capable de gérer les contacts sur les liens. Cela peut facilement être étendu en faisant fonctionner d'autres parties du texte sous forme de liens. La bibliothèque AttributedTextView est une sous-classe UITextView qui facilite leur gestion. Pour plus d'informations, voir: https://github.com/evermeer/AttributedTextView
Vous pouvez faire en sorte que n'importe quelle partie du texte interagisse comme ceci (où textView1 est un IBOutlet UITextView):
Et pour gérer les hashtags et les mentions, vous pouvez utiliser du code comme celui-ci:
la source
J'étends la réponse de @ samwize pour gérer UILabel multi-lignes et donner un exemple sur l'utilisation d'un UIButton
la source
Je suis cette version,
Swift 4:
Exemple d'appel:
la source
J'ai trouvé une autre solution:
Je trouve un moyen de détecter le lien dans un texte html que vous trouvez sur Internet, vous le transformez en nsattributeString avec:
Ma méthode vous permet de détecter l'hyperlien sans avoir à les spécifier.
vous créez d'abord une extension de tapgesturerecognizer:
}
puis dans le contrôleur d'affichage, vous avez créé une liste d'url et de plages pour stocker tous les liens et la plage que le texte d'attribut contient:
pour trouver l'URL et l'URLRange, vous pouvez utiliser:
puis vous implémentez le robinet de poignée:
et c'est reparti!
J'espère que cette solution vous aidera comme elle m'aidera.
la source
Pour des liens entièrement personnalisés, vous devrez utiliser une UIWebView - vous pouvez intercepter les appels, afin de pouvoir accéder à une autre partie de votre application à la place lorsqu'un lien est enfoncé.
la source
Voici une catégorie Objective-C intégrée qui active les liens cliquables dans les
UILabel.attributedText
chaînes existantes , exploitant l'NSLinkAttributeName
attribut existant .Ce serait un peu plus propre via une sous-classe UILabel (c'est-à-dire aucun du mess objc_getAssociatedObject), mais si vous êtes comme moi, vous préférez éviter d'avoir à créer des sous-classes inutiles (tierces parties) juste pour ajouter une fonction supplémentaire aux classes UIKit existantes. De plus, cela a la beauté d'ajouter des liens cliquables à tout UILabel existant, par exemple existant
UITableViewCells
!J'ai essayé de le rendre le moins invasif possible en utilisant les
NSLinkAttributeName
attributs existants déjà disponibles dans NSAttributedString. Donc, c'est aussi simple que:Fondamentalement, cela fonctionne en ajoutant un
UIGestureRecognizer
à votre UILabel. Le travail acharné est effectué dansgestureRecognizerShouldBegin:
, qui redispose la chaîne attribuéeText pour savoir sur quel caractère a été tapé. Si ce caractère faisait partie d'un NSLinkAttributeName, le gestureRecognizer se déclenche ensuite, récupère l'URL correspondante (à partir de la valeur NSLinkAttributeName) et ouvre le lien selon le[UIApplication.sharedApplication openURL:url]
processus habituel .Remarque - en faisant tout cela
gestureRecognizerShouldBegin:
, si vous n'appuyez pas sur un lien dans l'étiquette, l'événement est transmis. Ainsi, par exemple, votre UITableViewCell capturera les taps sur les liens, mais sinon se comportera normalement (sélectionnez la cellule, désélectionnez, faites défiler, ...).J'ai mis cela dans un référentiel GitHub ici . Adapté de la publication SO de Kai Burghardt ici .
la source
Créez la classe avec les fichiers .h et .m suivants. Dans le fichier .m, il y a la fonction suivante
À l'intérieur de cette fonction, nous vérifierons les plages de sous-chaînes pour lesquelles nous devons donner des actions. Utilisez votre propre logique pour mettre vos plages.
Et voici l'utilisation de la sous-classe
Voici le fichier .h
Voici le fichier .m
la source
Je recommande fortement d'utiliser une bibliothèque qui détecte automatiquement les URL dans le texte et les convertit en liens. Essayer:
Les deux sont sous licence MIT.
la source
sur la base de la réponse de Charles Gamble, voici ce que j'ai utilisé (j'ai supprimé quelques lignes qui m'ont dérouté et m'ont mal indexé):
la source
Solution intégrée en tant que catégorie
UILabel
(cela suppose que vousUILabel
utilisez une chaîne attribuée avec certainsNSLinkAttributeName
attributs):la source
Voici une implémentation Swift qui est à peu près aussi minime que possible et qui inclut également un retour tactile. Avertissements:
"\u{a0}"
).link
clés.
la source
Cette méthode générique fonctionne aussi!
Et vous pouvez appeler la méthode avec
la source
UITapGestureRecognizer
vient-il? Est-ce un débouché? Une propriété que vous configurez?Voici ma réponse basée sur la réponse de @Luca Davanzo , remplacer l'
touchesBegan
événement au lieu d'un geste de tapotement:la source
TAGS # Swift2.0
Je m'inspire - excellente - de la réponse de NAlexN et je décide d'écrire moi-même un wrapper d'UILabel.
J'ai également essayé TTTAttributedLabel mais je ne peux pas le faire fonctionner.
J'espère que vous pourrez apprécier ce code, toutes les suggestions sont les bienvenues!
la source
0
causelocationOfTouchInTextContainer.x
négative. J'essaie d'utiliser à lalet indexOfCharacter = layoutManager.glyphIndex(for: locationOfTouch, in: textContainer)
place et fonctionne bien.la source
Code @timbroder modifié pour gérer correctement plusieurs lignes pour swift4.2
Code UILabel
Code pour reconnaître le robinet
la source
Il s'agit d'une implémentation Xamarin.iOS c # basée sur la réponse de Kedar .
Implémentation de MyClickableTextViewWithCustomUrlScheme avec
ShouldInteractWithUrl
remplacement:Le code objectif-C converti en c # devient:
Assurez-vous de définir Editable = false et Selectable = true pour pouvoir cliquer sur le lien.
ScrollEnabled = true permet également à textview de dimensionner correctement sa hauteur.
la source