Jak przechwycić kliknięcie na link w UITextView?
Czy możliwe jest wykonanie niestandardowej akcji, gdy użytkownik dotknie automatycznie wykrytego łącza telefonu w UITextView. Proszę nie doradzać, aby zamiast tego używać UIWebView.
I proszę nie powtarzaj tylko tekstu z Apple classes reference - oczywiście, że już to przeczytałem.
Dzięki.10 answers
Update: From ios10 ,
- (BOOL)textView:(UITextView *)textView shouldInteractWithURL:(NSURL *)URL inRange:(NSRange)characterRange interaction:(UITextItemInteraction)interaction;
Od ios7 i Później UITextView
ma metodę delegata:
- (BOOL)textView:(UITextView *)textView shouldInteractWithURL:(NSURL *)URL inRange:(NSRange)characterRange *NS_DEPRECATED_IOS(7_0, 10_0, "Use textView:shouldInteractWithURL:inRange:forInteractionType: instead");*
Przechwytywanie kliknięć na linki. I to jest najlepszy sposób, aby to zrobić.
Dla ios6 a wcześniej dobrym sposobem na to jest podkategoryzowanie UIApplication
i nadpisanie -(BOOL)openURL:(NSURL *)url
@interface MyApplication : UIApplication {
}
@end
@implementation MyApplication
-(BOOL)openURL:(NSURL *)url{
if ([self.delegate openURL:url])
return YES;
else
return [super openURL:url];
}
@end
Będziesz musiał zaimplementować openURL:
w swoim delegacie.
Teraz, Aby aplikacja zaczęła się od nowej podklasy UIApplication
, Znajdź plik główny.m w Twoim projekcie. W tym małym pliku, który uruchamia aplikację, zwykle znajduje się ta linia:
int retVal = UIApplicationMain(argc, argv, nil, nil);
Trzeci parametr to nazwa klasy dla Twojej aplikacji. Tak więc, zastąpienie tej linii dla:
int retVal = UIApplicationMain(argc, argv, @"MyApplication", nil);
To mi pomogło.Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-16 09:38:01
W systemie iOS 7 lub nowszym
Możesz użyć następującej metody UITextView delegate:
- (BOOL)textView:(UITextView *)textView shouldInteractWithURL:(NSURL *)URL inRange:(NSRange)characterRange
Widok tekstowy wywołuje tę metodę, jeśli użytkownik dotknie lub długo naciśnie link URL. Implementacja tej metody jest opcjonalna. Domyślnie widok tekstowy otwiera aplikację odpowiedzialną za obsługę typu adresu URL i przekazuje mu adres URL. Za pomocą tej metody można wywołać alternatywną akcję, na przykład wyświetlanie zawartości sieci web pod adresem URL w widoku sieci web w bieżącym podanie.
Ważne:
Linki w widokach tekstowych są interaktywne tylko wtedy, gdy Widok tekstowy jest do wyboru, ale nie do edycji. Czyli, jeśli wartość UITextView właściwość do wyboru to tak, a właściwość isEditable to nie.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-11-11 08:42:00
Wersja Swift:
Twoja standardowa konfiguracja UITextView powinna wyglądać mniej więcej tak, nie zapomnij o typach delegate i datadetectortyp.
var textView = UITextView(x: 10, y: 10, width: CardWidth - 20, height: placeholderHeight) //This is my custom initializer
textView.text = "dsfadsaf www.google.com"
textView.selectable = true
textView.dataDetectorTypes = UIDataDetectorTypes.Link
textView.delegate = self
addSubview(textView)
Po zakończeniu zajęć dodaj ten kawałek:
class myVC: UIViewController {
//viewdidload and other stuff here
}
extension MainCard: UITextViewDelegate {
func textView(textView: UITextView, shouldInteractWithURL URL: NSURL, inRange characterRange: NSRange) -> Bool {
//Do your stuff over here
var webViewController = SVModalWebViewController(URL: URL)
view.presentViewController(webViewController, animated: true, completion: nil)
return false
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-24 20:33:21
Dla Swift 3
textView.delegate = self
extension MyTextView: UITextViewDelegate
func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange) -> Bool {
GCITracking.sharedInstance.track(externalLink: URL)
return true
}
}
Lub jeśli target jest > = IOS 10
func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange, interaction: UITextItemInteraction) -> Bool
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-03 07:35:58
W Swift 3 i i0S 10 najprostszym sposobem interakcji z numerami telefonów, adresami URL lub adresami w UITextView
jest użycie UIDataDetectorTypes
. Poniższy kod pokazuje, jak wyświetlić numer telefonu w UITextView
, aby użytkownik mógł z nim współpracować.
import UIKit
class ViewController: UIViewController {
// Link this outlet to a UITextView in your Storyboard
@IBOutlet weak var textView: UITextView!
override func viewDidLoad() {
super.viewDidLoad()
textView.text = "+33687654321"
textView.isUserInteractionEnabled = true // default: true
textView.isEditable = false // default: true
textView.isSelectable = true // default: true
textView.dataDetectorTypes = [.phoneNumber]
}
}
Z tym kodem, po kliknięciu na numer telefonu, pojawi się UIAlertController
.
Jako alternatywę możesz użyć NSAttributedString
:
import UIKit
class ViewController: UIViewController {
// Link this outlet to a UITextView in your Storyboard
@IBOutlet weak var textView: UITextView!
override func viewDidLoad() {
super.viewDidLoad()
let phoneUrl = NSURL(string: "tel:+33687654321")! // "telprompt://+33687654321" also works
let attributes = [NSLinkAttributeName: phoneUrl]
let attributedString = NSAttributedString(string: "phone number", attributes: attributes)
textView.attributedText = attributedString
textView.isUserInteractionEnabled = true // default: true
textView.isEditable = false // default: true
textView.isSelectable = true // default: true
}
}
Z tym kodem, po kliknięciu na przypisany ciąg, a UIAlertController
pojawi się w górę.
Jednak możesz chcieć wykonać niestandardową akcję zamiast tworzyć wyskakujące okienko UIAlertController
Po kliknięciu numeru telefonu. Możesz też zachować UIAlertController
, aby wyskakiwać i wykonywać własne niestandardowe działania w tym samym czasie.
W obu przypadkach będziesz musiał dostosować swój UIViewController
do UITextViewDelegate
protokołu i wdrożyć textView(_:shouldInteractWith:in:interaction:)
. Poniższy kod pokazuje, jak to zrobić.
import UIKit
class ViewController: UIViewController, UITextViewDelegate {
// Link this outlet to a UITextView in your Storyboard
@IBOutlet weak var textView: UITextView!
override func viewDidLoad() {
super.viewDidLoad()
textView.delegate = self
textView.text = "+33687654321"
textView.isUserInteractionEnabled = true
textView.isEditable = false
textView.isSelectable = true
textView.dataDetectorTypes = [.phoneNumber]
}
func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange, interaction: UITextItemInteraction) -> Bool {
/* perform your own custom actions here */
print(URL)
return false // return true if you still want UIAlertController to pop up
}
}
Z tym kodem, po kliknięciu na numer telefonu, Nie UIAlertController
pojawi się i Ty zamiast tego zostanie wyświetlony następujący wydruk w konsoli:
Tel: + 33687654321
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-04-22 08:40:01
Mam dynamiczną zawartość w widoku tekstowym, która może zawierać link. ShouldInteractWithURL jest wywoływany tylko wtedy, gdy użytkownik jest długo naciśnięty na link, ale nie wywołuje na dotknięcie link. Proszę przekierować, jeśli jakiś kumpel ma do niego odniesienie.
Poniżej znajduje się fragment kodu.
UITextView *ltextView = [[UITextView alloc] init];
[ltextView setScrollEnabled:YES];
[ltextView setDataDetectorTypes:UIDataDetectorTypeLink];
ltextView.selectable = YES;
[ltextView setEditable:NO];
ltextView.userInteractionEnabled = YES;
ltextView.delegate = (id)self;
ltextView.delaysContentTouches = NO;
[self.view addsubview:ltextview];
- (BOOL)textView:(UITextView *)textView shouldInteractWithURL:(NSURL *)URL inRange:(NSRange)characterRange{
[self.mActionDelegate userClickedOnImageLinkFromWebview:URL];
NSLog(@"urls is :- %@",URL);
return FALSE;
}
Powyższa metoda delegata nie jest wywoływana na tap.
Pozdrawiam, Rohit Jankar
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-26 02:32:37
Swift 4:
1) Utwórz następującą klasę (podklasowaną UITextView):
import Foundation
protocol QuickDetectLinkTextViewDelegate: class {
func tappedLink()
}
class QuickDetectLinkTextView: UITextView {
var linkDetectDelegate: QuickDetectLinkTextViewDelegate?
override init(frame: CGRect, textContainer: NSTextContainer?) {
super.init(frame: frame, textContainer: textContainer)
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
let glyphIndex: Int? = layoutManager.glyphIndex(for: point, in: textContainer, fractionOfDistanceThroughGlyph: nil)
let index: Int? = layoutManager.characterIndexForGlyph(at: glyphIndex ?? 0)
if let characterIndex = index {
if characterIndex < textStorage.length {
if textStorage.attribute(NSLinkAttributeName, at: characterIndex, effectiveRange: nil) != nil {
linkDetectDelegate?.tappedLink()
return self
}
}
}
return nil
}
}
2) gdziekolwiek skonfigurujesz textview, zrób to:
//init, viewDidLoad, etc
textView.linkDetectDelegate = self
//outlet
@IBOutlet weak var textView: QuickDetectLinkTextView!
//change ClassName to your class
extension ClassName: QuickDetectLinkTextViewDelegate {
func tappedLink() {
print("Tapped link, do something")
}
}
Jeśli używasz storyboard, upewnij się, że widok tekstu wygląda tak w Inspektorze tożsamości po prawej stronie panelu:
Voila! Teraz otrzymasz link dotknij natychmiast, zamiast gdy URL shouldInteractWith URL metoda
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-29 18:59:09
Sam tego nie próbowałem, ale możesz spróbować zaimplementować metodę application:handleOpenURL:
w swoim delegacie aplikacji-wygląda na to, że wszystkie żądania openURL
przechodzą przez ten callback.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-03-31 08:57:59
Nie wiem, w jaki sposób przechwycisz wykryte łącze danych, ani jakiego rodzaju funkcję musisz uruchomić. Ale możesz być w stanie wykorzystać metodę didBeginEditing TextField do uruchomienia testu/skanowania przez textfield, jeśli wiesz, czego szukasz..takich jak porównywanie ciągów tekstowych, które spełniają ###-###-#### formatować, lub zaczynać od " www."aby pobrać te pola, ale musisz napisać mały kod, aby powąchać przez ciąg textfields, ponownie skonfigurować to, czego potrzebujesz, a następnie wyodrębnić go dla swojego zastosowanie funkcji. Nie sądzę, że byłoby to takie trudne, gdy zawęzisz dokładnie to, czego chciałeś, a następnie skupisz swoją instrukcję if() na bardzo specyficznym wzorcu dopasowania tego, czego potrzebujesz.
Z couse oznacza to, że użytkownik dotknie pola tekstowego w celu aktywacji funkcji didBeginEditing (). Jeśli nie jest to typ interakcji użytkownika, którego szukałeś, możesz po prostu użyć timera wyzwalającego, który rozpoczyna się w viewdidappear () lub w inny sposób oparty na potrzebujesz i uruchamia łańcuch textfields, a następnie na końcu uruchamiasz metody TextField string, które zbudowałeś, po prostu wyłączasz zegar z powrotem.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-04-04 23:47:34
application:handleOpenURL:
jest wywoływany, gdy inna aplikacja otworzy Twoją aplikację, otwierając adres URL ze schematem, który obsługuje Twoja aplikacja. Nie jest wywoływany, gdy aplikacja zaczyna otwierać adres URL.
Myślę, że jedynym sposobem, aby zrobić to, czego chce Vladimir, jest użycie UIWebView zamiast UITextView. Upewnij się, że kontroler widoku zaimplementuje UIWebViewDelegate, Ustaw delegata UIWebView na kontroler widoku, a w kontrolerze widoku zaimplementuj webView:shouldStartLoadWithRequest:navigationType:
, aby otworzyć [request URL]
w widoku zamiast zamykać aplikację i otwierać ją w Mobilne Safari.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-06-08 02:31:18