WWDC Quick Look 💓 By SwiftGGTeam
Your guide to keyboard layout

Your guide to keyboard layout

元の動画を見る

ハイライト

iOS 15 UIKit の新機能UIKeyboardLayoutGuideそしてUITrackingLayoutGuideにより、開発者は自動レイアウト制約を使用して、オンスクリーン キーボード、フローティング キーボード、ショートカット バーに従うことができるため、通知のリスニング、フレーム計算、および手書きのアニメーション コードを削減できます。

主な内容

チャット入力ボックスやコメントボックス、エディターを作るとき、レイアウト上でいつも悩まされるのがキーボードです。

これまでの UIKit コードは通知から始まることがよくありました。監視したいkeyboardWillShowNotificationそしてkeyboardWillHideNotification、からuserInfoキーボードの終了位置を取得し、ビューをどれだけ移動するかを計算します。また、キーボード アニメーションの継続時間を自分で取得し、最後に手動で呼び出す必要があります。layoutIfNeeded()

このソリューションは機能しますが、多くの限界があります。キーボードは収納され、セキュリティエリアの高さが変更される場合があります。 iPad には、フローティング キーボード、分割キーボード、ハードウェア キーボード ショートカット バーもあります。アプリが Split View に入ると、キーボードはウィンドウの一部のみを覆います。追加のフォームごとに、追加の判断セクションがあります。

iOS 15 ではキーボードが自動レイアウトになります。UIView新しいkeyboardLayoutGuide、現在のアプリ ウィンドウ内でキーボードが占めるスペースを表します。入力ボックス、ツールバー、またはコンテンツ ビューをこのガイドに制限すると、キーボードがポップアップしたり、折りたたまれたり、高さが変更されると、システムが自動的にレイアウトを更新します。

このアップデートには次の内容も含まれますUITrackingLayoutGuide。ガイドがエッジに近いかどうかに基づいて、一連の制約を自動的に有効または無効にすることができます。フローティング キーボードが上部付近にある場合、入力ツールバーは下部に戻ることができます。フローティング キーボードが左側近くにある場合、ピクチャ ビューにスペースができることがあります。

キーボードの回避からレイアウトへのキーボードの組み込みへ

キーボードは外部イベントのように動作していました。ポップアップが表示され、アプリがそれを修正します。

iOS 15 の考え方はより単純で、キーボードもレイアウト スペースです。開発者はフレームを読み取って計算するのではなく、ビューとキーボードの関係を宣言します。キーボードがどのようにアニメーション化されるか、制約がどのように更新されるか。

これはiPadではさらに重要です。ユーザーは、フローティング キーボードを移動したり、分割キーボードに切り替えたり、ハードウェア キーボードを接続したりできます。keyboardLayoutGuideデフォルトで一般的なシナリオを処理します。開けるfollowsUndockedKeyboard最後に、レイアウトはフローティング キーボードの位置に従うこともできます。

##詳細

通知を使用してキーボードを処理する古い方法

(01:31) 講演ではまず、iOS 15 以前の典型的な記述方法、つまりカスタム レイアウト ガイドを作成し、キーボード通知を聞き、通知内のフレームとアニメーション情報を使用して制約を更新する方法が示されました。

import UIKit

final class NotificationKeyboardViewController: UIViewController {
    private let textView = UITextView()
    private let keyboardGuide = UILayoutGuide()
    private var keyboardHeight: NSLayoutConstraint!

    override func viewDidLoad() {
        super.viewDidLoad()

        view.addSubview(textView)
        view.addLayoutGuide(keyboardGuide)
        textView.translatesAutoresizingMaskIntoConstraints = false

        NSLayoutConstraint.activate([
            textView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor),
            textView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor),
            textView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
            keyboardGuide.bottomAnchor.constraint(equalTo: view.bottomAnchor),
            keyboardGuide.topAnchor.constraint(equalTo: textView.bottomAnchor)
        ])

        keyboardHeight = keyboardGuide.heightAnchor.constraint(equalToConstant: view.safeAreaInsets.bottom)
        keyboardHeight.isActive = true

        NotificationCenter.default.addObserver(
            self,
            selector: #selector(respondToKeyboard),
            name: UIResponder.keyboardWillShowNotification,
            object: nil
        )
    }

    @objc func respondToKeyboard(notification: Notification) {
        let info = notification.userInfo
        if let endRect = info?[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect {
            var offset = view.bounds.size.height - endRect.origin.y
            if offset == 0.0 {
                offset = view.safeAreaInsets.bottom
            }
            let duration = info?[UIResponder.keyboardAnimationDurationUserInfoKey] as? TimeInterval ?? 2.0
            UIView.animate(withDuration: duration, animations: {
                self.keyboardHeight.constant = offset
                self.view.layoutIfNeeded()
            })
        }
    }
}

