395

在IB的库中,介绍告诉我们,当return按键被按下时,键盘forUITextView会消失。但实际上return密钥只能充当'\n'。

我可以添加一个按钮并用于[txtView resignFirstResponder]隐藏键盘。

但是有没有办法为return键盘中的键添加操作,这样我就不需要添加了UIButton

4

34 回答 34

519

想我会在这里发布代码段:

确保您声明支持该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
}
于 2010-05-21T03:42:16.080 回答
364

UITextView当用户点击返回键时,没有任何方法将被调用。如果您希望用户只能添加一行文本,请使用UITextField. 按回车键并隐藏键盘 aUITextView不符合界面指南。

即使那样,如果您想这样做,请实现 and 的textView:shouldChangeTextInRange:replacementText:方法UITextViewDelegate,检查替换文本是否为\n,隐藏键盘。

可能还有其他方法,但我不知道。

于 2009-04-01T05:41:17.827 回答
83

我知道这已经得到了回答,但我真的不喜欢将字符串文字用于换行符,所以这就是我所做的。

- (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
}
于 2011-06-30T16:30:37.520 回答
44

我知道这已经被回答了很多次,但这是我对这个问题的两分钱。

我发现samvermetteribeto的答案非常有用,而且maxpower在ribeto的答案中的评论也是如此。但是这些方法存在问题。马特samvermette的回答中提到的问题是,如果用户想要粘贴带有换行符的内容,键盘将隐藏而不粘贴任何内容。

所以我的方法是上述三种解决方案的混合,并且仅在字符串长度为 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;
}
于 2014-05-21T09:29:56.037 回答
37

一种更优雅的方法是当用户点击键盘框架之外的某个位置时关闭键盘。

首先,在 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];
}

当用户在键盘外点击而不点击输入空间时,键盘将关闭。

于 2012-10-07T05:36:24.397 回答
35

在您的视图控制器中添加此方法。

斯威夫特

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()
        }
    }
}
于 2015-02-24T05:36:14.960 回答
26
-(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"]),则无法编辑

于 2012-06-05T04:25:19.883 回答
18

与 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];
}
于 2014-09-23T09:02:18.943 回答
18

我发现josebama的答案是该线程中最完整和最干净的答案。

下面是它的Swift 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
}
于 2017-08-11T10:17:07.173 回答
14

UITextViewDelegate与使用但更新的 swift 界面的其他答案类似isNewline

func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
    if let character = text.first, character.isNewline {
        textView.resignFirstResponder()
        return false
    }
    return true
}
于 2020-04-30T16:55:37.833 回答
6

使用导航控制器托管一个栏以关闭键盘:

在 .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;
}
于 2011-11-15T00:11:12.510 回答
6

迅速

func textView(textView: UITextView, shouldChangeTextInRange range: NSRange, replacementText text: String) -> Bool {
    if text == "\n" {
        textView.resignFirstResponder()
    }
    return true
}

并配置

于 2016-02-22T23:40:48.020 回答
5

就像对 samvermette 的马特评论一样,我也不喜欢检测“\n”的想法。UITextView 中有“return”键是有原因的,当然是转到下一行。

我认为最好的解决方案是模仿 iPhone 消息应用程序——即在键盘上添加工具栏(和按钮)。

我从以下博客文章中获得了代码:

http://www.iosdevnotes.com/2011/02/iphone-keyboard-toolbar/

脚步:

- 将工具栏添加到您的 XIB 文件 - 将高度设置为 460

- 添加工具栏按钮项(如果尚未添加)。如果需要右对齐,还要在XIB中添加灵活的bar button item,并移动toolbar button item

- 创建将按钮项链接到 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];
}
于 2012-03-21T00:16:20.260 回答
5

在 viewDidLoad 中添加观察者

[[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(textViewKeyPressed:) name: UITextViewTextDidChangeNotification object: nil];

然后使用选择器检查“\n”

-(void) textViewKeyPressed: (NSNotification*) notification {

  if ([[[notification object] text] hasSuffix:@"\n"])
  {
    [[notification object] resignFirstResponder];
  }
}

它确实使用“\n”并且没有专门检查返回键,但我认为这没关系。

更新

请参阅下面 ribto 的答案,它使用[NSCharacterSet newlineCharacterSet]代替\n

于 2012-09-07T20:58:32.620 回答
5

只是用不同的方式解决了这个问题。

  • 创建一个将放置在背景中的按钮
  • 在属性检查器中,将按钮类型更改为自定义,并使按钮透明。
  • 展开按钮以覆盖整个视图,并确保按钮位于所有其他对象的后面。简单的方法是将按钮拖到视图中的列表视图顶部
  • 控制将按钮拖动到viewController.h文件并创建一个动作(Sent Event: Touch Up Inside),如:

    (IBAction)ExitKeyboard:(id)sender;
    
  • ViewController.m应该看起来像:

    (IBAction)ExitKeyboard:(id)sender {
        [self.view endEditing:TRUE];
    }
    
  • 运行应用程序,当您单击离开 TextView 时,键盘消失
于 2014-02-27T10:06:43.200 回答
5

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()
            }
        }
    }
}

编辑 我更新了代码,因为在 hack 代码完成后将文本字段中的用户输入更改为 workarround 并且不重置状态绝不是一个好主意。

于 2014-11-06T19:32:06.523 回答
4

