幾行代碼搞定UITextField彈起鍵盤遮擋視圖問(wèn)題

先看效果圖


先看效果圖

問(wèn)題描述

在開發(fā)中經(jīng)常會(huì)遇到點(diǎn)擊輸入框激活鍵盤的時(shí)候口予,彈出的鍵盤導(dǎo)致輸入框被遮擋的現(xiàn)象兽泣。常用的解決方案有兩種:
1.鍵盤彈出的時(shí)候奶镶,將整個(gè)視圖上移褐耳。
2.鍵盤彈出的時(shí)候诈闺,懸浮輸入框到適當(dāng)位置。

第一種方案比較簡(jiǎn)單铃芦,常用的實(shí)現(xiàn)方式有三種:

  • 給UITextField注冊(cè)監(jiān)聽事件:UIControlEventEditingDidBeginUIControlEventEditingDidEnd
  • 協(xié)議+代理:通過(guò)UITextField的代理方法來(lái)實(shí)現(xiàn)
  • 用通知來(lái)實(shí)現(xiàn)

幾種方式分析

  • 方法1:如果給UITextField注冊(cè)監(jiān)聽事件雅镊,監(jiān)聽正在編輯和編輯完畢,需要自己寫一個(gè)正在編輯和編輯完畢時(shí)候視圖位置改變的方法刃滓,如果有多個(gè)UITextField仁烹,那么每個(gè)都要添加監(jiān)聽事件,很麻煩咧虎。

    UITextField * usernameTextField = [[UITextField alloc]initWithFrame:CGRectMake(30, 30, 100, 30)];
//    UITextField * passwordTextField = [[UITextField alloc]initWithFrame:CGRectMake(30, 160, 100, 30)];
    
    // 添加監(jiān)聽事件
    // 開始輸入
    [usernameTextField addTarget:self action:@selector(textFieldEditBegin) forControlEvents:UIControlEventEditingDidBegin];
    // 輸入結(jié)束
    [usernameTextField addTarget:self action:@selector(textFieldEditEnd) forControlEvents:UIControlEventEditingDidEnd];
    
    [self.view addSubview:usernameTextField];
  • 方法二:通過(guò)UITextField的代理方法進(jìn)行設(shè)置卓缰,代理方法有:
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField; // 文本框是否可以編輯

- (void)textFieldDidBeginEditing:(UITextField *)textField;   // 開始編輯時(shí)調(diào)用

- (BOOL)textFieldShouldEndEditing:(UITextField *)textField;   // 文本是否結(jié)束編輯

- (void)textFieldDidEndEditing:(UITextField *)textField;     // 結(jié)束編輯時(shí)調(diào)用

- (BOOL)textFieldShouldClear:(UITextField *)textField;        // 是否可以清楚文本框的內(nèi)容

- (BOOL)textFieldShouldReturn:(UITextField *)textField;      // 是否可以return
  • 在代理方法textFieldDidBeginEditingtextFieldDidEndEditing里面實(shí)現(xiàn)視圖的偏移

  • 方法3:用UITextField的通知UIKeyboardWillChangeFrameNotification來(lái)實(shí)現(xiàn),只需要在監(jiān)聽通知砰诵,設(shè)置視圖偏移的動(dòng)畫

所以采用通知的形式來(lái)實(shí)現(xiàn)

完整代碼(重要)

#import "ViewController.h"
@interface ViewController ()
@property (weak, nonatomic) IBOutlet UITextField *usernameTextField;
@property (weak, nonatomic) IBOutlet UITextField *passwordTextField;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // 監(jiān)聽通知
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillChangeFrame:) name:UIKeyboardWillChangeFrameNotification object:nil]; 
}