キーポイント:

  • keyboardGuide開発者自身が作成したUILayoutGuide、キーボード上の利用可能なスペースを表すために使用されます。 -keyboardGuide.bottomAnchorバインドするview.bottomAnchor、ガイドが画面の下からカウントを開始します。 -keyboardGuide.topAnchorバインドするtextView.bottomAnchor、テキスト ビューの下部がガイドの上部に続くようになります。 -keyboardHeightガイド高さの制約を保存し、後で変更します。constantレイアウトを変更します。 -NotificationCenter.default.addObserver通知を表示するキーボードを登録します。 -respondToKeyboardからuserInfo読むkeyboardFrameEndUserInfoKey
  • offsetビューの高さからキーボードの終了位置を減算します。yキーボードカバレッジの高さを取得するための値。 -offset == 0.0に戻るsafeAreaInsets.bottom、キーボードが画面から離れたときの状況を処理します。 -keyboardAnimationDurationUserInfoKeyキーボードアニメーションの長さを提供します。 -UIView.animate内の制約定数を更新して呼び出しますlayoutIfNeeded()、カスタム ガイドがキーボード アニメーションに従うようにします。

このコードは、古いソリューションのコストを示しています。開発者は、通知、フレーム、安全領域、アニメーションを同時に考慮する必要があります。

UIKeyboardLayoutGuideキーボードをコンストレイント ターゲットに変える

(03:09) iOS 15 新しいUIView.keyboardLayoutGuide。それはですUILayoutGuideには、キーボードが占めるスペースを表すために使用されるビューと同じアンカーがあります。

import UIKit

final class KeyboardLayoutGuideViewController: UIViewController {
    private let textView = UITextView()

    override func viewDidLoad() {
        super.viewDidLoad()

        view.addSubview(textView)
        textView.translatesAutoresizingMaskIntoConstraints = false

        NSLayoutConstraint.activate([
            textView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor),
            textView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor),
            textView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
            view.keyboardLayoutGuide.topAnchor.constraint(
                equalToSystemSpacingBelow: textView.bottomAnchor,
                multiplier: 1.0
            )
        ])
    }
}

キーポイント:

  • view.keyboardLayoutGuideはいUIViewプロパティ、iOS 15 で利用可能。 -topAnchor現在キーボードが占有している領域の上部を示します。 -textView.bottomAnchorキーボード ガイドの上部に限定されているため、キーボードがポップアップしてもテキスト ビューが隠れることはありません。 -equalToSystemSpacingBelowシステム間隔を使用して、テキストビューとキーボード間の標準的な距離を維持します。
  • このコードはキーボード通知を登録せず、キーボード フレームを読み取りません。
  • ガイドはキーボードのポップアップと折りたたみのアニメーションに一致し、キーボードの高さの変更にも追従します。
  • ガイドは安全領域を処理し、基本シナリオでは開発者が下部インセットを計算する必要はありません。

デフォルトでは、フローティング キーボードまたはドッキングされていないキーボードが表示されると、ガイドはウィンドウの幅と同じ幅で画面の下部に表示されます。ガイドの上部にバインドされたビューは、引き続き下部の位置に従うことができます。

フローティングキーボードに従ってください

(05:07) インターフェイスが iPad フローティング キーボードに対して実際に動きたい場合は、それをオンにできます。followsUndockedKeyboard

import UIKit

final class FloatingKeyboardViewController: UIViewController {
    private let editView = UIView()

    override func viewDidLoad() {
        super.viewDidLoad()

        view.addSubview(editView)
        editView.translatesAutoresizingMaskIntoConstraints = false

        view.keyboardLayoutGuide.followsUndockedKeyboard = true

        NSLayoutConstraint.activate([
            editView.centerXAnchor.constraint(equalTo: view.keyboardLayoutGuide.centerXAnchor),
            editView.bottomAnchor.constraint(equalTo: view.keyboardLayoutGuide.topAnchor)
        ])
    }
}

