(iPhone) 如何处理 UITextView 上的触摸?
我正在尝试处理 iPhone 的 UITextView 上的触摸。 我通过创建 UIImageViews 的子类并实现 TouchBegan 方法成功地处理了点击和其他触摸事件...但是这显然不适用于 UITextView :(
UITextView 启用了用户交互和多点触摸,只是为了当然...不,没有人能处理这个问题吗?
I'm trying to handle touches on a iPhone's UITextView. I successfully managed to handle taps and other touch events by creating a subclass of UIImageViews for example and implementing the touchesBegan method...however that doesn't work with the UITextView apparently :(
The UITextView has user interaction and multi touch enabled, just to be sure...no no joy. Anyone managed to handle this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
UITextView(UIScrollView的子类)包含很多事件处理。 它处理复制和粘贴以及数据检测器。 也就是说,这可能是一个错误,它不会传递未处理的事件。
有一个简单的解决方案:您可以子类化 UITextView 并在您自己的版本中实现您自己的touchesEnded(和其他事件处理消息),您应该在每次触摸内调用
[super TouchsBegan:touches withEvent:event];
处理方法。UITextView (subclass of UIScrollView) includes a lot of event processing. It handles copy and paste and data detectors. That said, it is probably a bug that it does not pass unhandled events on.
There is a simple solution: you can subclass UITextView and impement your own touchesEnded (and other event handling messages) in your own versions, you should call
[super touchesBegan:touches withEvent:event];
inside every touch handling method.如果您想处理 UITextView 上的单击/双击/三次点击,您可以委托 UIGestureRecongnizer 并在文本视图上添加手势识别器。
继承人相同的代码(在 viewDidLoad 中):
并
希望有所帮助:D
If you want to handle single/double/triple tap on UITextView, you can delegate UIGestureRecongnizer and add gesture recognizers on your textview.
Heres sameple code (in viewDidLoad):
and
Hope this help :D
更好的解决方案 (无需调整任何内容或使用任何私有 API :D )
如下所述,向文本视图添加新的
UITapGestureRecognizers
不会达到预期效果结果,处理程序方法永远不会被调用。 这是因为UITextView
已经有一些点击手势识别器设置,我认为他们的委托不允许我的手势识别器正常工作,并且更改他们的委托可能会导致更糟糕的结果, 我相信。幸运的是,
UITextView
已经设置了我想要的手势识别器,问题是它根据视图的状态而变化(即:输入日语时的手势识别器集与输入英语时不同,而且当不处于编辑模式时)。我通过在 UITextView 的子类中重写这些解决了这个问题:
通过这种方式,无论 textview 何时更改其手势识别器,我们总是会捕获我们想要的点击手势识别器 → 因此,我们的处理程序方法将被相应地调用:)
<强>结论:
如果你想向
UITextView
添加手势识别器,你必须检查文本视图是否已经有它。旧答案
我通过调整私有方法想出了这个答案,因为以前的答案有缺点,并且不能按预期工作。 在这里,我没有修改 UITextView 的点击行为,而是拦截被调用的方法,然后调用原始方法。
进一步说明
UITextView
有一堆专门的UIGestureRecognizers
,每个都有一个target
和一个action
但它们的目标
不是UITextView
本身,它是转发类UITextInteractionAssistant
的对象。 (此助手是UITextView
的@package
ivar,但前向定义位于公共标头:UITextField.h 中)。UITextTapRecognizer
识别点击并调用UITextInteractionAssistant
上的oneFingerTap:
,因此我们想要拦截该调用:)Better solution (Without swizzling anything or using any Private API :D )
As explained below, adding new
UITapGestureRecognizers
to the textview does not have the expected results, handler methods are never called. That is because theUITextView
has some tap gesture recognizer setup already and I think their delegate does not allow my gesture recognizer to work properly and changing their delegate could lead to even worse results, I believe.Luckily the
UITextView
has the gesture recognizer I want already setup, the problem is that it changes according to the state of the view (i.e.: set of gesture recognizers are different when inputing Japanese than when inputing English and also when not being in editing mode).I solved this by overriding these in a subclass of UITextView:
By doing this way, no matter when the textview changes its gesture recognizers, we will always catch the tap gesture recognizer we want → Hence, our handler method will be called accordingly :)
Conclusion:
If you want to add a gesture recognizers to the
UITextView
, you have to check the text view does not have it already.Old Answer
I came up with this answer by swizzling a private method because previous answers have cons and they don't work as expected. Here, rather than modifying the tapping behavior of the
UITextView
, I just intercept the called method and then call the original method.Further Explanation
UITextView
has a bunch of specializedUIGestureRecognizers
, each of these has atarget
and aaction
but theirtarget
is not theUITextView
itself, it's an object of the forward classUITextInteractionAssistant
. (This assistant is a@package
ivar ofUITextView
but is forward definition is in the public header: UITextField.h).UITextTapRecognizer
recognizes taps and callsoneFingerTap:
on theUITextInteractionAssistant
so we want to intercept that call :)您需要分配 UITextView instance.delegate = self (假设您想处理同一控制器中的事件)
并确保在界面中实现 UITextViewDelegate 协议...例如:
然后您可以实现以下任何一个
You need to assign the UITextView instance.delegate = self (assuming you want to take care of the events in the same controller)
And make sure to implement the UITextViewDelegate protocol in the interface... ex:
Then you can implement any of the following
我使用文本视图作为较大视图的子视图。 我需要用户能够滚动文本视图,但不能编辑它。 我想检测文本视图的超级视图上的单击,包括文本视图本身。
当然,我遇到了文本视图吞没从其开始的触摸的问题。 禁用用户交互可以解决此问题,但用户将无法滚动文本视图。
我的解决方案是使文本视图可编辑,并使用文本视图的 shouldBeginEditing 委托方法来检测文本视图中的点击。 我只是返回“否”,从而阻止编辑,但现在我知道文本视图(以及超级视图)已被点击。 在这个方法和超级视图的touchesEnded方法之间我有我需要的。
我知道这对于想要访问实际触摸的人来说不起作用,但如果您想做的只是检测点击,那么这种方法就有效!
I'm using a textview as a subview of a larger view. I need the user to be able to scroll the textview, but not edit it. I want to detect a single tap on the textview's superview, including on the textview itself.
Of course, I ran into the problem that the textview swallows up the touches that begin on it. Disabling user interaction would fix this, but then the user won't be able to scroll the textview.
My solution was to make the textview editable and use the textview's shouldBeginEditing delegate method to detect a tap in the textview. I simply return NO, thereby preventing editing, but now I know that the textview (and thus the superview) has been tapped. Between this method and the superview's touchesEnded method I have what I need.
I know that this won't work for people who want to get access to the actual touches, but if all you want to do is detect a tap, this approach works!
制作一个 UIScrollView 和
[scrollView addSubview: textview]
怎么样,它可以滚动 textview?How about make a UIScrollView and
[scrollView addSubview: textview]
which makes it possible to scroll textview?您还可以发送
Touch Down
事件。 通过 Interface Builder 连接该事件。然后在事件处理程序中添加代码
You can also send a
Touch Down
event. Wire-up this event through the Interface Builder.Then add code in your event handler