當鍵盤彈出來蓋住UITextField,iOS不會主動把UITextField推到鍵盤上方,必須由開發者自行處理,但它並沒有想像中好使,不是僅僅把UI元件放在UIScrollView內,你還得告訴UIScrollView的ContentSize,再來才是處理鍵盤覆蓋UITextField問題。
處理方式有分成兩種,一種是UITableView,它是UIScrollView的子類別,它實作上述惱人的問題,它會自動推算UI元件占用UIScrollView的Content大小以及鍵盤彈出來,自動校正UIScrollView可以捲動範圍,並把正在編輯的UITextField推到鍵盤上方。但偏偏有些設計稿不適用,另一種就要自己動手解決上述問題。
本篇文章要介紹是手動方式,實現步驟如下
- 把元件放到UIScrollView
- 註冊鍵盤彈出和收起的通知
- 鍵盤彈出和收起時,調整UIScrollView的contentInset和scrollIndicatorInset
- 將編輯中並被鍵盤蓋住的UITextField,推到鍵盤上面
1. 把元件放到UIScrollView
a. 最外層先拉一個UIScrollView,把它的Top、Bottom、Leading和Trailing貼合Screen的Safe Area
b. 為了簡化UI元件在UIScrollView的Constraint復雜度,在UIScrollView內,新增一個UIView,命名為ContentView,ContentView的Top、Botton、Leading和Trailing貼合UIScrollView,ContentView和UIScrollView的Width一樣,但不指定ContentView的Height,由ContentView的元件決定高度。如果直接把元件放在UIScrollView內層,設定元件的Constrain會變得很難處理,以UITextField為例,一般只需指定它的Leading和Top就能定位出它的x和y,但在UIScrollView的UITextField,還要加上Trailing和Botton,UIScrollView才能界定它的Content大小。
c. 在contentView內,各元件的constraints,因為已經指定contentView寬度,所以元件不用同時給leading和trailing,以「Sing up」Label為例:UILabel可以由內文長度決定Width,所以可以不用給固定的Width,將它水平置中,就能推出它的x位置。但是ContentView的高度還沒給,也不是固定的,裡面的元件在constraint時,要同時滿足top和bottom,ContentView才能去推出它的Height。
2. 註冊鍵盤彈出和收起的通知
3. 校正UIScrollView的contentInset和scrollIndicatorInset
從storyboard拉scrollView的IBOutlet到view controller
a. 在鍵盤已經彈起時,從notification的userInfo物件,再透過「UIResponder.keyboardFrameEndUserInfoKey」KEY從userInfo取出值(鍵盤的cgRect),最後從cgRect的size拿到鍵盤的高度。
注意:因為鍵盤的高度在transition到畫面過程會改變,應該用UIKeyboardFrameEndUserInfoKey,而不是 UIKeyboardFrameBeginUserInfoKey
b. 將鍵盤高度,也就是遮蔽UIScrollView的部份,指定給ScrollView的content和scrollIndicator底部邊界,調整可以捲動距離,讓遮蔽的內容可以重見天日。
a. 當鍵盤收合時,將scrollView的content和scrollIndicator底部邊界距離歸零。
4. 將編輯中並被鍵盤蓋住的UITextField,推到鍵盤上面
在Interface Build的document outline視窗,選擇「first name」textField,按住左鍵拖曳到View Controller上方並放開,在彈出的選單,按一下delegate,其它textField重覆相同的操作
將正要編輯的textField指定給activeField變數,在結束編輯時,將textField設為nil
a. 如果activeField被鍵盤遮蔽,把它推到鍵盤的上面