キーポイント:

  • followsUndockedKeyboardデフォルトはfalse
  • に設定trueその後、ガイドはドッキングされていないキーボードとフローティング キーボードの位置に従います。 -centerXAnchorさせてeditViewキーボードの中心を水平に合わせます。 -bottomAnchorさせてeditViewキーボード上部にぴったりフィットします。
  • ユーザーがフローティングキーボードをドラッグすると、editViewガイドに沿って移動していきます。
  • このスピーチは開発者に、この属性をオンにした後は、レイアウトでキーボードの形状と画面の端をさらに考慮する必要があることを思い出させます。

フォローをオンにしたらキーボードの位置が安定しなくなりました。フローティング キーボードは四方から外れているか、上面、左側、または右側に近い場合があります。こんな時こそ協力してねUITrackingLayoutGuideエッジケースに対処します。

垂直エッジに基づいて制約を切り替えます

06:46UIKeyboardLayoutGuideはいUITrackingLayoutGuideサブカテゴリ。複数の制約セットを保存し、ガイドがエッジに近づいたり遠ざかったりしたときに自動的に切り替えることができます。

import UIKit

final class VerticalTrackingViewController: UIViewController {
    private let editView = UIView()

    override func viewDidLoad() {
        super.viewDidLoad()

        view.addSubview(editView)
        editView.translatesAutoresizingMaskIntoConstraints = false
        view.keyboardLayoutGuide.followsUndockedKeyboard = true

        let awayFromTopConstraints = [
            view.keyboardLayoutGuide.topAnchor.constraint(equalTo: editView.bottomAnchor),
        ]
        view.keyboardLayoutGuide.setConstraints(awayFromTopConstraints, activeWhenAwayFrom: .top)

        let nearTopConstraints = [
            view.safeAreaLayoutGuide.bottomAnchor.constraint(equalTo: editView.bottomAnchor),
        ]
        view.keyboardLayoutGuide.setConstraints(nearTopConstraints, activeWhenNearEdge: .top)
    }
}

キーポイント:

  • awayFromTopConstraintsキーボードガイドが上から離れたときに有効になります。
  • 最初の制約editView.bottomAnchorに接続しますkeyboardLayoutGuide.topAnchor編集ツールバーをキーボードの上に維持します。 -setConstraints(_:activeWhenAwayFrom:)この一連の制約は、管理用の追跡ガイドに任せてください。 -nearTopConstraintsキーボードガイドが最上部付近にあるときに有効になります。 -view.safeAreaLayoutGuide.bottomAnchor.constraint(equalTo: editView.bottomAnchor)バンドルeditView安全エリアの一番下まで戻ります。 -setConstraints(_:activeWhenNearEdge:)上部付近で指定されている場合、この一連の制約を有効にします。
  • フローティング キーボードを画面の上部付近にドラッグすると、上部の制約が無効になり、下部の制約が有効になり、ツールバーが画面からはみ出ることはありません。

このモードは、入力添付バー、書式設定ツールバー、およびコメント ボックスに適しています。ユーザーがフローティング キーボードを上にドラッグすると、ツールバーが画面の端に押し出されるのを避けるために下に戻ることができます。

水平エッジに基づいて制約を切り替えます

(07:44) 同じメカニズムで水平方向の動きも処理できます。音声の例では、キーボードが左右の端から遠く離れている場合、編集ビューはキーボードに従い、中央に表示されます。キーボードが一方の側に近づくと、画像ビューが反対側に移動します。

import UIKit

final class HorizontalTrackingViewController: UIViewController {
    private let editView = UIView()
    private let imageView = UIImageView()

