如何使用返回键关闭 UITextView 的键盘?
-
22-08-2019 - |
题
在IB的图书馆中,简介告诉我们,当 返回 键被按下,键盘为 UITextView
会消失。但实际上 返回 键只能充当“
”。
我可以添加一个按钮并使用 [txtView resignFirstResponder]
隐藏键盘。
但是有没有办法添加动作 返回 在键盘上键入这样我就不需要添加 UIButton
?
解决方案
UITextView
没有任何当用户按下返回键时将被调用的方法。如果您希望用户只能添加一行文本,请使用 UITextField
. 。按回车键并隐藏键盘一段时间 UITextView
不遵循界面指南。
即使如此,如果您想这样做,请实施 textView:shouldChangeTextInRange:replacementText:
的方法 UITextViewDelegate
并检查替换文本是否是 \n
, ,隐藏键盘。
可能还有其他方法,但我不知道。
其他提示
我想我应该把代码片段贴在这里:
确保您声明支持 UITextViewDelegate
协议。
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {
if([text isEqualToString:@"\n"]) {
[textView resignFirstResponder];
return NO;
}
return YES;
}
斯威夫特4.0更新:
func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
if text == "\n" {
textView.resignFirstResponder()
return false
}
return true
}
我知道这个问题已经得到解答,但我真的不喜欢使用字符串文字作为换行符,所以这就是我所做的。
- (BOOL)textView:(UITextView *)txtView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {
if( [text rangeOfCharacterFromSet:[NSCharacterSet newlineCharacterSet]].location == NSNotFound ) {
return YES;
}
[txtView resignFirstResponder];
return NO;
}
斯威夫特4.0更新:
func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
if (text as NSString).rangeOfCharacter(from: CharacterSet.newlines).location == NSNotFound {
return true
}
txtView.resignFirstResponder()
return false
}
我知道这个问题已经被回答过很多次了,但这里是我对这个问题的两点看法。
我找到了答案 萨姆弗梅特 和 里贝托 真的很有用,还有评论 最大功率 在里面 里贝托的回答。但这些方法存在一个问题。问题在于 马特 中提到的 萨姆弗梅特的答案是,如果用户想要粘贴带有换行符的内容,键盘将隐藏而不粘贴任何内容。
所以我的方法是混合上述三种解决方案,并且仅在字符串长度为 1 时检查输入的字符串是否为新行,以便我们确保用户正在键入而不是粘贴。
这是我所做的:
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {
NSRange resultRange = [text rangeOfCharacterFromSet:[NSCharacterSet newlineCharacterSet] options:NSBackwardsSearch];
if ([text length] == 1 && resultRange.location != NSNotFound) {
[textView resignFirstResponder];
return NO;
}
return YES;
}
一种更优雅的方法是当用户点击键盘框架之外的某个位置时关闭键盘。
首先,在 UIBuilder 的身份检查器中将 ViewController 的视图设置为“UIControl”类。按住 Control 键并将视图拖动到 ViewController 的头文件中,并将其作为操作与 Touch Up Inside 事件链接起来,例如:
视图控制器.h
-(IBAction)dismissKeyboardOnTap:(id)sender;
在主 ViewController 文件 ViewController.m 中:
-(IBAction)dismissKeyboardOnTap:(id)sender
{
[[self view] endEditing:YES];
}
您可以使用类似的技术要求双击或长按。您可能需要将 ViewController 设置为 UITextViewDelegate 并将 TextView 连接到 ViewController。此方法适用于 UITextView 和 UITextField。
来源:大书呆子牧场
编辑:我还想补充一点,如果您使用的是 UIScrollView,则上述技术可能无法通过 Interface Builder 轻松实现。在这种情况下,您可以使用 UIGestureRecognizer 并调用其中的 [[self view] endEditing:YES] 方法。一个例子是:
-(void)ViewDidLoad{
....
UITapGestureRecognizer *tapRec = [[UITapGestureRecognizer alloc]
initWithTarget:self action:@selector(tap:)];
[self.view addGestureRecognizer: tapRec];
....
}
-(void)tap:(UITapGestureRecognizer *)tapRec{
[[self view] endEditing: YES];
}
当用户点击键盘外部且未点击输入空间时,键盘将关闭。
在您的视图控制器中添加此方法。
迅速:
func textView(textView: UITextView, shouldChangeTextInRange range: NSRange, replacementText text: String) -> Bool {
if text == "\n" {
textView.resignFirstResponder()
return false
}
return true
}
此方法也可以对您有所帮助:
/**
Dismiss keyboard when tapped outside the keyboard or textView
:param: touches the touches
:param: event the related event
*/
override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
if let touch = touches.anyObject() as? UITouch {
if touch.phase == UITouchPhase.Began {
textField?.resignFirstResponder()
}
}
}
-(BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {
if([text isEqualToString:@"\n"])
[textView resignFirstResponder];
return YES;
}
yourtextView.delegate=self;
还添加 UITextViewDelegate
不要忘记确认协议
如果你没有添加 if([text isEqualToString:@"\n"])
你不能编辑
与 uitextview 一起使用时还有另一种解决方案, 您可以在“textViewShouldBeginEditing”中将工具栏添加为 InputAccessoryView,并且从此工具栏的完成按钮可以关闭键盘,其代码如下:
在 viewDidLoad 中
toolBar = [[UIToolbar alloc]initWithFrame:CGRectMake(0, 0, 320, 44)]; //toolbar is uitoolbar object
toolBar.barStyle = UIBarStyleBlackOpaque;
UIBarButtonItem *btnDone = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(btnClickedDone:)];
[toolBar setItems:[NSArray arrayWithObject:btnDone]];
在textviewdelegate方法中
- (BOOL)textViewShouldBeginEditing:(UITextView *)textView
{
[textView setInputAccessoryView:toolBar];
return YES;
}
工具栏中“完成”按钮的操作如下:
-(IBAction)btnClickedDone:(id)sender
{
[self.view endEditing:YES];
}
我找到了答案 何塞巴马 成为该线程中最完整、最干净的答案。
下面是 雨燕4 它的语法:
func textView(_ textView: UITextView, shouldChangeTextIn _: NSRange, replacementText text: String) -> Bool {
let resultRange = text.rangeOfCharacter(from: CharacterSet.newlines, options: .backwards)
if text.count == 1 && resultRange != nil {
textView.resignFirstResponder()
// Do any additional stuff here
return false
}
return true
}
使用导航控制器托管一个栏以关闭键盘:
在.h文件中:
UIBarButtonItem* dismissKeyboardButton;
在 .m 文件中:
- (void)viewDidLoad {
dismissKeyboardButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(dismissKeyboard)];
}
-(void)textViewDidBeginEditing:(UITextView *)textView {
self.navigationItem.rightBarButtonItem = dismissKeyboardButton;
}
-(void)textFieldDidBeginEditing:(UITextField *)textField {
self.navigationItem.rightBarButtonItem = dismissKeyboardButton;
}
-(void)dismissKeyboard {
[self.textField resignFirstResponder];
[self.textView resignFirstResponder];
//or replace this with your regular right button
self.navigationItem.rightBarButtonItem = nil;
}
就像马特对 samvermette 的评论一样,我也不喜欢检测“ ”的想法。UITextView 中存在“返回”键是有原因的,那就是当然可以转到下一行。
我认为最好的解决方案是模仿iPhone消息应用程序——即在键盘上添加工具栏(和按钮)。
我从以下博客文章中获得了代码:
http://www.iosdevnotes.com/2011/02/iphone-keyboard-toolbar/
脚步:
- 将工具栏添加到您的 XIB 文件 - 将高度设置为 460
-添加工具栏按钮项目(如果尚未添加)。如果需要右对齐,还要在 XIB 中添加灵活的栏按钮项,并移动工具栏按钮项
- 创建将按钮项目链接到 resignFirstResponder 的操作,如下所示:
- (IBAction)hideKeyboard:(id)sender {
[yourUITextView resignFirstResponder];
}
-然后:
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
}
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillShowNotification object:nil];
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillHideNotification object:nil];
}
- (void)keyboardWillShow:(NSNotification *)notification {
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.3];
CGRect frame = self.keyboardToolbar.frame;
frame.origin.y = self.view.frame.size.height - 260.0;
self.keyboardToolbar.frame = frame;
[UIView commitAnimations];
}
- (void)keyboardWillHide:(NSNotification *)notification {
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.3];
CGRect frame = self.keyboardToolbar.frame;
frame.origin.y = self.view.frame.size.height;
self.keyboardToolbar.frame = frame;
[UIView commitAnimations];
}
只是用不同的方式解决了这个问题。
- 创建一个将放置在后台的按钮
- 从属性检查器中,将按钮类型更改为自定义,并使按钮透明。
- 展开按钮以覆盖整个视图,并确保按钮位于所有其他对象的后面。执行此操作的简单方法是将按钮拖动到视图中列表视图的顶部
控制按钮拖动到
viewController.h
文件并创建一个操作(发送事件:内部修饰)如:(IBAction)ExitKeyboard:(id)sender;
在
ViewController.m
应该看起来像:(IBAction)ExitKeyboard:(id)sender { [self.view endEditing:TRUE]; }
- 运行应用程序,当您单击远离 TextView 时,键盘消失
在viewDidLoad中添加观察者
[[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(textViewKeyPressed:) name: UITextViewTextDidChangeNotification object: nil];
然后使用选择器检查“ ”
-(void) textViewKeyPressed: (NSNotification*) notification {
if ([[[notification object] text] hasSuffix:@"\n"])
{
[[notification object] resignFirstResponder];
}
}
它确实使用“ ”并且没有专门检查返回键,但我认为这是可以的。
更新
请参阅下面 ribto 的回答,其中使用 [NSCharacterSet newlineCharacterSet]
代替 \n
尝试这个 :
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text{
if ([text isEqualToString:@"\n"]) {
[self.view endEditing:YES];
}
return YES;
}
//你可以使用这个...
步骤1。第一步是确保您声明支持 UITextViewDelegate
协议。这是在您的头文件中完成的,例如这里的头称为
编辑器控制器.h:
@interface EditorController : UIViewController {
UITextView *messageTextView;
}
@property (nonatomic, retain) UITextView *messageTextView;
@end
第2步。接下来,您需要将控制器注册为 UITextView 的委托。继续上面的示例,以下是我如何初始化 UITextView
和 EditorController
作为代表……
- (id) init {
if (self = [super init]) {
// define the area and location for the UITextView
CGRect tfFrame = CGRectMake(10, 10, 300, 100);
messageTextView = [[UITextView alloc] initWithFrame:tfFrame];
// make sure that it is editable
messageTextView.editable = YES;
// add the controller as the delegate
messageTextView.delegate = self;
}
步骤 3.现在,最后的难题是采取行动应对 shouldCahngeTextInRange
留言如下:
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range
replacementText:(NSString *)text
{
// Any new character added is passed in as the "text" parameter
if ([text isEqualToString:@"\n"]) {
// Be sure to test for equality using the "isEqualToString" message
[textView resignFirstResponder];
// Return FALSE so that the final '\n' character doesn't get added
return FALSE;
}
// For any other character return TRUE so that the text gets added to the view
return TRUE;
}
SWIFT代码
在您的类/视图中实现 UITextViewDelegate,如下所示:
class MyClass: UITextViewDelegate { ...
将 textView 委托设置为 self
myTextView.delegate = self
然后执行以下操作:
func textViewDidChange(_ textView: UITextView) {
if textView.text.characters.count >= 1 {
if let lastChar = textView.text.characters.last {
if(lastChar == "\n"){
textView.text = textView.text.substring(to: textView.text.index(before: textView.text.endIndex))
textView.resignFirstResponder()
}
}
}
}
编辑我更新了代码,因为将文本字段中的用户输入更改为解决方法而不是在黑客代码完成后重置状态从来都不是一个好主意。
您还可以在视图屏幕中触摸时隐藏键盘:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch * touch = [touches anyObject];
if(touch.phase == UITouchPhaseBegan) {
[txtDetail resignFirstResponder];
}
}
迅速回答:
override func viewDidLoad() {
super.viewDidLoad()
let tapGestureReconizer = UITapGestureRecognizer(target: self, action: "tap:")
view.addGestureRecognizer(tapGestureReconizer)
}
func tap(sender: UITapGestureRecognizer) {
view.endEditing(true)
}
我使用此代码来更改响应者。
- (BOOL)textView:(UITextView*) textView shouldChangeTextInRange: (NSRange) range replacementText: (NSString*) text
{
if ([text isEqualToString:@"\n"]) {
//[textView resignFirstResponder];
//return YES;
NSInteger nextTag = textView.tag + 1;
// Try to find next responder
UIResponder* nextResponder = [self.view viewWithTag:nextTag];
if (nextResponder) {
// Found next responder, so set it.
[nextResponder becomeFirstResponder];
} else {
// Not found, so remove keyboard.
[textView resignFirstResponder];
}
return NO;
return NO;
}
return YES;
}
好的。每个人都用技巧给出了答案,但我认为实现这一目标的正确方法是
将以下操作连接到“退出时结束“ 事件在 Interface Builder
. 。(右键单击 TextField
然后按住 Ctrl 键并从 ' 拖动退出时结束' 到以下方法。
-(IBAction)hideTheKeyboard:(id)sender
{
[self.view endEditing:TRUE];
}
- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
{
if (range.length==0) {
if ([text isEqualToString:@"\n"]) {
[txtView resignFirstResponder];
if(textView.returnKeyType== UIReturnKeyGo){
[self PreviewLatter];
return NO;
}
return NO;
}
} return YES;
}
+ (void)addDoneButtonToControl:(id)txtFieldOrTextView
{
if([txtFieldOrTextView isKindOfClass:[UITextField class]])
{
txtFieldOrTextView = (UITextField *)txtFieldOrTextView;
}
else if([txtFieldOrTextView isKindOfClass:[UITextView class]])
{
txtFieldOrTextView = (UITextView *)txtFieldOrTextView;
}
UIToolbar* numberToolbar = [[UIToolbar alloc]initWithFrame:CGRectMake(0,
0,
[Global returnDeviceWidth],
50)];
numberToolbar.barStyle = UIBarStyleDefault;
UIBarButtonItem *btnDone = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"btn_return"]
style:UIBarButtonItemStyleBordered
target:txtFieldOrTextView
action:@selector(resignFirstResponder)];
numberToolbar.items = [NSArray arrayWithObjects:btnDone,nil];
[numberToolbar sizeToFit];
if([txtFieldOrTextView isKindOfClass:[UITextField class]])
{
((UITextField *)txtFieldOrTextView).inputAccessoryView = numberToolbar;
}
else if([txtFieldOrTextView isKindOfClass:[UITextView class]])
{
((UITextView *)txtFieldOrTextView).inputAccessoryView = numberToolbar;
}
}
问题询问如何使用返回键执行此操作,但我认为这可以帮助那些意图在使用 UITextView 时使键盘消失的人:
@IBOutlet weak var textView: UITextView!
private func addToolBarForTextView() {
let textViewToolbar: UIToolbar = UIToolbar()
textViewToolbar = UIBarStyle.Default
textViewToolbar = [
UIBarButtonItem(title: "Cancel", style: UIBarButtonItemStyle.Done, target: self, action: #selector(self.cancelInput)),
UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.FlexibleSpace, target: self, action: nil),
UIBarButtonItem(title: "Done", style: UIBarButtonItemStyle.Done, target: self, action: #selector(self.doneInput))
]
textViewToolbar()
self.textView.inputAccessoryView = textViewToolbar //do it for every relevant textView if there are more than one
}
func doneInput() {
self.textView.resignFirstResponder()
}
func cancelInput() {
self.textView.text = ""
self.textView.resignFirstResponder()
}
称呼 addToolBarForTextView() 在里面 viewDidLoad 或其他一些生命周期方法。
看来这对我来说是完美的解决方案。
干杯,
穆拉特
我知道这不是这个问题的确切答案,但我在互联网上寻找答案后发现了这个帖子。我想其他人也有同样的感觉。
这是我对 UITapGestureRecognizer 的变体,我发现它可靠且易于使用 - 只需将 TextView 的委托设置为 ViewController 即可。
当 TextView 变为活动编辑状态时,我添加 UITapGestureRecognizer,而不是 ViewDidLoad:
-(void)textViewDidBeginEditing:(UITextView *)textView{
_tapRec = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(tap:)];
[self.view addGestureRecognizer: _tapRec];
NSLog(@"TextView Did begin");
}
当我点击 TextView 外部时,视图会结束编辑模式,并且 UITapGestureRecognizer 会自行删除,以便我可以继续与视图中的其他控件进行交互。
-(void)tap:(UITapGestureRecognizer *)tapRec{
[[self view] endEditing: YES];
[self.view removeGestureRecognizer:tapRec];
NSLog(@"Tap recognized, tapRec getting removed");
}
我希望这有帮助。这看起来很明显,但我从未在网络上的任何地方看到过这个解决方案 - 我做错了什么吗?
不要忘记为 textView 设置委托 - 否则 resignfirstresponder 将无法工作。
尝试这个 。
NSInteger lengthOfText = [[textView.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] length];
对于 Xcode 6.4、Swift 1.2。:
override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent)
{
super.touchesBegan(touches, withEvent: event)
if let touch = touches.first as? UITouch
{
self.meaningTextview.resignFirstResponder()
}
}
你应该添加 UIToolbar
顶部 UITextView 使其变得简单而不是使用 shouldChangeTextIn
在 Swift 4 中
let toolbar = UIToolbar(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: 50))
toolbar.barStyle = .default
toolbar.items = [
UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil),
UIBarButtonItem(title: "Done", style: .done, target: self, action: #selector(doneAction))
]
textView.inputAccessoryView = toolbar
@objc func doneAction(){
self.textView.resignFirstResponder()
}
-(BOOL)textFieldShouldReturn:(UITextField *)textField; // called from textfield (keyboard)
-(BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text; // good tester function - thanks