(iPhone) Как обрабатывать штрихи в UITextView?
Я пытаюсь обрабатывать штрихи на iPhone UITextView. Я успешно справился с кранами и другими событиями касания, создав подкласс UIImageViews, например, и выполнив метод touchhesBegan... однако это не работает с UITextView, по-видимому: (
UITextView поддерживает взаимодействие с пользователем и поддерживает мультитач, чтобы быть уверенным... нет никакой радости. Кто-нибудь справился с этим?
Ответы
Ответ 1
UITextView (подкласс UIScrollView) включает в себя много обработки событий. Он обрабатывает копии, вставки и детекторы данных. Тем не менее, это, вероятно, ошибка в том, что он не передает необработанные события.
Существует простое решение: вы можете подклассифицировать UITextView и импортировать свои собственные touchsEnded (и другие сообщения обработки событий) в свои собственные версии, вы должны вызвать [super touchesBegan:touches withEvent:event];
внутри каждого метода обработки касаний.
#import "MyTextView.h" //MyTextView:UITextView
@implementation MyTextView
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
NSLog(@"touchesBegan");
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
[super touchesBegan:touches withEvent:event];
NSLog(@"touchesMoved");
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
NSLog(@"****touchesEnded");
[self.nextResponder touchesEnded: touches withEvent:event];
NSLog(@"****touchesEnded");
[super touchesEnded:touches withEvent:event];
NSLog(@"****touchesEnded");
}
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event{
[super touches... etc];
NSLog(@"touchesCancelled");
}
Ответ 2
Если вы хотите обрабатывать одиночный/двойной/тройной щелчок на UITextView, вы можете делегировать UIGestureRecongnizer и добавлять распознаватели жестов в своем текстовом виде.
Имеет одинаковый код (в viewDidLoad):
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleSingleTap)];
//modify this number to recognizer number of tap
[singleTap setNumberOfTapsRequired:1];
[self.textView addGestureRecognizer:singleTap];
[singleTap release];
и
-(void)handleSingleTap{
//handle tap in here
NSLog(@"Single tap on view");
}
Надеюсь, что эта помощь: D
Ответ 3
Лучшее решение (без использования чего-либо или использования какого-либо частного API: D)
Как объясняется ниже, добавление нового текста UITapGestureRecognizers
в текстовое представление не имеет ожидаемых результатов, методы обработчика никогда не вызываются. Это связано с тем, что у UITextView
уже установлена установка распознавателя жестов, и я думаю, что их делегат не позволяет моему распознавателю жестов работать исправно, и, по-моему, изменение их делегата может привести к еще худшим результатам.
К счастью, у UITextView
есть распознаватель жестов, который я хочу уже установить, проблема в том, что он изменяется в соответствии с состоянием представления (т.е. набор распознавателей жестов отличается при вводе японского языка, чем при вводе на английский язык, а также когда нет находясь в режиме редактирования).
Я решил это, переопределив их в подклассе UITextView:
- (void)addGestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
{
[super addGestureRecognizer:gestureRecognizer];
// Check the new gesture recognizer is the same kind as the one we want to implement
// Note:
// This works because `UITextTapRecognizer` is a subclass of `UITapGestureRecognizer`
// and the text view has some `UITextTapRecognizer` added :)
if ([gestureRecognizer isKindOfClass:[UITapGestureRecognizer class]]) {
UITapGestureRecognizer *tgr = (UITapGestureRecognizer *)gestureRecognizer;
if ([tgr numberOfTapsRequired] == 1 &&
[tgr numberOfTouchesRequired] == 1) {
// If found then add self to its targets/actions
[tgr addTarget:self action:@selector(_handleOneFingerTap:)];
}
}
}
- (void)removeGestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
{
// Check the new gesture recognizer is the same kind as the one we want to implement
// Read above note
if ([gestureRecognizer isKindOfClass:[UITapGestureRecognizer class]]) {
UITapGestureRecognizer *tgr = (UITapGestureRecognizer *)gestureRecognizer;
if ([tgr numberOfTapsRequired] == 1 &&
[tgr numberOfTouchesRequired] == 1) {
// If found then remove self from its targets/actions
[tgr removeTarget:self action:@selector(_handleOneFingerTap:)];
}
}
[super removeGestureRecognizer:gestureRecognizer];
}
- (void)_handleOneFingerTap:(UITapGestureRecognizer *)tgr
{
NSDictionary *userInfo = [NSDictionary dictionaryWithObject:tgr forKey:@"UITapGestureRecognizer"];
[[NSNotificationCenter defaultCenter] postNotificationName:@"TextViewOneFingerTapNotification" object:self userInfo:userInfo];
// Or I could have handled the action here directly ...
}
Таким образом, независимо от того, когда текстовое изменение изменит свои распознаватели жестов, мы всегда поймаем распознаватель жестов нажатия, который мы хотим → Следовательно, наш метод обработчика будет вызван соответственно:)
Вывод:
Если вы хотите добавить распознаватели жестов в UITextView
, вам нужно проверить, что текстовое представление уже не имеет его.
- Если это не так, просто сделайте обычный путь. (Создайте свой распознаватель жестов, настройте его и добавьте в текстовое представление), и все готово!
- Если у него есть это, вам, вероятно, нужно будет сделать что-то похожее, как указано выше.
Старый ответ
Я придумал этот ответ swizzling private method, потому что предыдущие ответы имеют минусы, и они не работают должным образом. Здесь вместо того, чтобы изменять поведение нажатия UITextView
, я просто перехватываю вызываемый метод, а затем вызываю оригинальный метод.
Дальнейшее объяснение
UITextView
имеет кучу специализированных UIGestureRecognizers
, каждый из которых имеет target
и a action
, но их target
не сам UITextView
, это объект прямого класса UITextInteractionAssistant
. (Этот помощник является @package
ivar UITextView
, но прямое определение находится в общедоступном заголовке: UITextField.h).
UITextTapRecognizer
распознает нажатия и вызовы oneFingerTap:
на UITextInteractionAssistant
, поэтому мы хотим перехватить этот вызов:)
#import <objc/runtime.h>
// Prototype and declaration of method that is going be swizzled
// When called: self and sender are supposed to be UITextInteractionAssistant and UITextTapRecognizer objects respectively
void proxy_oneFingerTap(id self, SEL _cmd, id sender);
void proxy_oneFingerTap(id self, SEL _cmd, id sender){
[[NSNotificationCenter defaultCenter] postNotificationName:@"TextViewOneFinderTap" object:self userInfo:nil];
if ([self respondsToSelector:@selector(proxy_oneFingerTap:)]) {
[self performSelector:@selector(proxy_oneFingerTap:) withObject:sender];
}
}
...
// subclass of UITextView
// Add above method and swizzle it with.
- (void)doTrickForCatchingTaps
{
Class class = [UITextInteractionAssistant class]; // or below line to avoid ugly warnings
//Class class = NSClassFromString(@"UITextInteractionAssistant");
SEL new_selector = @selector(proxy_oneFingerTap:);
SEL orig_selector = @selector(oneFingerTap:);
// Add method dynamically because UITextInteractionAssistant is a private class
BOOL success = class_addMethod(class, new_selector, (IMP)proxy_oneFingerTap, "[email protected]:@");
if (success) {
Method originalMethod = class_getInstanceMethod(class, orig_selector);
Method newMethod = class_getInstanceMethod(class, new_selector);
if ((originalMethod != nil) && (newMethod != nil)){
method_exchangeImplementations(originalMethod, newMethod); // Method swizzle
}
}
}
//... And in the UIViewController, let say
[textView doTrickForCatchingTaps];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textViewWasTapped:) name:@"TextViewOneFinderTap" object:nil];
- (void)textViewWasTapped:(NSNotification *)noti{
NSLog(@"%@", NSStringFromSelector:@selector(_cmd));
}
Ответ 4
Вам нужно назначить UITextView instance.delegate = self (при условии, что вы хотите следить за событиями в одном контроллере)
И убедитесь, что реализован протокол UITextViewDelegate в интерфейсе... ex:
@interface myController : UIViewController <UITextViewDelegate>{
}
Затем вы можете реализовать любое из следующих
- (BOOL)textViewShouldBeginEditing:(UITextView *)textView;
- (BOOL)textViewShouldEndEditing:(UITextView *)textView;
- (void)textViewDidBeginEditing:(UITextView *)textView;
- (void)textViewDidEndEditing:(UITextView *)textView;
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text;
- (void)textViewDidChange:(UITextView *)textView;
- (void)textViewDidChangeSelection:(UITextView *)textView;
Ответ 5
Я использую textview как подвид большего изображения. Мне нужно, чтобы пользователь мог прокручивать текстовое изображение, но не редактировать его. Я хочу обнаружить одно нажатие на надписи textview, в том числе и на самом текстовом изображении.
Конечно, я столкнулся с проблемой, что текст просматривает штрихи, которые начинаются с него. Отключение взаимодействия с пользователем устранит это, но тогда пользователь не сможет прокрутить текстовое окно.
Мое решение состояло в том, чтобы сделать textview редактируемым и использовать метод textview shouldBeginEditing delegate для обнаружения крана в текстовом виде. Я просто возвращаю NO, тем самым предотвращая редактирование, но теперь я знаю, что текст (и, следовательно, супервизор) был использован. Между этим методом и supviewEnded метод имеет то, что мне нужно.
Я знаю, что это не сработает для людей, которые хотят получить доступ к фактическим касаниям, но если все, что вы хотите сделать, это обнаружить кран, этот подход работает!
Ответ 6
Как сделать UIScrollView и [scrollView addSubview: textview]
, что позволяет прокручивать текстовое изображение?
Ответ 7
Вы также можете отправить событие Touch Down
. Подключите это событие через Interface Builder.
![enter image description here]()
Затем добавьте код в обработчик событий
- (IBAction)onAppIDTap:(id)sender {
//Your code
}