    override func viewDidLoad() {
        super.viewDidLoad()

        view.addSubview(editView)
        view.addSubview(imageView)
        editView.translatesAutoresizingMaskIntoConstraints = false
        imageView.translatesAutoresizingMaskIntoConstraints = false
        view.keyboardLayoutGuide.followsUndockedKeyboard = true

        let awayFromSides = [
            view.keyboardLayoutGuide.centerXAnchor.constraint(equalTo: editView.centerXAnchor),
            imageView.centerXAnchor.constraint(equalTo: view.centerXAnchor),
        ]
        view.keyboardLayoutGuide.setConstraints(awayFromSides, activeWhenAwayFrom: [.leading, .trailing])

        let nearTrailingConstraints = [
            view.keyboardLayoutGuide.trailingAnchor.constraint(equalTo: editView.trailingAnchor),
            imageView.leadingAnchor.constraint(
                equalToSystemSpacingAfter: view.safeAreaLayoutGuide.leadingAnchor,
                multiplier: 1.0
            )
        ]
        view.keyboardLayoutGuide.setConstraints(nearTrailingConstraints, activeWhenNearEdge: .trailing)

        let nearLeadingConstraints = [
            editView.leadingAnchor.constraint(equalTo: view.keyboardLayoutGuide.leadingAnchor),
            view.safeAreaLayoutGuide.trailingAnchor.constraint(
                equalToSystemSpacingAfter: imageView.trailingAnchor,
                multiplier: 1.0
            )
        ]
        view.keyboardLayoutGuide.setConstraints(nearLeadingConstraints, activeWhenNearEdge: .leading)
    }
}

キーポイント:

  • awayFromSides鍵盤を左右から離したときに有効になります。 -keyboardLayoutGuide.centerXAnchor位置合わせeditView.centerXAnchor編集ビューがキーボードの中心に追従するようにします。 -imageView.centerXAnchor位置合わせview.centerXAnchor、ウィンドウの中央に画像を保持します。 -activeWhenAwayFrom: [.leading, .trailing]ガイドに左側と右側に同時に近づかないように依頼してください。 -nearTrailingConstraints鍵盤が右に寄ったときに有効になります。 -keyboardLayoutGuide.trailingAnchor.constraint(equalTo: editView.trailingAnchor)編集ビューをキーボードの右側にスナップさせます。 -imageView.leadingAnchor安全領域の左側に固定し、画像をキーボードの反対方向に移動します。 -nearLeadingConstraintsキーボードを左側に近づけて対称的なシーンを処理します。
  • トラッキング ガイドは、キーボードがエッジ領域に出入りするときに、これらの制約を自動的に有効または無効にします。

この機能は、iPad エディター、アートボード、チャット インターフェイスに適しています。フローティング キーボードが移動すると、コンテンツは積極的に道を譲り、入力コントロールはキーボードの近くに留まります。

設計時に考慮すべきキーボードの形状

(08:55) スピーチではnearとawayFromの判定ルールがわかりやすく説明されています。

view.keyboardLayoutGuide.followsUndockedKeyboard = true

let dockedKeyboardBehavior = [
    view.keyboardLayoutGuide.topAnchor.constraint(equalTo: editView.bottomAnchor)
]
view.keyboardLayoutGuide.setConstraints(dockedKeyboardBehavior, activeWhenAwayFrom: [.top, .leading, .trailing])

let topEdgeBehavior = [
    view.safeAreaLayoutGuide.bottomAnchor.constraint(equalTo: editView.bottomAnchor)
]
view.keyboardLayoutGuide.setConstraints(topEdgeBehavior, activeWhenNearEdge: .top)

キーポイント:

  • ドッキングされたキーボードは下部に近く、上部、左右から離れると表示されます。
  • ドッキング解除および分割キーボードが四方から離れているか、上部に近い場合があります。
  • フローティング キーボードは、任意の端に近づけることも、同時に 2 つの隣接する端に近づけることもできます。
  • これらのルールは以下でのみ利用可能ですfollowsUndockedKeyboardのためにtrue時間はレイアウトに影響します。 -activeWhenAwayFrom: [.top, .leading, .trailing]「キーボードが上端や左右端に寄っていない」という一般的な状態を表現するのに適しています。 -activeWhenNearEdge: .topキーボードを上部にドラッグした後のフォールバック レイアウトを処理するのに適しています。

このスピーチはまた、安易に依存しないことを思い出させました。keyboardLayoutGuide.widthAnchor。ハードウェア キーボードのアダプティブ ショートカット バーの幅は、iOS 15 の言語とボタンの数によって変わります。折りたたんだときに、左側または右側に寄ることもあります。

(12:02) マルチタスクもガイドに影響します。キーボードがアプリのスペースから離れる場合があり、その場合、システムはキーボードを閉じたものとして扱います。アプリが分割画面またはスライド オーバーにある場合、ガイドのサイズは現在のウィンドウ内のキーボードの部分のみをカバーします。

view.keyboardLayoutGuide.followsUndockedKeyboard = true

let visibleKeyboardConstraints = [
    editView.bottomAnchor.constraint(equalTo: view.keyboardLayoutGuide.topAnchor)
]
view.keyboardLayoutGuide.setConstraints(visibleKeyboardConstraints, activeWhenAwayFrom: .top)

let safeFallbackConstraints = [
    editView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor)
]
view.keyboardLayoutGuide.setConstraints(safeFallbackConstraints, activeWhenNearEdge: .top)

キーポイント:

  • 分割ビューとスライド オーバーでは、キーボードは現在のアプリの一部しかカバーしない場合があります。
  • ガイドのサイズは、現在のウィンドウのキーボードで覆われている部分に基づいて計算されます。
  • キーボードがアプリ空間から離れると、ガイドはキーボードによって処理されます。 -visibleKeyboardConstraints通常の状態では、コントロールをキーボードの近くに置いてください。 -safeFallbackConstraintsトップエッジシーンに安全なフォールバック位置を提供します。
  • このタイプのフォールバック制約により、フローティング キーボードでコントロールが画面からはみ出すのを防ぐことができます。

重要なポイント

1. キーボードの後に​​チャット入力フィールドが続きます

  • やるべきこと: チャット入力フィールドを作成します。キーボードがポップアップすると、入力フィールドはキーボードの上で自動的に停止します。
  • 実行する価値がある理由:keyboardLayoutGuide.topAnchorキーボードのアニメーションと高さの変更は一致し、入力フィールドは手書き通知の監視を必要としません。
  • 開始方法: 入力フィールドを配置しますbottomAnchorに制約されるview.keyboardLayoutGuide.topAnchor、メッセージ リストの下部を入力フィールドの上部に制限します。

2. iPad フローティング キーボードの特殊編集ツールバー

  • 手順: メモ アプリのフローティング キーボードで太字、リスト、イラストのボタンを移動させます。
  • 実行する価値がある理由:followsUndockedKeyboard = trueツールバーをドッキング解除されたキーボードの位置に追従させることができます。
  • 開始方法: 有効にするview.keyboardLayoutGuide.followsUndockedKeyboard、ツールバーの中央と下部を次のように制限します。keyboardLayoutGuide.centerXAnchorそしてtopAnchor

3. 上端が自動的に引っ込むフォーム

  • 内容: フローティング キーボードが画面の上部にドラッグされたときに、フォーム アクション バーを安全領域の下部に移動します。
  • 実行する価値がある理由:UITrackingLayoutGuideガイドが上部に近づくと、コンストレイントを自動的に切り替えることができます。
  • 開始方法: を使用しますsetConstraints(_:activeWhenAwayFrom: .top)「キーボードの貼り付け」制約を管理するには、次を使用します。setConstraints(_:activeWhenNearEdge: .top)「最後に戻る」制約の管理。

4. Sketchpad アプリのキーボード回避レイアウト

  • 内容: ユーザーがフローティング キーボードを移動すると、キャンバス プレビューまたはレイヤー パネルがキーボードの反対側に自動的に移動します。
  • 実行する価値がある理由: 追跡ガイドは区別できます.leadingそして.trailing、水平エッジ状態により、コンテンツが道を譲ってしまう可能性があります。
  • 開始方法: キーボードの左右の端から離れたところ、左側に近いところ、右側に近いところに制約配列を用意して渡します。keyboardLayoutGuide.setConstraints

5. ハードウェアキーボードショートカットバーをサポートするエディタ

  • 何をすべきか: ハードウェア キーボードが接続されているときに、エディターの下部コントロールを適応型ショートカット バーの実際の幅に適応させます。
  • 実行する価値がある理由: iOS 15 のショートカット バーの幅は全画面に固定されなくなりました。keyboardLayoutGuide実際のリーディングエッジとトレーリングエッジを露出させることができます。
  • 開始方法: 有効にするfollowsUndockedKeyboard最後に、固定幅に依存することを避け、ガイドのエッジ アンカーとnear/awayFrom状態を使用してツールバーの位置を決定します。

関連セッション

コメント

GitHub Issues · utterances