试试这个 :

 - (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text{
    if ([text isEqualToString:@"\n"]) {
        [self.view endEditing:YES];
    }

    return YES;

}
于 2013-12-06T10:57:21.023 回答
4

//你可以用这个...

步骤 1. 第一步是确保您声明支持该UITextViewDelegate协议。这是在您的头文件中完成的,例如这里的头文件名为

编辑器控制器.h:

@interface EditorController : UIViewController  {
  UITextView *messageTextView;
}

@property (nonatomic, retain) UITextView *messageTextView;

@end

第 2 步。接下来,您需要将控制器注册为 UITextView 的委托。继续上面的例子,下面是我如何将UITextViewwith初始化EditorController为委托……</p>

- (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;
}
于 2015-01-19T11:40:34.180 回答
3

您还可以在视图屏幕中触摸时隐藏键盘:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
     UITouch * touch = [touches anyObject];
     if(touch.phase == UITouchPhaseBegan) {
        [txtDetail resignFirstResponder];
      }
 }
于 2014-02-24T10:24:46.420 回答
3

快速回答:

override func viewDidLoad() {
    super.viewDidLoad()
    let tapGestureReconizer = UITapGestureRecognizer(target: self, action: "tap:")
    view.addGestureRecognizer(tapGestureReconizer)
}

func tap(sender: UITapGestureRecognizer) {
    view.endEditing(true)
}
于 2015-06-15T02:26:08.767 回答
3

我使用此代码更改响应者。

 - (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;

    }
于 2015-09-23T11:23:32.110 回答
3

该问题询问如何使用返回键来执行此操作,但我认为这可以帮助那些打算在使用 UITextView 时让键盘消失的人:

private func addToolBarForTextView() {
    let textViewToolbar: UIToolbar = UIToolbar()
    textViewToolbar.barStyle = .default
    textViewToolbar.items = [
        UIBarButtonItem(title: "Cancel", style: .done,
                  target: self, action: #selector(cancelInput)),
        UIBarButtonItem(barButtonSystemItem: .flexibleSpace,
                  target: self, action: nil),
        UIBarButtonItem(title: "Post Reply", style: .done,
                  target: self, action: #selector(doneInput))
    ]
    textViewToolbar.sizeToFit()
    yourTextView.inputAccessoryView = textViewToolbar
}

@objc func cancelInput() { print("cancel") }
@objc func doneInput() { print("done") }

override func viewDidLoad() {
    super.viewDidLoad()
    addToolBarForTextView()
}

viewDidLoad或其他一些生命周期方法中调用addToolBarForTextView() 。

看来这对我来说是完美的解决方案。

干杯,

穆拉特

于 2016-12-16T11:04:37.887 回答
2

行。每个人都给出了技巧的答案,但我认为实现这一目标的正确方法是

将以下操作连接到 中的“退出时结束”事件Interface Builder。(右键单击TextField并 cntrl-从 ' Did end on exit ' 拖动到以下方法。

-(IBAction)hideTheKeyboard:(id)sender
{
    [self.view endEditing:TRUE];
}
于 2012-01-31T10:53:16.667 回答
1
- (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;
}
于 2014-08-27T06:37:38.270 回答
1
+ (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;
    }
}
于 2015-03-10T08:01:46.873 回答
1

您应该添加UIToolbar到顶部 UITextView 以简化而不是使用shouldChangeTextIn

在斯威夫特 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()
}
于 2019-02-25T10:32:13.240 回答
0

我知道这不是这个问题的确切答案,但我在上网寻找答案后找到了这个帖子。我假设其他人也有这种感觉。

这是我发现可靠且易于使用的 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");
}

我希望这有帮助。看起来很明显,但我从未在网络上的任何地方看到过这个解决方案——我做错了什么吗?

于 2013-10-13T21:12:27.470 回答
0

不要忘记为 textView 设置委托 - 否则 resignfirstresponder 将不起作用。

于 2014-05-20T06:53:07.330 回答
0

试试这个 。

NSInteger lengthOfText = [[textView.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] length];
于 2015-03-31T09:51:55.427 回答
0

对于 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()
        }
    }
于 2015-07-09T09:12:13.157 回答
-1

我对此的破解:

1-创建一个覆盖整个视图的按钮;2-将其发送到视图的背景,3-在属性检查器中将其类型从“圆形矩形”更改为“自定义”,4-创建一个动作 5-实现动作方法:

- (IBAction)bgTouched:(id)sender 
{
    //to dismiss keyboard on bg btn pressed
    [_userInput resignFirstResponder];
}

其中 _userInput 是您的 TextField 出口

于 2013-10-21T11:55:42.957 回答
-1

对于 Swift 3,此代码允许我在 UITextView 外部按下以关闭键盘。

@IBOutlet weak var comment: UITextView!

   override func viewDidLoad() {
        super.viewDidLoad()

        comment.delegate = self

        let tapGestureRecogniser = UITapGestureRecognizer(target: self, action: #selector(tap))
        view.addGestureRecognizer(tapGestureRecogniser)
    }

    func tap(sender: UITapGestureRecognizer) {
        if comment.isFirstResponder {
            comment.resignFirstResponder()
        }
    }
于 2017-02-02T10:56:31.237 回答
-2
-(BOOL)textFieldShouldReturn:(UITextField *)textField; // called from textfield (keyboard)

-(BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text; // good tester function - thanks
于 2010-12-30T16:53:37.253 回答
-2

隐藏Queboard的功能。

- (void)HideQueyboard
{
    [[UIApplication sharedApplication] sendAction:@selector(resignFirstResponder)   to:nil from:nil forEvent:nil];
}
于 2014-11-01T21:13:58.110 回答