我已经编写了自己的函数,当键盘出现时滚动文本字段。为了通过点击离开文本字段来取消键盘,我创建了一个UITapGestureRecognizer,它负责在点击离开时放弃文本字段上的第一个响应器。
现在我还为文本字段创建了一个自动完成,它在文本字段的下面创建了一个UITableView,并在用户输入文本时用项目填充它。
但是,当选择自动补全表中的一个条目时,不会调用didSelectRowAtIndexPath。相反,它似乎是点击手势识别器被调用,只是辞职第一响应器。
我猜有一些方法告诉点击手势识别器继续将点击消息传递给UITableView,但我不知道它是什么。任何帮助都将不胜感激。
解决这个问题最简单的方法是:
UITapGestureRecognizer *tapRec = [[UITapGestureRecognizer alloc]
initWithTarget:self action:@selector(tap:)];
[tapRec setCancelsTouchesInView:NO];
这让UIGestureRecognizer识别点击,并将触摸传递给下一个响应器。这个方法的一个意想不到的结果是,如果你在屏幕上有一个UITableViewCell来推另一个视图控制器。如果用户轻按该行以取消键盘,则键盘和推送都将被识别。我怀疑这是你的意图,但这种方法适用于许多情况。
同时,扩展Robert的回答,如果你有一个指向表视图的指针,那么你可以直接比较它的类,而不是必须转换为字符串,希望苹果不会改变命名法:
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
shouldReceiveTouch:(UITouch *)touch
{
if([touch.view class] == tableview.class){
return //YES/NO
}
return //YES/NO
}
记住,你还必须声明UIGestureRecognizer来拥有一个包含这段代码的委托。
下面是我的解决方案,它将识别器的shouldReceiveTouch直接绑定到键盘是否显示。
在点击手势识别器委托中:
#pragma mark - UIGestureRecognizerDelegate
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
if ([PFXKeyboardStateListener sharedInstance].visible) {
return YES;
}
return NO;
}
PFXKeyboardStateListener.h:
@interface PFXKeyboardStateListener : NSObject
{
BOOL _isVisible;
}
+ (PFXKeyboardStateListener *)sharedInstance;
@property (nonatomic, readonly, getter=isVisible) BOOL visible;
@end
PFXKeyboardStateListener.m:
static PFXKeyboardStateListener *sharedInstance;
@implementation PFXKeyboardStateListener
+ (PFXKeyboardStateListener *)sharedInstance
{
return sharedInstance;
}
+ (void)load
{
@autoreleasepool {
sharedInstance = [[self alloc] init];
}
}
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
- (BOOL)isVisible
{
return _isVisible;
}
- (void)didShow
{
_isVisible = YES;
}
- (void)didHide
{
_isVisible = NO;
}
- (id)init
{
if ((self = [super init])) {
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
[center addObserver:self selector:@selector(didShow) name:UIKeyboardDidShowNotification object:nil];
[center addObserver:self selector:@selector(didHide) name:UIKeyboardWillHideNotification object:nil];
}
return self;
}
@end
你可能想要更新键盘监听器的单例模式,我还没有得到它。希望这对每个人都有用,就像对我一样。^ ^
虽然现在已经很晚了,很多人发现上面的建议还不错,但我无法让Jason或TMilligan的方法起作用。
我有一个静态tableView与多个单元格包含文本字段接收数字输入只使用数字键盘。这对我来说很理想:
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
if(![touch.view isKindOfClass:[UITableViewCell class]]){
[self.firstTF resignFirstResponder];
[self.secondTF resignFirstResponder];
[self.thirdTF resignFirstResponder];
[self.fourthTF resignFirstResponder];
NSLog(@"Touches Work ");
return NO;
}
return YES;
}
确保你已经在你的.h文件中实现了<UIGestureRecognizerDelegate>。
这条线!view isKindOfClass:[UITableViewCell类]]检查tableViewCell是否被点击,并解散任何活动键盘。
我的情况是不同的,包括一个uisearchbar和uitableview在self.view。我想通过触摸视图来消除uisearchbar键盘。
var tapGestureRecognizer:UITapGestureRecognizer?
override func viewWillAppear(animated: Bool) {
tapGestureRecognizer = UITapGestureRecognizer(target: self, action:Selector("handleTap:"))
}
关于UISearchBar委托方法:
func searchBarShouldBeginEditing(searchBar: UISearchBar) -> Bool {
view.addGestureRecognizer(tapGestureRecognizer!)
return true
}
func searchBarShouldEndEditing(searchBar: UISearchBar) -> Bool {
view.removeGestureRecognizer(tapGestureRecognizer!)
return true
}
当用户触摸self.view时:
func handleTap(recognizer: UITapGestureRecognizer) {
sampleSearchBar.endEditing(true)
sampleSearchBar.resignFirstResponder()
}
我有一个不同的情况,我想要触摸手势函数被调用,只有当用户点击表视图之外。如果用户在表视图内点击,那么触摸手势函数不应该被调用。此外,如果触摸手势函数被调用,它仍然应该将触摸事件传递给被点击的视图,而不是消耗它。
生成的代码是阿卜杜勒拉赫曼·马苏德的答案和尼古拉·尼尔森的答案的组合。
extension MyViewController: UIGestureRecognizerDelegate {
func addGestureRecognizer() {
let tapOnScreen = UITapGestureRecognizer(target: self,
action: #selector(functionToCallWhenUserTapsOutsideOfTableView))
// stop the gesture recognizer from "consuming" the touch event,
// so that the touch event can reach other buttons on view.
tapOnScreen.cancelsTouchesInView = false
tapOnScreen.delegate = self
self.view.addGestureRecognizer(tapOnScreen)
}
// if your tap event is on the menu, don't run the touch event.
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
if touch.view?.isDescendant(of: self.tableView) == true {
return false
}
return true
}
@objc func functionToCallWhenUserTapsOutsideOfTableView() {
print("user tapped outside table view")
}
}
在MyViewController类,类有UITableView,在onViewDidLoad(),我确保调用addGestureRecognizer():
class MyViewController: UIViewController {
...
override func viewDidLoad() {
super.viewDidLoad()
...
self.addGestureRecognizer()
...
}
...
}
Swift 5, 2020年5月。
当我输入文本时,我有一个textField和一个tableView。
初始状态
当我点击tableViewCell或其他东西时我想要2个不同的事件。
键盘和tableView显示出来了
首先我们添加tapGestureRecognizer。
tap = UITapGestureRecognizer(target: self, action: #selector(viewTapped))
tap.delegate = self
view.addGestureRecognizer(tap)
@objc func viewTapped() {
view.endEditing(true)
}
然后我们将以下检查添加到UIGestureRecognizerDelegate中:
extension StadtViewController: UIGestureRecognizerDelegate {
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
if touch.view?.isDescendant(of: self.tableView) == true {
return false
} else {
view.endEditing(true)
return true
}
}
}
如果我想先隐藏键盘,tableView仍然是可见的,并对我的点击做出响应。
在这里输入图像描述
Swift解决方案将于2021年生效。对于这个解决方案,你不需要有对表视图的引用。
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
//return !(touch.view is UITableViewCell) <-- doesn't work, the type of the touched class is not UITableViewCell anymore
var v = touch.view
while v != nil {
if v is UITableView { return false }
v = v?.superview
}
return true
}
用法:
let gestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(YOUR_METHOD))
gestureRecognizer.delegate = self
YOUR_VIEW.addGestureRecognizer(gestureRecognizer)