關閉ios虛擬鍵盤的幾種方法

来源:http://www.cnblogs.com/shouce/archive/2016/04/08/5366465.html
-Advertisement-
Play Games

在iOS應用開發中,有三類視圖對象會打開虛擬鍵盤,進行輸入操作,但如何關閉虛擬鍵盤,卻沒有提供自動化的方法。這個需要我們自己去實現。這三類視圖對象分別是UITextField,UITextView和UISearchBar。 這裡介紹一下UITextField中關閉虛擬鍵盤的幾種方法。 (miki西游 ...


在iOS應用開發中,有三類視圖對象會打開虛擬鍵盤,進行輸入操作,但如何關閉虛擬鍵盤,卻沒有提供自動化的方法。這個需要我們自己去實現。這三類視圖對象分別是UITextField,UITextView和UISearchBar。 這裡介紹一下UITextField中關閉虛擬鍵盤的幾種方法。

 

(miki西游 @mikixiyou 原文鏈接: http://mikixiyou.iteye.com/blog/1753330 )

第一種方法,使用它的委托UITextFieldDelegate中的方法textFieldShouldReturn:來關閉虛擬鍵盤。 在UITextField視圖對象如birdNameInput所在的類中實現這個方法。

 

C代碼 複製代碼 收藏代碼
  1. - (BOOL)textFieldShouldReturn:(UITextField *)textField {  
  2.     if ((textField == self.birdNameInput) || (textField == self.locationInput)) {  
  3.         [textField resignFirstResponder];  
  4.     }  
  5.     return YES;  
  6. }  
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
    if ((textField == self.birdNameInput) || (textField == self.locationInput)) {
        [textField resignFirstResponder];
    }
    return YES;
}

 

這樣,在輸入框birdNameInput中打開虛擬鍵盤後,輕擊鍵盤的return鍵就會自動關閉掉虛擬鍵盤。
第二種方法,將birdNameInput的屬性中Return Key修改為done,再定義一個方法和Done鍵的Did End On Exit連接。通過輕擊done鍵觸發這個事件來關閉虛擬鍵盤。 定義的方法如下:

 

C代碼 複製代碼 收藏代碼
  1. - (IBAction) textFieldDoneEditing:(id)sender  
  2. {  
  3.         [sender resignFirstResponder];  
  4. }  
- (IBAction) textFieldDoneEditing:(id)sender
{
        [sender resignFirstResponder];
}

 

這兩個方法都是輕擊虛擬鍵盤上一個鍵來關閉它。這屬於精確操作,而手指不像滑鼠,做這種操作不容易。因此就UI層面而言,這兩個方法都不是最好的方法。 在iphone或ipad屏幕上,虛擬鍵盤占用的面積大小是有限的。通過輕擊虛擬鍵盤之外的區域而關閉虛擬鍵盤。

 

第三種方法,通過輕擊鍵盤之外的空白區域關閉虛擬鍵盤。 在birdNameInput所屬的視圖控制器類的viewDidLoad方法中定義一個UITapGestureRecognizer的對象,然後將它賦值為它的視圖。

C代碼 複製代碼 收藏代碼
  1. UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]   initWithTarget:self action:@selector(dismissKeyboard)];  
  2. [self.view addGestureRecognizer:tap];  
  3. [tap release];  
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]   initWithTarget:self action:@selector(dismissKeyboard)];
[self.view addGestureRecognizer:tap];
[tap release];

 

再定義一下選擇器調用的方法dismissKeyboard。

C代碼 複製代碼 收藏代碼
  1. -(void)dismissKeyboard {  
  2.        [birdNameInput resignFirstResponder];  
  3. }  
-(void)dismissKeyboard {
       [birdNameInput resignFirstResponder];
}

  如果屏幕上有多個textField的話,一個一個地列出來就有些麻煩。那麼將方法修改一下,如下:

C代碼 複製代碼 收藏代碼
  1. -(void)dismissKeyboard {  
  2.     NSArray *subviews = [self.view subviews];  
  3.     for (id objInput in subviews) {  
  4.         if ([objInput isKindOfClass:[UITextField class]]) {  
  5.             UITextField *theTextField = objInput;  
  6.             if ([objInput isFirstResponder]) {  
  7.                 [theTextField resignFirstResponder];  
  8.             }  
  9.         }  
  10.     }  
  11. }  