#pragma mark 鍵盤處理
- (void)keyboardWillChangeFrame:(NSNotification *)note{
    // 取出鍵盤最終的frame
    CGRect rect = [note.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
    // 取出鍵盤彈出需要花費(fèi)的時(shí)間
    double duration = [note.userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue];
    // 修改transform
    [UIView animateWithDuration:duration animations:^{
        CGFloat ty = [UIScreen mainScreen].bounds.size.height - rect.origin.y;
        self.view.transform = CGAffineTransformMakeTranslation(0, - ty);
    }];
}
/**
 * 點(diǎn)擊屏幕的時(shí)候
 */
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
    [self.view endEditing:YES];
    
}
-(void)dealloc{
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

補(bǔ)充 - 關(guān)于通知

通知中心(NSNotificationCenter)

  • 每一個(gè)應(yīng)用程序都有一個(gè)通知中心(NSNotificationCenter)實(shí)例征唬,專門負(fù)責(zé)協(xié)助不同對(duì)象之間的消息通信。
  • 任何一個(gè)對(duì)象都可以向通知中心發(fā)布通知(NSNotification),描述自己在在做什么胧砰。
  • 其他感興趣的對(duì)象(Observer)可以申請(qǐng)?jiān)谀硞€(gè)特定通知發(fā)布時(shí)(或在某個(gè)特定的對(duì)象發(fā)布通知的時(shí)候)收到這個(gè)通知鳍鸵。
    NSNotificationCenter

通知(NSNotificationCenter)

  • 通知包含的屬性:
    • 通知名稱;
    • 通知發(fā)布者;
    • /額外信息(通知發(fā)布者傳遞給通知接收著的信息內(nèi)容).
    - (NSString *)name;  // 通知名稱
    - (id)object;   // 通知發(fā)布者
    - (NSDictionary *)userInfo; //額外信息(通知發(fā)布者傳遞給通知接收著的信息內(nèi)容)
  • 初始化通知對(duì)象的方法:
+ (instancetype)notificationWithName:(NSNotificationName)aName object:(nullable id)anObject;
+ (instancetype)notificationWithName:(NSNotificationName)aName object:(nullable id)anObject userInfo:(nullable NSDictionary *)aUserInfo;

- (instancetype)init

發(fā)布通知

- (void)postNotification:(NSNotification *)notification;

發(fā)布一個(gè)notification通知苇瓣,可在notification對(duì)象中設(shè)置通知的名稱尉间、通知發(fā)布者、額外信息等

- (void)postNotificationName:(NSNotificationName)aName object:(nullable id)anObject;

發(fā)布一個(gè)名稱為aName的通知击罪,anObject為這個(gè)通知的發(fā)布者

- (void)postNotificationName:(NSNotificationName)aName object:(nullable id)anObject userInfo:(nullable NSDictionary *)aUserInfo;

發(fā)布一個(gè)名稱為aName的通知哲嘲,anObject為這個(gè)通知的發(fā)布者,aUserInfo為額外信息

監(jiān)聽通知

  • 通知中心提供了方法來(lái)注冊(cè)一個(gè)監(jiān)聽通知的監(jiān)聽器(Observer)
- (void)addObserver:(id)observer selector:(SEL)aSelector name:(nullable NSNotificationName)aName object:(nullable id)anObject;

observer:監(jiān)聽器
aSelector:接收通知后媳禁,回調(diào)監(jiān)聽器的這個(gè)放啊眠副,并且把通知對(duì)象當(dāng)參數(shù)傳入
aName:通知名稱。如果為nil竣稽,那么無(wú)論通知名稱是什么囱怕,監(jiān)聽器都能收到這個(gè)通知
anObject:通知發(fā)布者。如果anObjectaName都為nil毫别,監(jiān)聽器都能收到所有通知

- (id <NSObject>)addObserverForName:(nullable NSNotificationName)name object:(nullable id)obj queue:(nullable NSOperationQueue *)queue usingBlock:(void (^)(NSNotification *note))block ;

name:通知名稱
obj:通知發(fā)布者
block:收到對(duì)應(yīng)的通知時(shí)娃弓,會(huì)回調(diào)這個(gè)block
queue:決定了block在哪個(gè)操作隊(duì)列中執(zhí)行,如果為nil岛宦,默認(rèn)在當(dāng)前操作隊(duì)列中同步執(zhí)行台丛。

