この記事はユニファAdvent Calendar 2023の16日目の記事です。iOSアプリ開発者&一部QAご担当向けの内容となります。
密やかなキーボード仕様変更、細やかなキーボード挙動対応。
iPhone発表とソフトウェアキーボード
iPhone発表から2023年12月現在、16年近く経過しました。故スティーブ・ジョブスによるiPhone発表プレゼンテーションでは競合他社が販売する携帯機器を並べて用途によってはキーボードが必要ない場合もあるのに携帯機器の画面下に物理キーボードが占拠しているのはナンセンスと唱え、代わりにAppleは人間が生まれながら持っている指による操作と目的によって画面下からドッキングするソフトウェアキーボードを表示する方法を提案(※1)、以降スマートフォンの使い勝手を決める秘伝のエッセンスとして利用者に親しまれてきました。
そんなソフトウェアキーボードに関してiOS17から変更が加えられました。注目点は、1. キーボードの外部プロセス化、2.UIKit のキーボードレイアウト属性追加 です。
1. キーボードの外部プロセス化
アプリ上でテキスト入力欄をタップするとキーボードが表示されます。iOS17のキーボードはiOS16以前と変わらない見た目でありますがキーボードはアプリとは別のプログラムとして動作しOSによって表示が合成されるようになりました。2つ以上のアプリごとにテキスト入力欄にフォーカスを当ててソフトウェアキーボードを出した際、見えているキーボードはOSが管理するキーボードとなります。
プレゼンテーション中、Appleはアプリごとに用意されていたキーボードがOSにまとめられる事でメモリ節約できるメリットのほか、1つのハードウェアキーボードを複数のOSで共有するなどの機能を提供可能となります。
https://developer.apple.com/wwdc23/10281?time=92
幾分Appleの都合が強い気がする仕様変更であり、AppleとしてはiOS17以降のソフトウェアキーボード挙動についてアプリへの影響が出てくるケースがあることをセッション内で認めております。
Apple曰くアプリへの影響とはアプリとキーボードの表示タイミングを制御できない場合との事。Appleからは具体的な明示はありませんがiOSアプリ開発者として思いつくのがキーボードが表示されるタイミングを開発者側がハンドリングする場合です。
キーボードが表示されるタイミングについて簡単にまとめますと、iOSアプリ開発でUI周りを開発する際に使用するフレームワークUIKitに含まれるアプリ内イベント通達機能(NSNotification)の中からキーボードに関連するイベントを監視して得た情報をもとに、アプリ側でソフトウェアキーボード表示/非表示に合わせて画面レイアウトを調整することが可能です。
// UIKit より引用 extension UIResponder { public class let keyboardWillShowNotification: NSNotification.Name public class let keyboardDidShowNotification: NSNotification.Name public class let keyboardWillHideNotification: NSNotification.Name public class let keyboardDidHideNotification: NSNotification.Name … }
keyboardWillShowNotificationイベントに含まれる付加情報からキーボードの高さ(keyboardWillShowNotificationイベント)を得た上でアプリ側がUIの高さ調整に利用します。
アプリ内イベント通達機能を説明した上で以下にiOS16以前とiOS17以前のキーボード表示に違いを図に示します。
図でわかる通りiOS17ではアプリ外、OSがソフトウェアキーボードを管理しており利用者はアプリとキーボードが重なった状態でアプリを使用することになります。
keyboardWillShowNotificationイベントを扱う際、iOS16以前はアプリ内でキーボード表示を行っていたためアプリ内の処理スケジュールにキーボード表示が巻き込まれているケースがあったかもしれませんがiOS17からは外部プロセスとして独立して動作するのでアプリとキーボードのアニメーションが連動して見えないケースが出てくる可能性がある仕様変更となります(※2)。
2. UIKit向けキーボードレイアウトガイドのアップデート
iOS15からUIKit フレームワーク(iOSアプリのUI周りのフレームワーク)にはソフトウェアキーボードが表示される際のレイアウトを調整するためのUIKeyboardLayoutGuide が用意されています。Xcode - Storyboard Editorでは Size Inspector(Command + Alt + 6) - Layout guide - Keyboard をチェックするとStoryboard Editor上にレイアウトガイドを表示できるようになります。
iOS17では新しく2つの属性がサポートされています。
2-1. キーボードレイアウトでキーボードオフ/オフでの背面表示をサポート
メッセージアプリなどキーボード下部にテキスト入力欄を差し込む場合があります。メッセージアプリはメッセージを入力したい時はキーボードを表示し、メッセージコンテンツを確認したい時はキーボードが自然に下がる挙動が求められることがあります。
メッセージ入力欄の下に背景を配置したい場合、iOS17のキーボードは背面が透過している都合上メッセージ入力欄の背景は入力欄の範囲に収まってほしいものです。一方キーボードが隠れると入力欄はホームバー(iPhoneの画面下部に表示される細長のバー)と重複しないよう少し上に配置されるべきですが画面背面は画面の下部まで表示を広げてほしいことがあります。
その際に利用できるがiOS17からUIKeyboardLayoutGuideに追加されたusesBottomSafeArea 属性です。usesBottomSafeAreaのデフォルト値はtrueでキーボードの下部はホームバーよりも少し上となります。falseとするとキーボードの下部は画面下まで調整を施してくれます。
view.keyboardLayoutGuide.usesBottomSafeArea = false
Appleのセッション上で説明されているサンプルコードと、画面下入力欄に配置する背景の高さを固定したiOS16以前での見た目を比べてみました。usesBottomSafeAreaを使った場合は画面下部入力欄の背面表示について理想的な(キーボード背面を覆わない、キーボードが閉じた際に画面下魔で表示をカバーする)が実現されています。
2-2. キーボードを閉じる際の埋め合わせ(Padding)領域を拡張
UIKeyboardLayoutGuideにはusesBottomSafeArea のほか、keyboardDismissPaddingが追加されています。iOSはスクロールで自動でキーボードを下げる機能が用意されていますがiO16以前はキーボードを下げる領域を拡張する方法がありませんでした。iOS16からkeyboardDismissPaddingを使ってキーボードを閉じる領域を増やすことができます。利用するケースとして画面下の入力欄やキーボード上部に表示する画面パーツ(Input accessory view)もキーボードを閉じる領域に含めることが可能となります。
keyboardDismissPadding はCGFloat型で指定可能です。
view.keyboardLayoutGuide. keyboardDismissPadding = 49.0
細かな改善点ですがアプリ側で自前でキーボードを閉じる範囲を広げているコードを書いている場合はiOS17以降はkeyboardDismissPadding に置き換えてコード量を減らすこともできそうです。
まとめ
iOS17は見た目が大きく変わるといった新機能は影を潜めているもののキーボードの仕様変更などこれまでiPhoneの魅力を支えていた機能に変更が加えられています。利用者への影響は少ないですがソフトウェアキーボードの仕様変更はiOSアプリ開発者にとって覚えておいても良い内容かもしれません。
※1 物理キーボードの他、スタイラスペンを使ったデバイスについては壇上で冗談じゃないと一蹴していました。後に紙書くような精密なトラッキングが可能なAppleペンシルが登場しましたが一般的なスマートフォン利用者とは異なるユーザー向けの製品でしょう。
※2 iOS17からiPhoneⅩ, iPhone8 などの機種が対応機種から外れたのでApple側で影響があると思われる機種を除外した上でのキーボード仕様変更であったかもしません
最後までお読みいただき感謝であります。
ユニファでは、一緒にはたらく仲間を募集しています!