-(void)dismissKeyboard {
    NSArray *subviews = [self.view subviews];
    for (id objInput in subviews) {
        if ([objInput isKindOfClass:[UITextField class]]) {
            UITextField *theTextField = objInput;
            if ([objInput isFirstResponder]) {
                [theTextField resignFirstResponder];
            }
        }
    }
}

 

如果這個屏幕上的視圖對象很複雜的話,另當別論。 這個方法是編碼新建一個手勢對象。也可以直接使用interface builder圖形化開發工具,在storyboard中拉入一個手勢對象到視圖控制器類中,再將此手勢對象建立一個IBACTION,名稱可以是dismissKeyboard。
第四種方法,通過輕擊鍵盤之外的空白區域關閉虛擬鍵盤。 將屏幕上的view也就是textField的父視圖拖一個touch down事件出來,和一個能關閉虛擬鍵盤的方法連接。如果視圖沒有touch down事件,可將view的父類從UIView修改為UIButton。 首先定義並實現一個方法backgroundTap:。

 

C代碼 複製代碼 收藏代碼
  1. - (IBAction) backgroundTap:(id)sender  
  2. {  
  3.         NSArray *subviews = [self.view subviews];  
  4.     for (id objInput in subviews) {  
  5.         if ([objInput isKindOfClass:[UITextField class]]) {  
  6.             UITextField *theTextField = objInput;  
  7.             if ([objInput isFirstResponder]) {  
  8.                 [theTextField resignFirstResponder];  
  9.             }  
  10.         }  
  11.     }  
  12. }  
- (IBAction) backgroundTap:(id)sender
{
        NSArray *subviews = [self.view subviews];
    for (id objInput in subviews) {
        if ([objInput isKindOfClass:[UITextField class]]) {
            UITextField *theTextField = objInput;
            if ([objInput isFirstResponder]) {
                [theTextField resignFirstResponder];
            }
        }
    }
}

 

然後選擇背景視圖的Touch Down事件,連接 backgroundTap:即可。這樣只要輕擊一下虛擬鍵盤之外的區域,就能關閉虛擬鍵盤。這些方法都是使用resignFirstResponder方法來關閉虛擬鍵盤,還有其他的方法。

 

第五種方法,使用endEditing:方法 在所在的視圖控制器類中,覆蓋這個方法。

 

C代碼 複製代碼 收藏代碼
  1. - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {  
  2.       [[self view] endEditing:YES];  
  3. }  
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
      [[self view] endEditing:YES];
}

 

This method looks at the current view and its subview hierarchy for the text field that is currently the first responder. If it finds one, it asks that text field to resign as first responder. If the force parameter is set to YES, the text field is never even asked; it is forced to resign. 但是,如果這個屏幕很複雜,虛擬鍵盤之外的區域中有很多按鈕。輕擊這些區域時可能會輕擊到這些按鈕,這樣虛擬鍵盤就不能關閉。 要是找到一個沒有按鈕的空白區域都不容易且還有隱藏的視圖對象時,通過輕擊虛擬鍵盤之外的區域關閉虛擬鍵盤的方法實現起來就難了。

 

第六種方法,覆蓋hitTest:withEvent:方法關閉虛擬鍵盤

 

在stackoverflow.com上,有人這樣總結。說使用hitTest:withEvent:方法是最好的,也是最容易的解決方法。

 

I think the easiest (and best) way to do this is to subclass your global view and use hitTest:withEvent method to listen to any touch. Touches on keyboard aren't registered, so hitTest:withEvent is only called when you touch/scroll/swipe/pinch... somewhere else, then call [self endEditing:YES]. This is better than using touchesBegan because touchesBegan are not called if you click on a button on top of the view. It is better than UITapGestureRecognizer which can't recognize a scrolling gesture for example. It is also better than using a dim screen because in a complexe and dynamic user interface, you can't put dim screen every where. Moreover, it doesn't block other actions, you don't need to tap twice to select a button outside (like in the case of a UIPopover). Also, it's better than calling [textField resignFirstResponder], because you may have many text fields on screen, so this works for all of them.

 

