通过触摸 UITableView 的背景来关闭键盘
我有一个 UITableView
,其中 UITextField
作为单元格。我想在触摸 UITableView
的背景时关闭键盘。我试图通过创建一个 UIButton
大小为 UITableView
并将其放置在 UITableView
后面来实现此目的。唯一的问题是 UIButton 正在捕获所有触摸,即使触摸位于 UITableView 上也是如此。我做错了什么?
谢谢!
I have a UITableView
with UITextField
s as cells. I would like to dismiss the keyboard when the background of the UITableView
is touched. I'm trying to do this by creating a UIButton
the size of the UITableView
and placing it behind the UITableView
. The only problem is the UIButton
is catching all the touches even when the touch is on the UITableView. What am I doing wrong?
Thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(29)
UITableView 是 UIScrollView 的子类。
我这样做的方法是监听用户的滚动事件,然后 resignFirstResponder。这是要在代码中实现的 UIScrollViewDelegate 方法;
<代码>
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
当解决这类问题时,我发现最好的方法是研究每个对象及其父类的委托协议(在本例中为 UITableViewDelegate、UIScrollViewDelegate)。NS 对象触发的事件数量相当大而且更全面。实现协议比子类化任何东西都更容易。
UITableView is a subclass of UIScrollView.
The way I did it was to listen for a scroll event by the user and then resignFirstResponder. Here's the UIScrollViewDelegate method to implement in your code;
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
When approaching these sorts of problems I've found the best way is to research the delegate protocols for each object and those of the parent classes (in this case UITableViewDelegate, UIScrollViewDelegate. The number of events NS objects fires is quite large and comprehensive. It's also easier implementing a protocol then subclassing anything.
我遇到了同样的问题,这是我的解决方案,它非常适合我:
在您实现
的视图或视图控制器中(在我的情况下,我有一个自定义
UITableViewCell 称为 TextFieldCell),
将
UITapGestureRecognizer
声明为属性:并在视图/控制器中初始化它:
在
- (void)textFieldDidBeginEditing:(UITextField *)textField
方法中,使用superView
向上移动到你的 tableView 并调用addGestureRecognizer
:在
- (void)textFieldDidEndEditing:(UITextField *)textField
中,只需删除手势识别器:希望有帮助。
I had the same problem and here's my solution, it works perfectly for me:
In the view or view controller that you implemented
<UITextFieldDelegate>
(In my case I have a custom
UITableViewCell
called TextFieldCell),Declare the
UITapGestureRecognizer
as a property:And initialize it in your view/controller:
In the
- (void)textFieldDidBeginEditing:(UITextField *)textField
method, usesuperView
to move up to your tableView and calladdGestureRecognizer
:And in the
- (void)textFieldDidEndEditing:(UITextField *)textField
, just remove the gesture recognizer:Hope it helps.
我希望我的单元格在选择单元格的任何部分时打开键盘,并在单击单元格外的任何位置时关闭键盘。要打开键盘:(
注意:我已经对单元格进行了子类化,但您可以在
UITableView
的tableView:didSelectRowAtIndexPath:
委托方法中轻松实现此目的)这样做意味着顶级解决方案如果您单击单元格两次键盘会震动,因为首先手势识别器尝试关闭键盘,然后重新选择单元格并尝试打开键盘。
解决方案是检查单击是否发生在当前选定的单元格内:
I wanted my cell to open the keyboard when any part of the cell was selected and close it if you clicked anywhere off the cell. To open the keyboard:
(NOTE: I've subclassed the cell but you can easily achieve this in the
tableView:didSelectRowAtIndexPath:
delegate method ofUITableView
)Doing this meant that with the top solutions if you clicking on the cell twice the keyboard would shake as, first the gesture recogniser tried to close the keyboard, and second the cell was reselected and tried open the keyboard.
Solution is to check whether the click occurred inside the currently selected cell:
我找到了一个非常有效的解决方案。
需要使用UIGestureRecognizerDelegate和方法-gestureRecognizer:shouldReceiveTouch:。
将手势识别器添加到 TableView,如下所示:
然后,实现 shouldReceiveTouch 委托方法以拒绝在 UITableViewCell 类中执行的触摸。仅当在 UITableViewCell 类外部执行触摸时才会调用 hideKeyboard 方法。
I've found a solution that works great.
Is needed to use the UIGestureRecognizerDelegate and the method – gestureRecognizer:shouldReceiveTouch:.
Add the gesture recognizer to the TableView as follows:
Then, implement the shouldReceiveTouch delegate method to reject touches that are performed in UITableViewCell class. The hideKeyboard method only will be called when the touch has been performed outside UITableViewCell class.
UITableView
有一个方便的backgroundView
属性,我用它实现了此行为,而不会干扰单元格选择,如下所示(在 Swift 中):UITableView
has a handybackgroundView
property, with which I achieved this behavior without messing with cell selection, as shown below in Swift:我正在寻找解决方案,但没有找到任何适合我的代码的内容,所以我这样做了:
http://82517.tumblr.com/post/13189719252/dismiss-keyboard-on-uitableview-non-cell-tap
基本上是之前的组合- 提到的方法,但不需要子类化任何内容或创建背景按钮。
I was searching for the solution and did not find anything that would fit my code, so I did it like this:
http://82517.tumblr.com/post/13189719252/dismiss-keyboard-on-uitableview-non-cell-tap
It's basically a combination of before-mentioned approaches but does not require to subclass anything or to create background buttons.
简单地使用 UITapGestureRecognizer 和 cancelsTouchesInView = NO 意味着点击单元格和 UITextView 也会触发隐藏。如果您有多个 UITextView 并且点击下一个,这会很糟糕。键盘将开始隐藏,然后下一个 textView 成为第一个响应者,键盘再次变得可见。为了避免这种情况,请检查点击位置,并且仅在点击不在单元格上时隐藏键盘:
为了触发
scrollViewWillBeginDragging:
,tableView 的scrollEnabled
属性必须是YES
Simply using a UITapGestureRecognizer and
cancelsTouchesInView = NO
means that taps on cells and UITextViews also trigger the hide. This is bad if you have multiple UITextViews and you tap on the next one. The keyboard will start to hide and then the next textView becomes the firstResponder and the keyboard becomes visible again. To avoid this, check the tap location and only hide the keyboard if the tap isn't on a cell:In order for
scrollViewWillBeginDragging:
to be triggered, the tableView'sscrollEnabled
property must beYES
Swift 4/4.2/5
您还可以在点击单元格时关闭键盘 - 在执行其他操作之前。
Swift 4/4.2/5
You can also dismiss the keyboard when a cell is tapped - prior to doing anything else.
tableView.keyboardDismissMode = .onDrag // .interactive
tableView.keyboardDismissMode = .onDrag // .interactive
为什么要创建一个充满文本字段的表格?您应该对包含文本字段的每一行使用详细视图。
当您推送详细视图时,请确保调用“[myTextField成为FirstResponder]”,以便用户只需在表格列表中单击一下即可开始编辑。
Why do you want to create a table full of textfields? You should be using a detailed view for each row that contains the text fields.
When you push your detailedview, ensure that you call "[myTextField becomeFirstResponder]" so that the user can start editing with just one click away from the table list.
如果您愿意子类化(呃!)您的表视图,类似这样的可能会起作用:
If you're willing to subclass (ugh!) your table view, something like this might work:
如果您想在按下返回键时关闭键盘,您可以简单地在 textField 应该返回方法中添加以下代码,即:
某些文本字段可能有一个选择器视图或其他一些作为子视图,因此在这种情况下,上述方法不会不起作用,所以在这种情况下我们需要使用 UITapGestureRecognizer 类,即将以下代码片段添加到 viewDidLoad 方法,即:
现在只需将辞职响应者添加到选择器方法,即:
希望它有帮助,谢谢:)
If you want to dismiss the keyboard while return key is pressed,you can simply add the following code in textField should return method i.e.:
Some textfields might have a picker view or some other as a subview,so in that case the above method doesn't work so in that case we need to make use of UITapGestureRecognizer class i.e. add the following code snippet to viewDidLoad method i.e.:
Now simply add the resign responder to the selector method i.e.:
Hope it helps,thanks :)
许多有趣的答案。我想将不同的方法编译成我认为最适合 UITableView 场景的解决方案(这是我通常使用的方法):
我们通常想要的基本上是在两种情况下隐藏键盘:点击文本 UI 元素外部时,或向下/向上滚动 UITableView 时。第一个场景我们可以通过 TapGestureRecognizer 轻松添加,第二个场景则通过 UIScrollViewDelegate scrollViewWillBeginDragging: 方法添加。
第一个任务是隐藏键盘的方法:
此方法会放弃 UITableView 视图层次结构中子视图的任何 textField UI,因此它比单独放弃每个元素更实用。
接下来,我们通过外部 Tap 手势来处理关闭,方法是:
将 tapGestureRecognizer.cancelsTouchesInView 设置为 NO 是为了避免gestureRecognizer 覆盖 UITableView 的正常内部工作(例如,不干扰单元格选择)。
最后,为了处理在UITableView上/下滚动时隐藏键盘,我们必须实现UIScrollViewDelegate协议scrollViewWillBeginDragging:方法,如:
.h 文件
.m 文件
我希望它有帮助! =)
Many interesting answers. I would like to compile different approaches into the solution that i thought best fit a UITableView scenario (it's the one I usually use):
What we usually want is basically to hide the keyboard on two scenarios: on tapping outside of the Text UI elements, or on scrolling down/up the UITableView. The first scenario we can easily add via a TapGestureRecognizer, and the second via the UIScrollViewDelegate scrollViewWillBeginDragging: method.
First order of business, the method to hide the keyboard:
This method resigns any textField UI of the subviews within the UITableView view hierarchy, so it's more practical than resigning every single element independently.
Next we take care of dismissing via an outside Tap gesture, with:
Setting tapGestureRecognizer.cancelsTouchesInView to NO is to avoid the gestureRecognizer from overriding the normal inner workings of the UITableView (for example, not to interfere with cell Selection).
Finally, to handle hiding the keyboard on Scrolling up/down the UITableView, we must implement the UIScrollViewDelegate protocol scrollViewWillBeginDragging: method, as:
.h file
.m file
I hope it helps! =)
这是我最终制作作品的方式。我结合了不同答案的建议和代码。
功能:关闭键盘,在编辑和设置“下一步”和“完成”键盘返回类型时移动键盘上方的文本字段。用更多字段替换“...”
Here's how I finally made works. I combined suggestions and codes from different answers.
Features: dismissing keyboard, moving text fields above keyboard while editing and setting "Next" and "Done" keyboard return type.REPLACE "..." with more fields
@mixca 的答案非常有用,但是如果我有与 UITextField 不同的东西怎么办?我认为最好的处理方法是使用递归函数搜索主视图的所有子视图,检查下面的示例
,您也可以将此方法放入您的实用程序类中,并可以像@mixca的答案一样从点击手势中使用。
@mixca's answer is very useful but what if i've something different from UITextField. I think best way to handle it by searching all subviews of main view with recursive function, check example below
and also you can put this method to your utility class and can use from tap gesture like @mixca's answer..
通过创建 UITapGestureRecognizer 对象可以轻松完成此操作(默认情况下,这将检测“手势”)单击一次,因此无需进一步自定义),指定触发手势时的目标/操作,然后将手势识别器对象附加到表格视图。
例如,也许在您的
viewDidLoad
方法中:并且
hideKeyboard
方法可能如下所示:请注意,触摸
UITextField
对象内部时不会触发手势。它在UITableView
背景、页脚视图、标题视图和单元格内的UILabels
等上触发。This is easily done by creating a UITapGestureRecognizer object (by default this will detect a "gesture" on a single tap so no further customization is required), specifying a target/action for when the gesture is fired, and then attaching the gesture recognizer object to your table view.
E.g. Perhaps in your
viewDidLoad
method:And the
hideKeyboard
method might look like this:Note that the gesture is not fired when touching inside a
UITextField
object. It is fired though on theUITableView
background, footer view, header view and onUILabels
inside cells etc.如果您设置: UITapGestureRecognizer 解决方案可与表格单元格选择一起使用:
The UITapGestureRecognizer solution works with table cell selection if you set:
这是执行此操作的最佳方法。
只需这样做
或
Here is a best way to do this.
Just do this
or
您也可以从故事板中执行此操作:
You can also do it from Storyboard:
由于
UITableView
是UIScrollView
的子类,因此实现下面的一个委托方法提供了一种极其简单、快速的解决方案。甚至不需要涉及resignFirstResponder
因为视图层次结构会内省并找到当前响应者并要求其放弃其响应者状态。并记住将
UIScrollViewDelegate
添加到头文件中。As
UITableView
is a subclass ofUIScrollView
, implementing one delegate method below provides an extremely easy, quick solution. No need to even involveresignFirstResponder
since view hierarchy introspects and finds the current responder and asks it to resign it's responder status.And remember to add
UIScrollViewDelegate
to header file.首先,通过添加
UIScrollViewDelegate
在UIViewController
中监听scrollViewWillBeginDragging
:在 .h 文件中:
在 .m 文件中:
然后监听其他交互:
然后实现
dismissKeyboard
:如果像我一样,您想关闭自定义表格单元格内 UITextField 的键盘:
希望这可以帮助任何人搜索!
Firstly, listen for
scrollViewWillBeginDragging
in yourUIViewController
by adding theUIScrollViewDelegate
:In .h file:
In .m file:
Then listen for other interactions:
Then implement
dismissKeyboard
:And if, like me, you wanted to dismiss the keyboard for a UITextField inside a custom table cell:
Hope that helps anyone searching!!
这是为您带来编码乐趣的快速版本:
它添加了点击手势识别器,然后关闭键盘。 TextField 不需要插座!
Here's the swift version for your coding pleasure:
It adds a tap gesture recognizer then dismisses the keyboard. No outlet for the TextField is required!
有 Swift 3 版本,不会阻止对单元格的点击。
在
viewDidLoad()
方法中:hideKeyboard
看起来像这样:There is Swift 3 version without blocking taps on cells.
In
viewDidLoad()
method:And
hideKeyboard
looks like this:我是这样做的:
在 TableViewController 中创建一个方法来停用第一响应者(此时将是您的 TextBox)
在
tableView:didSelectRowAtIndexPath:
中调用前面的方法:I did it like this:
Create a method in your TableViewController to deactivate first responder (which would be your TextBox at that point)
In
tableView:didSelectRowAtIndexPath:
call the previous method:我有一个
UITableViewController
并且实现touchesBegan:withEvent:
对我来说不起作用。这是有效的:
Swift:
Objective-C:
I had a
UITableViewController
and implementingtouchesBegan:withEvent:
didn't work for me.Here's what worked:
Swift:
Objective-C:
然后确保在 Nib 文件中将 UITableView 的类型设置为 DismissableUITableView .....也许我可以为此类想到一个更好的名称,但你明白了。
Then make sure that in your Nib file you set the type of your UITableView to DismissableUITableView .....maybe i could have thought of a better name for this class, but you get the point.
如果您的目标是 iOS7,则可以使用以下选项之一:
前者将在滚动表视图时将键盘动画化到屏幕外,后者将像普通消息应用程序一样隐藏键盘。
请注意,这些来自
UIScrollView
,UITableView
继承自它。If you are targeting iOS7 you can use one of the following:
The former will animate the keyboard off screen when the table view is scrolled and the later will hide the keyboard like the stock Messages app.
Note that these are from
UIScrollView
, whichUITableView
inherits from.试试这个:
Try this: