彈出帶輸入框鍵盤,鍵盤監(jiān)聽,輸入框自適應(yīng)高度

先來(lái)看一下效果圖:
鍵盤彈出演示.gif

效果就如展示的一樣,彈出樣式也很簡(jiǎn)單,但是做這個(gè)我花費(fèi)了足足的一天時(shí)間,可能我對(duì) textview 的代理和鍵盤的通知之類的方法不是很了解,走了不少?gòu)澛啡鳌O旅婢徒o大家分享一下我做這個(gè)界面的兩個(gè)思路:

思路一:

將要彈出的視圖做為一個(gè) textFiled 的inputAccessoryView這樣做的好處是不用處理彈出視圖的動(dòng)畫與鍵盤動(dòng)畫同步,也不用監(jiān)聽鍵盤的彈出收回事件蒜鸡。

我在控制器里聲明一個(gè) textFiled

@property (nonatomic, strong) UITextField *textFile;

在初始化的時(shí)候只alloc而不給Frame

self.textFile = [UITextField new];
//加載到 view 中讓 view 持有避免回收
[self.view addSubview:self.textFile];

因?yàn)橄胫鲆粋€(gè)類似微信回復(fù)評(píng)論的那種杆麸,可以輸入多行有高度限制祝蝠,就在自定義 view 里面用到了 textview 的代理扭弧,第一步想到的代理就是用ViewDidChange方法

- (void)textViewDidChange:(UITextView *)textView只锭;

通過(guò)這個(gè)代理來(lái)計(jì)算輸入文字的寬度谢澈,計(jì)算文字寬度是用的系統(tǒng)的字體Attribute屬性

CGSize  textSize = [textView.text sizeWithAttributes:@{NSFontAttributeName:[UIFont systemFontOfSize:FontSize]}];

給 textview 一個(gè)固定寬度(或者在初始化視圖時(shí)獲取 textview 的寬度)芦劣,通過(guò)兩者比較來(lái)判斷輸入的文字是否換行粗俱,如果換行就把 textview 的高度和視圖本身的高度改變,改變的大小就是文字換行的大小虚吟。

在控制器里寸认,初始化自定義視圖:

self.inputAccessoryView = [[MReplyCommentView alloc] initWithFrame: CGRectMake(0, 0, windowRect.size.width, 50)];

self.textField.inputAccessoryView = self.inputAccessoryView;

這樣我在點(diǎn)評(píng)論按鈕的時(shí)候?qū)?code>textFiled變成鍵盤第一響應(yīng)就行了,鍵盤帶著輸入框就彈出來(lái)了串慰,很流暢偏塞。等等,不對(duì)啊邦鲫,自定義視圖里的 textview 并沒(méi)有進(jìn)入編輯狀態(tài)灸叼,也就是沒(méi)有光標(biāo)閃爍。然后我在自定義視圖init方法里加了鍵盤的通知UIKeyboardWillShowNotification

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow) name:UIKeyboardWillShowNotification object:nil];

- (void)keyboardWillShow {
    if (![self.textView isFirstResponder]) {
        [self.textView becomeFirstResponder];
    }
}

通過(guò) if 判斷來(lái)判斷 textv 是否為鍵盤第一響應(yīng)者庆捺。

輸入文字換行遇到的問(wèn)題

因?yàn)樽远x視圖的高度是寫死的為50古今,textview 的高度也是寫死的是30,(16號(hào)字體時(shí) textview 高度為36)在換行的時(shí)候光標(biāo)總是下移滔以,刪除字體換行的時(shí)候光標(biāo)會(huì)上移捉腥,每當(dāng)輸入當(dāng)前行最后一個(gè)字換到下一行時(shí)光標(biāo)就跑的很離譜。字體寬度我是通過(guò)計(jì)算字體的寬度來(lái)計(jì)算的你画,高度我是這樣計(jì)算的:

// TextView 大小
CGRect bounds = self.textView.bounds;
CGSize maxSize = CGSizeMake(bounds.size.width, CGFLOAT_MAX);
//用這個(gè)方法將得到的尺寸轉(zhuǎn)化為 textview 最適合的尺寸
CGSize newSize = [self.textView sizeThatFits:maxSize];
self.textView.frame = CGRectMake(10, 10, bounds.size.width, newSize.height);

但是每次一到換行的時(shí)候光標(biāo)就移動(dòng)的很離譜抵碟,而且 textview 有晃動(dòng),我以為是這個(gè)sizeThatFits方法轉(zhuǎn)化的不是很準(zhǔn)確坏匪,我就打斷點(diǎn)一點(diǎn)一點(diǎn)看數(shù)據(jù)拟逮,發(fā)現(xiàn)也是正確的,這讓我感到很困惑适滓,我在網(wǎng)上查了下相關(guān)資料敦迄,都推薦讓用kvo 去監(jiān)聽 textview 的contentSize屬性,我也借來(lái)用了一下:

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{
    UITextView * view =(UITextView *)object;
    if ([keyPath isEqualToString:@"contentSize"]) {
        
        CGFloat height = view.contentSize.height;
        if (height > 112) {
            height = 112;
        }
        CGRect textViewFrame = self.textView.frame;
        textViewFrame.size.height = height;
        self.textView.frame = textViewFrame;
        [self updateSelfOfTextViewSize];
    }
}

發(fā)現(xiàn)比原來(lái)的要好很多,而且這個(gè)監(jiān)聽方法比 textview 的代理要好用的多颅崩,代理是沒(méi)次輸入字的時(shí)候都會(huì)去計(jì)算寬度几于,而這個(gè)監(jiān)聽只有 textview 換行的時(shí)候才會(huì)調(diào)用,而且換行高度也是字體高度⊙睾螅現(xiàn)在 textview 的光標(biāo)沒(méi)有跑那么離譜了沿彭,但是還是有 frame 設(shè)置的問(wèn)題,我百思不得其解尖滚,我隨意輸入幾行字喉刘,用 xcode 打開app 的圖層,發(fā)現(xiàn)光標(biāo)的高度在16號(hào)字體下竟然是36而不是30漆弄,導(dǎo)致每次換行都有誤差睦裳,設(shè)置好高度換行問(wèn)題都迎刃而解了。

點(diǎn)擊頁(yè)面空白處不能回收鍵盤問(wèn)題

我在控制器中設(shè)置取消編輯事件發(fā)現(xiàn)鍵盤不能回收撼唾,

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    [self.view endEditing:YES];
}

而且在點(diǎn)擊控制器頁(yè)面的時(shí)候發(fā)現(xiàn)方法都不執(zhí)行廉邑,可能是我用一個(gè)三方IQKeyboardManager的原因,也可能是圖層的原因倒谷,我也沒(méi)有追究到底是哪里的原因蛛蒙,我放棄了這種做法,因?yàn)槔速M(fèi)的時(shí)間已經(jīng)很多了渤愁。

思路二:

自定義視圖重寫-(instancetype)init方法牵祟,將textview的初始化放在這里,分別加入鍵盤出現(xiàn)監(jiān)聽:UIKeyboardWillShowNotification抖格,和消失監(jiān)聽UIKeyboardWillHideNotification诺苹,通過(guò)對(duì)鍵盤的監(jiān)聽來(lái)設(shè)置自定視圖的Frame和 textview 的動(dòng)畫,再加上上次踩的坑都一起設(shè)置完畢雹拄,run 了一下達(dá)到了預(yù)想的結(jié)果收奔,可能是因?yàn)槿綆?kù)IQKeyboard的原因,每次彈出視圖办桨,控制器視圖會(huì)滾動(dòng)筹淫,所以在viewWillAppearviewWillDisappear中加入了[IQKeyboardManager sharedManager].enable = NO;將 IQ 的作用取消。具體代碼可以看一下 demo 點(diǎn)我下載呢撞。

總結(jié)

這個(gè)功能也不是很復(fù)雜损姜,花費(fèi)了一天時(shí)間才搞定。主要用的知識(shí)點(diǎn):對(duì) textview 做contentSizekvo 監(jiān)聽殊霞,通過(guò)contentSize.height來(lái)設(shè)定高度要比自己計(jì)算準(zhǔn)確的多摧阅,一定要根據(jù)字號(hào)高度把 textview 的初始化高度計(jì)算準(zhǔn)確,要不然光標(biāo)會(huì)跳躍绷蹲;通過(guò)監(jiān)聽鍵盤來(lái)做動(dòng)畫改變 frame棒卷。

最后再說(shuō)一點(diǎn)

此 demo 很簡(jiǎn)單顾孽,只適應(yīng)小工程,有興趣的同學(xué)可以試一下比规,如果你的工程里比如有界面套界面若厚,列表套列表,層級(jí)關(guān)系比較多蜒什,想彈鍵盤視圖可以將自定義 view 設(shè)置成單例测秸,這樣就好控制了。設(shè)置單例的時(shí)候要把-(void)close方法中的[[NSNotificationCenter defaultCenter] removeObserver:self];代碼注釋掉.

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末灾常,一起剝皮案震驚了整個(gè)濱河市霎冯,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌钞瀑,老刑警劉巖沈撞,帶你破解...
    沈念sama閱讀 218,284評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異雕什,居然都是意外死亡缠俺,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,115評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門监徘,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)晋修,“玉大人,你說(shuō)我怎么就攤上這事凰盔。” “怎么了倦春?”我有些...
    開封第一講書人閱讀 164,614評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵户敬,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我睁本,道長(zhǎng)尿庐,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,671評(píng)論 1 293
  • 正文 為了忘掉前任呢堰,我火速辦了婚禮抄瑟,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘枉疼。我一直安慰自己皮假,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,699評(píng)論 6 392
  • 文/花漫 我一把揭開白布骂维。 她就那樣靜靜地躺著惹资,像睡著了一般。 火紅的嫁衣襯著肌膚如雪航闺。 梳的紋絲不亂的頭發(fā)上褪测,一...
    開封第一講書人閱讀 51,562評(píng)論 1 305
  • 那天猴誊,我揣著相機(jī)與錄音,去河邊找鬼侮措。 笑死懈叹,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的分扎。 我是一名探鬼主播项阴,決...
    沈念sama閱讀 40,309評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼笆包!你這毒婦竟也來(lái)了环揽?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,223評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤庵佣,失蹤者是張志新(化名)和其女友劉穎歉胶,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體巴粪,經(jīng)...
    沈念sama閱讀 45,668評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡通今,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,859評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了肛根。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片辫塌。...
    茶點(diǎn)故事閱讀 39,981評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖派哲,靈堂內(nèi)的尸體忽然破棺而出臼氨,到底是詐尸還是另有隱情,我是刑警寧澤芭届,帶...
    沈念sama閱讀 35,705評(píng)論 5 347
  • 正文 年R本政府宣布储矩,位于F島的核電站,受9級(jí)特大地震影響褂乍,放射性物質(zhì)發(fā)生泄漏持隧。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,310評(píng)論 3 330
  • 文/蒙蒙 一逃片、第九天 我趴在偏房一處隱蔽的房頂上張望屡拨。 院中可真熱鬧,春花似錦褥实、人聲如沸呀狼。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,904評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)赠潦。三九已至,卻和暖如春草冈,著一層夾襖步出監(jiān)牢的瞬間她奥,已是汗流浹背瓮增。 一陣腳步聲響...
    開封第一講書人閱讀 33,023評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留哩俭,地道東北人绷跑。 一個(gè)月前我還...
    沈念sama閱讀 48,146評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像凡资,于是被迫代替她去往敵國(guó)和親砸捏。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,933評(píng)論 2 355

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

  • 內(nèi)容抽屜菜單ListViewWebViewSwitchButton按鈕點(diǎn)贊按鈕進(jìn)度條TabLayout圖標(biāo)下拉刷新...
    皇小弟閱讀 46,761評(píng)論 22 665
  • ¥開啟¥ 【iAPP實(shí)現(xiàn)進(jìn)入界面執(zhí)行逐一顯】 〖2017-08-25 15:22:14〗 《//首先開一個(gè)線程隙赁,因...
    小菜c閱讀 6,419評(píng)論 0 17
  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫(kù)垦藏、插件、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 12,103評(píng)論 4 62
  • 《裕語(yǔ)言》速成開發(fā)手冊(cè)3.0 官方用戶交流:iApp開發(fā)交流(1) 239547050iApp開發(fā)交流(2) 10...
    葉染柒丶閱讀 26,776評(píng)論 5 19
  • 在生活中弟灼,我們難免會(huì)遇到一些事情,讓我們覺(jué)得很為難冒黑。拒絕吧田绑,有礙于情面;應(yīng)允吧抡爹,覺(jué)得并不會(huì)心甘情愿掩驱。以前我也會(huì)很糾...
    美心琪子閱讀 609評(píng)論 2 3