因此,我再建立一個繼承UIView的視圖類。在這個視圖類中,覆蓋hitTest:withEvent:方法,增加[self endEditing:YES]方法。

C代碼 複製代碼 收藏代碼
  1. - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {  
  2. UIView *result = [super hitTest:point withEvent:event];  
  3. [self endEditing:YES]  
  4. return result;  
  5. }  
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
UIView *result = [super hitTest:point withEvent:event];
[self endEditing:YES]
return result;
}

 

我將視圖控制器的主視圖所屬類修改為這個新建視圖類。這樣在屏幕上輕擊任何位置都會關閉虛擬鍵盤。 這個方法是最簡單,也是最好的關閉虛擬鍵盤的方法。 使用好hitTest:withEvent:這個方法,還可以實現很多很複雜的功能。 The implementation of hitTest:withEvent: in UIResponder does the following:

  •     It calls pointInside:withEvent: of self
  •     If the return is NO, hitTest:withEvent: returns nil. the end of the story.
  •     If the return is YES, it sends hitTest:withEvent: messages to its subviews. it starts from the top-level subview, and continues to other views until a subview returns a non-nil object, or all subviews receive the message.
  •     If a subview returns a non-nil object in the first time, the first hitTest:withEvent: returns that object. the end of the story.
  •     If no subview returns a non-nil object, the first hitTest:withEvent: returns self

This process repeats recursively, so normally the leaf view of the view hierarchy is returned eventually. However, you might override hitTest:withEvent to do something differently. In many cases, overriding pointInside:withEvent: is simpler and still provides enough options to tweak event handling in your application.


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 與其他大部分編程語言不同,Swift 並不強制要求你在每條語句的結尾處使用分號(;),當然,你也可以按照你自己的習慣添加分號。有一種情況下必須要用分號,即你打算在同一行內寫多條獨立的語句 let you = "Forrest" ;print(you) ...
  • 1.在Storyboard滑鼠右鍵可以直接拖線的,如果你用的是外接的第三方滑鼠,沒必要按著 control 鍵再用滑鼠左鍵拖線 如果是觸控板的話,雙指按下去就可以直接拖線,帶3Dtouch功能的觸控板會比較好使 2.雙擊選中一個單詞,三擊選中一行,方便管理 3.刪除時, option + delet ...
  • 一個NSOperation對象就代表一個操作,對象相當於GCD中的block。 一、NSOperation的作用: 配合使用NSOperation和NSOperationQueue也能實現多線程。 二、NSOperation和NSOperationQueue實現多線程的步驟: 步驟1: 先將需要執行 ...
  • 關 於iOS UI調試工具Reveal的配置,很多初學者朋友可能在網上搜索到一些文章,這些文章大部分都是講述瞭如何通過配置Xcode項目,通過加入一些庫文件, 並且在程式中編寫額外的代碼來調用Reveal服務,從而保證調試程式的時候能夠將項目附加到Reveal中分析。 這種方式,比較繁瑣,並且每寫個 ...
  • 引言 Cordova(PhoneGap)採用的是HTML5+JavaScript混合模式來開發移動手機APP,因此當頁面需要獲取手機內部某些信息時(例如:聯繫人信息,坐標定位,簡訊等),程式就需要調用手機內部的API跟頁面進行信息交換。Cordova 特別為此定製了完善的解決方案,以方便用戶進行程式 ...
  • 昨晚在網上看的乾貨,直接分享給大家了,覺得有用的,直接fork吧。 https://github.com/Brances/TimLiu-iOS ...
  • 用GCD實現單例模式的步驟: 步驟1. 創建頭文件 XZSingleton.h,裡面代碼如下: 步驟2. 要實現的單例類,比如 XZDataTool,XZDataTool.h XZDataTool.m代碼分別 如下: ...
  • 一,效果圖。 二,工程圖。 三,代碼。 RootViewController.h RootViewController.m ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...