He estado buscando esto durante horas pero he fallado. Probablemente ni siquiera sé lo que debería estar buscando.
Muchas aplicaciones tienen texto y en este texto son hipervínculos web en rectángulo redondeado. Cuando hago clic en ellos se UIWebView
abre. Lo que me desconcierta es que a menudo tienen enlaces personalizados, por ejemplo, si las palabras comienzan con #, también se puede hacer clic y la aplicación responde abriendo otra vista. ¿Cómo puedo hacer eso? ¿Es posible con UILabel
o necesito UITextView
u otra cosa?
Swift 4
solución totalmente funcional . UtilizaUITextView
pero hace que se comporte como aUILabel
. Probé las soluciones aquí y no pude obtener una detección de enlace precisa.Respuestas:
En general, si queremos que UILabel muestre un enlace en el que se puede hacer clic, tendremos que resolver dos tareas independientes:
El primero es facil. A partir de iOS 6, UILabel admite la visualización de cadenas atribuidas. Todo lo que necesita hacer es crear y configurar una instancia de NSMutableAttributedString:
¡Eso es! El código anterior hace que UILabel muestre String con un enlace
Ahora deberíamos detectar toques en este enlace. La idea es capturar todos los grifos dentro de UILabel y determinar si la ubicación del grifo estaba lo suficientemente cerca del enlace. Para capturar toques, podemos agregar un reconocimiento de gestos de toque a la etiqueta. Asegúrese de habilitar userInteraction para la etiqueta, está desactivada por defecto:
Ahora lo más sofisticado: averiguar si el toque estaba en el lugar donde se muestra el enlace y no en ninguna otra parte de la etiqueta. Si tuviéramos UILabel de una sola línea, esta tarea podría resolverse de manera relativamente fácil codificando los límites del área donde se muestra el enlace, pero solucionemos este problema de manera más elegante y para el caso general: UILabel multilínea sin conocimiento preliminar sobre el diseño del enlace.
Uno de los enfoques es utilizar las capacidades de Text API API introducidas en iOS 7:
Guarde las instancias creadas y configuradas de NSLayoutManager, NSTextContainer y NSTextStorage en las propiedades de su clase (probablemente el descendiente de UIViewController): las necesitaremos en otros métodos.
Ahora, cada vez que la etiqueta cambie su marco, actualice el tamaño de textContainer:
Y finalmente, detecta si el toque estaba exactamente en el enlace:
fuente
cellForRowAtIndexPath
? Estoy creando y configurando instancias dentrocellForRowAtIndexPath
y alojando lahandleTapOnLabel
función también. Pero encell.textLabel.addGestureRecognizer(UITapGestureRecognizer(target: cell, action: "handleTapOnLabel:"))
, me estoy poniendounrecognized selector
.textAlignment
atributo de la etiqueta está establecido enNSTextAlignmentCenter
. Si está utilizando texto no centrado, deberá ajustar el cálculo de sutextContainerOffset
en el código anterior.x
valor detextContainerOffset
,0.5
se utiliza la constante . Esto calculará la posición correcta paraNSTextAlignmentCenter
. Para alinear a la izquierda, natural o justificado, use un valor de0.0
. Para alinear a la derecha, use1.0
.Estoy ampliando la solución detallada original de @NAlexN , con una excelente extensión de @zekel
UITapGestureRecognizer
y brindando en Swift .Extendiendo UITapGestureRecognizer
Uso
Configure
UIGestureRecognizer
para enviar accionestapLabel:
, y puede detectar si se están aprovechando los rangos objetivomyLabel
.IMPORTANTE: El
UILabel
modo de salto de línea debe configurarse para ajustarse por word / char. De alguna manera,NSTextContainer
asumiremos que el texto es una sola línea solo si el modo de salto de línea es diferente.fuente
targetRange1
ytargetRange2
.NSMutableAttributedString(attributedString: text)
donde 'texto' es unNSAttributedString
Antigua pregunta, pero si alguien puede usar un en
UITextView
lugar de unUILabel
, entonces es fácil. Se detectarán automáticamente URL estándar, números de teléfono, etc.Sin embargo, si necesita una detección personalizada, es decir, si desea poder llamar a cualquier método personalizado después de que un usuario haga clic en una palabra en particular, debe usar
NSAttributedStrings
unNSLinkAttributeName
atributo que apunte a un esquema de URL personalizado (en lugar de tener el esquema http url por defecto). Ray Wenderlich lo tiene cubierto aquíCitando el código del enlace antes mencionado:
Para detectar esos clics de enlace, implemente esto:
PD: Asegúrate de que lo
UITextView
esselectable
.fuente
UIButtonTypeCustom es una etiqueta en la que se puede hacer clic si no configura ninguna imagen para ella.
fuente
(Mi respuesta se basa en la excelente respuesta de @ NAlexN . No duplicaré su explicación detallada de cada paso aquí).
Me pareció más conveniente y directo agregar soporte para texto UILabel que se puede tocar como una categoría para UITapGestureRecognizer. (No tiene que usar los detectores de datos de UITextView, como sugieren algunas respuestas).
Agregue el siguiente método a su categoría UITapGestureRecognizer:
Código de ejemplo
Devolución de gestos
fuente
plainText.length
.UITapGestureRecognizer
. Aquí hay información sobre cómo agregar categorías.UITextView
admite detectores de datos en OS3.0, mientrasUILabel
que no.Si habilita los detectores de datos en
UITextView
y su texto contiene URL, números de teléfono, etc., aparecerán como enlaces.fuente
hashtag://
o algo así, luego úselotextView(_:shouldInteractWith:in:interaction:)
para detectarlo. Vea la respuesta a continuación: stackoverflow.com/a/34014655/1161906Traduciendo la extensión de @ samwize a Swift 4:
Para configurar el reconocedor (una vez que coloreó el texto y otras cosas):
... luego el reconocedor de gestos:
fuente
didTapAttributedTextInLabel
necesita unNSRange
como argumento perorangeTerms
devuelve algo diferente. Además, lahandleTapOnLabel
función debe marcarse@objc
en Swift 4.Como mencioné en esta publicación , aquí hay una biblioteca ligera que creé especialmente para enlaces en UILabel FRHyperLabel .
Para lograr un efecto como este:
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque quis blandit eros, sit amet vehicula justo. Nam en urna neque. Mecenas ac sem eu sem porta dictum nec vel tellus.
usar código:
fuente
Creé la subclase UILabel llamada ResponsiveLabel que se basa en la API de kit de texto introducida en iOS 7. Utiliza el mismo enfoque sugerido por NAlexN . Proporciona flexibilidad para especificar un patrón para buscar en el texto. Se pueden especificar los estilos que se aplicarán a esos patrones, así como la acción que se realizará al tocar los patrones.
Si desea que se pueda hacer clic en una cadena, puede hacerlo de esta manera. Este código aplica atributos a cada aparición de la cadena "texto".
fuente
Trabajó en Swift 3, pegando todo el código aquí
fuente
Aquí hay un código de ejemplo para hipervínculo UILabel: Fuente: http://sickprogrammersarea.blogspot.in/2014/03/adding-links-to-uilabel.html
fuente
Aquí hay una versión rápida de la respuesta de NAlexN.
Luego puede crear una instancia de esa clase dentro de su
viewDidLoad
método de esta manera:Es mejor tener un atributo personalizado para usar cuando se toca un personaje. Ahora, es el
NSLinkAttributeName
, pero podría ser cualquier cosa y puede usar ese valor para hacer otras cosas además de abrir una URL, puede hacer cualquier acción personalizada.fuente
Me costó mucho lidiar con esto ... UILabel con enlaces en el texto atribuido ... es solo un dolor de cabeza, así que terminé usando ZSWTappableLabel .
fuente
Como se informó en la respuesta anterior, UITextView puede manejar toques en los enlaces. Esto se puede ampliar fácilmente haciendo que otras partes del texto funcionen como enlaces. La biblioteca AttributedTextView es una subclase UITextView que hace que sea muy fácil de manejar. Para obtener más información, consulte: https://github.com/evermeer/AttributedTextView
Puede hacer que cualquier parte del texto interactúe así (donde textView1 es un IBOutlet UITextView):
Y para manejar hashtags y menciones puedes usar un código como este:
fuente
Estoy extendiendo la respuesta de @ samwize para manejar UILabel multilínea y dar un ejemplo sobre el uso de un UIButton
fuente
Sigo esta versión,
Swift 4:
Ejemplo de llamada:
fuente
Encontré otra solución:
Encuentro una manera de detectar el enlace en un texto html que encuentras en Internet y lo transformas en nsattributeString con:
Mi método le permite detectar el hipervínculo sin tener que especificarlos.
primero crea una extensión de tapgesturerecognizer:
}
luego, en su controlador de vista, creó una lista de url y rangos para almacenar todos los enlaces y el rango que contiene el texto del atributo:
para encontrar la URL y la URLRange puede usar:
entonces implementas el grifo de la manija:
¡y aquí vamos!
Espero que esta solución te ayude, que me ayude.
fuente
Para enlaces totalmente personalizados, necesitará usar un UIWebView: puede interceptar las llamadas, para que pueda ir a otra parte de su aplicación cuando se presiona un enlace.
fuente
Aquí hay una categoría de Objective-C que permite hacer clic en enlaces en
UILabel.attributedText
cadenas existentes , explotando elNSLinkAttributeName
atributo existente .Esto sería un poco más limpio a través de una subclase UILabel (es decir, ninguno de los líos objc_getAssociatedObject), pero si eres como yo, prefieres evitar tener que hacer subclases innecesarias (de terceros) solo para agregar alguna función adicional a las clases UIKit existentes. Además, esto tiene la belleza de que agrega enlaces clicables a cualquier UILabel existente, por ejemplo,
UITableViewCells
¡ existente !Intenté hacerlo lo menos invasivo posible utilizando los
NSLinkAttributeName
atributos existentes que ya están disponibles en NSAttributedString. Entonces es tan simple como:Básicamente, funciona agregando un
UIGestureRecognizer
a su UILabel. Se realiza el trabajo durogestureRecognizerShouldBegin:
, que vuelve a diseñar la cadena de texto atribuido para averiguar qué carácter se tocó. Si este personaje era parte de un NSLinkAttributeName, entonces el GestorReconocidor se activará posteriormente, recuperará la URL correspondiente (del valor NSLinkAttributeName) y abrirá el enlace según el[UIApplication.sharedApplication openURL:url]
proceso habitual .Nota: al hacer todo esto
gestureRecognizerShouldBegin:
, si no toca un enlace en la etiqueta, el evento se transfiere. Entonces, por ejemplo, su UITableViewCell capturará toques en los enlaces, pero de lo contrario se comportará normalmente (seleccionar celda, anular selección, desplazamiento, ...).He puesto esto en un repositorio de GitHub aquí . Adaptado de la publicación SO de Kai Burghardt aquí .
fuente
Cree la clase con los siguientes archivos .h y .m. En el archivo .m hay la siguiente función
Dentro de esta función, verificaremos los rangos de subcadenas para las que necesitamos dar acciones. Usa tu propia lógica para poner tus rangos.
Y a continuación se muestra el uso de la subclase.
el siguiente es el archivo .h
el siguiente es el archivo .m
fuente
Recomiendo encarecidamente utilizar una biblioteca que detecte automáticamente las URL en el texto y las convierta en enlaces. Tratar:
Ambos están bajo licencia MIT.
fuente
basado en la respuesta de Charles Gamble, esto es lo que usé (eliminé algunas líneas que me confundieron y me dieron un índice incorrecto):
fuente
Solución directa como una categoría activada
UILabel
(esto supone queUILabel
utiliza una cadena atribuida con algunosNSLinkAttributeName
atributos):fuente
Aquí hay una implementación Swift que es lo más mínima posible que también incluye retroalimentación táctil. Advertencias:
"\u{a0}"
).link
claves.
fuente
¡Este método genérico también funciona!
Y puedes llamar al método con
fuente
UITapGestureRecognizer
viene? ¿Es una salida? ¿Una propiedad que configuraste?Aquí está mi respuesta basada en la respuesta de @Luca Davanzo , anule el
touchesBegan
evento en lugar de un gesto de toque:fuente
TAGS # Swift2.0
Me inspiro en - excelente - la respuesta de @ NAlexN y decido escribir por mí mismo un contenedor de UILabel.
También probé TTTAttributedLabel pero no puedo hacer que funcione.
Espero que puedan apreciar este código, cualquier sugerencia es bienvenida.
fuente
0
causa quelocationOfTouchInTextContainer.x
era negativa. Intento usarlolet indexOfCharacter = layoutManager.glyphIndex(for: locationOfTouch, in: textContainer)
, y funciona bien.fuente
Se modificó el código @timbroder para manejar varias líneas correctamente para swift4.2
Código UILabel
Código para reconocer el Tap
fuente
Esta es una implementación de Xamarin.iOS c # basada en la respuesta de Kedar .
Implementación MyClickableTextViewWithCustomUrlScheme con
ShouldInteractWithUrl
anulación:El código objetivo convertido de C en c # se convierte en:
Asegúrese de establecer Editable = false y Selectable = true para poder hacer clic en el enlace.
También ScrollEnabled = true permite que la vista de texto dimensione su altura correctamente.
fuente