取消注冊(cè)通知監(jiān)聽器

通知中心不會(huì)保留(retain)監(jiān)聽器對(duì)象,在通知中心注冊(cè)過(guò)的對(duì)象砾肺,必須在該對(duì)象釋放前取消注冊(cè)挽霉。否則防嗡,當(dāng)相應(yīng)的通知再次出現(xiàn)時(shí),通知中心仍然會(huì)想該監(jiān)聽器發(fā)送消息侠坎。因?yàn)橄鄳?yīng)的監(jiān)聽器對(duì)象已經(jīng)釋放了蚁趁,所以可能會(huì)導(dǎo)致應(yīng)用崩潰。

  • 通知中心提供了相應(yīng)的方法來(lái)取消注冊(cè)注冊(cè)監(jiān)聽器
- (void)removeObserver:(id)observer;
- (void)removeObserver:(id)observer name:(nullable NSNotificationName)aName object:(nullable id)anObject;

鍵盤通知

  • UIKeyboardWillShowNotification:鍵盤即將顯示
  • UIKeyboardDidShowNotification:鍵盤已經(jīng)顯示完畢
  • UIKeyboardWillHideNotification:鍵盤即將隱藏
  • UIKeyboardDidHideNotification:鍵盤已經(jīng)隱藏完畢
  • UIKeyboardWillChangeFrameNotification:鍵盤的位置尺寸即將發(fā)生改變
  • UIKeyboardDidChangeFrameNotification:鍵盤的位置尺寸已經(jīng)發(fā)生改變
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末实胸,一起剝皮案震驚了整個(gè)濱河市荣德,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌童芹,老刑警劉巖涮瞻,帶你破解...
    沈念sama閱讀 211,817評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異假褪,居然都是意外死亡署咽,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,329評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門生音,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)宁否,“玉大人,你說(shuō)我怎么就攤上這事缀遍∧浇常” “怎么了?”我有些...
    開封第一講書人閱讀 157,354評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵域醇,是天一觀的道長(zhǎng)台谊。 經(jīng)常有香客問(wèn)我,道長(zhǎng)譬挚,這世上最難降的妖魔是什么锅铅? 我笑而不...
    開封第一講書人閱讀 56,498評(píng)論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮减宣,結(jié)果婚禮上盐须,老公的妹妹穿的比我還像新娘。我一直安慰自己漆腌,他們只是感情好贼邓,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,600評(píng)論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著闷尿,像睡著了一般塑径。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上悠砚,一...
    開封第一講書人閱讀 49,829評(píng)論 1 290
  • 那天晓勇,我揣著相機(jī)與錄音,去河邊找鬼。 笑死绑咱,一個(gè)胖子當(dāng)著我的面吹牛绰筛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播描融,決...
    沈念sama閱讀 38,979評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼铝噩,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了窿克?” 一聲冷哼從身側(cè)響起骏庸,我...
    開封第一講書人閱讀 37,722評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎年叮,沒想到半個(gè)月后具被,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,189評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡只损,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,519評(píng)論 2 327
  • 正文 我和宋清朗相戀三年一姿,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片跃惫。...
    茶點(diǎn)故事閱讀 38,654評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡叮叹,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出爆存,到底是詐尸還是另有隱情蛉顽,我是刑警寧澤,帶...
    沈念sama閱讀 34,329評(píng)論 4 330
  • 正文 年R本政府宣布先较,位于F島的核電站携冤,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏拇泣。R本人自食惡果不足惜噪叙,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,940評(píng)論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望霉翔。 院中可真熱鬧,春花似錦苞笨、人聲如沸债朵。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,762評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)序芦。三九已至,卻和暖如春粤咪,著一層夾襖步出監(jiān)牢的瞬間谚中,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,993評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留宪塔,地道東北人磁奖。 一個(gè)月前我還...
    沈念sama閱讀 46,382評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像某筐,于是被迫代替她去往敵國(guó)和親比搭。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,543評(píng)論 2 349

推薦閱讀更多精彩內(nèi)容