使用 WindowInsetsCompat
,
您的應用程式可以查詢及控制螢幕小鍵盤 (又稱為
IME) 類似
與系統資訊列互動的方式。您的應用程式也能使用
WindowInsetsAnimationCompat
敬上
開啟或關閉螢幕鍵盤時,可創造流暢的轉場效果。
必要條件
設定螢幕鍵盤的控制項和動畫前,請先完成 在您的應用程式中顯示無邊框。這樣一來, 該元件會處理系統視窗插邊,例如 系統資訊列和螢幕小鍵盤。
檢查鍵盤軟體顯示設定
使用 WindowInsets
檢查軟體
。
Kotlin
val insets = ViewCompat.getRootWindowInsets(view) ?: return val imeVisible = insets.isVisible(WindowInsetsCompat.Type.ime()) val imeHeight = insets.getInsets(WindowInsetsCompat.Type.ime()).bottom
Java
WindowInsetsCompat insets = ViewCompat.getRootWindowInsets(view); boolean imeVisible = insets.isVisible(WindowInsetsCompat.Type.ime()); int imeHeight = insets.getInsets(WindowInsetsCompat.Type.ime()).bottom;
另外,您也可以使用
ViewCompat.setOnApplyWindowInsetsListener
敬上
觀察軟體鍵盤顯示設定的變化。
Kotlin
ViewCompat.setOnApplyWindowInsetsListener(view) { _, insets -> val imeVisible = insets.isVisible(WindowInsetsCompat.Type.ime()) val imeHeight = insets.getInsets(WindowInsetsCompat.Type.ime()).bottom insets }
Java
ViewCompat.setOnApplyWindowInsetsListener(view, (v, insets) -> { boolean imeVisible = insets.isVisible(WindowInsetsCompat.Type.ime()); int imeHeight = insets.getInsets(WindowInsetsCompat.Type.ime()).bottom; return insets; });
使用螢幕鍵盤同步處理動畫
使用者輕觸文字輸入欄位時,鍵盤將滑出 畫面底端,如以下範例所示:
示例標示為「未同步處理」圖 2 顯示了預設行為 在 Android 10 (API 級別 29) 中,應用程式的文字欄位和內容 而不是與鍵盤的 — 可能在視覺上造成乾擾的行為。
在 Android 11 (API 級別 30) 以上版本中,您可以使用
WindowInsetsAnimationCompat
,用於同步處理應用程式的轉換 鍵盤從螢幕底部向上和向下滑動。外觀 更流暢,如標示「已同步處理」的範例中如圖 2 所示
設定
WindowInsetsAnimationCompat.Callback
敬上
與鍵盤動畫同步的檢視畫面。
Kotlin
ViewCompat.setWindowInsetsAnimationCallback( view, object : WindowInsetsAnimationCompat.Callback(DISPATCH_MODE_STOP) { // Override methods. } )
Java
ViewCompat.setWindowInsetsAnimationCallback( view, new WindowInsetsAnimationCompat.Callback( WindowInsetsAnimationCompat.Callback.DISPATCH_MODE_STOP ) { // Override methods. });
WindowInsetsAnimationCompat.Callback
中有幾種覆寫方法。
名叫
onPrepare()
,
onStart()
,
onProgress()
,
和
onEnd()
。
在任何版面配置變更前,先呼叫 onPrepare()
。
插邊動畫開始及檢視畫面之前時,系統會呼叫 onPrepare
導致這些元素再次出現動畫您可以用它來儲存起始狀態
在本例中是檢視畫面的底部座標。
![顯示根檢視畫面起始狀態底部座標的圖片。](https://developer.android.com/static/images/guide/navigation/software-keyboard-3.png?hl=zh-tw)
onPrepare()
:
記錄啟動狀態
下列程式碼片段顯示對 onPrepare
的呼叫範例:
Kotlin
var startBottom = 0f override fun onPrepare( animation: WindowInsetsAnimationCompat ) { startBottom = view.bottom.toFloat() }
Java
float startBottom; @Override public void onPrepare( @NonNull WindowInsetsAnimationCompat animation ) { startBottom = view.getBottom(); }
插邊動畫開始時,系統會呼叫 onStart
。您可以使用它來設定
版面配置的結束狀態會變更。如果您有
設為任何檢視畫面的 OnApplyWindowInsetsListener
回呼,表示已
稱為這個元件建議您趁此機會儲存檢視畫面的結束狀態
資源。
![顯示檢視畫面結束狀態底部座標的圖片](https://developer.android.com/static/images/guide/navigation/software-keyboard-4.png?hl=zh-tw)
onStart()
錄製
結束狀態
下列程式碼片段顯示對 onStart
的呼叫範例:
Kotlin
var endBottom = 0f override fun onStart( animation: WindowInsetsAnimationCompat, bounds: WindowInsetsAnimationCompat.BoundsCompat ): WindowInsetsAnimationCompat.BoundsCompat { // Record the position of the view after the IME transition. endBottom = view.bottom.toFloat() return bounds }
Java
float endBottom; @NonNull @Override public WindowInsetsAnimationCompat.BoundsCompat onStart( @NonNull WindowInsetsAnimationCompat animation, @NonNull WindowInsetsAnimationCompat.BoundsCompat bounds ) { endBottom = view.getBottom(); return bounds; }
在執行動畫的過程中,插邊變更時,系統會呼叫 onProgress
。
因此你可以覆寫設定,並在使用鍵盤時於每個畫面收到通知
更新檢視畫面屬性,讓檢視畫面以動畫形式呈現
可與鍵盤同步處理
現在,所有版面配置變更都已完成。舉例來說,如果您使用
View.translationY
來移動檢視畫面,值會在每次
呼叫此方法後,最終會到達 0
的原始版面配置位置。
onProgress()
:
同步處理動畫。
下列程式碼片段顯示對 onProgress
的呼叫範例:
Kotlin
override fun onProgress( insets: WindowInsetsCompat, runningAnimations: MutableList<WindowInsetsAnimationCompat> ): WindowInsetsCompat { // Find an IME animation. val imeAnimation = runningAnimations.find { it.typeMask and WindowInsetsCompat.Type.ime() != 0 } ?: return insets // Offset the view based on the interpolated fraction of the IME animation. view.translationY = (startBottom - endBottom) * (1 - imeAnimation.interpolatedFraction) return insets }
Java
@NonNull @Override public WindowInsetsCompat onProgress( @NonNull WindowInsetsCompat insets, @NonNull List<WindowInsetsAnimationCompat> runningAnimations ) { // Find an IME animation. WindowInsetsAnimationCompat imeAnimation = null; for (WindowInsetsAnimationCompat animation : runningAnimations) { if ((animation.getTypeMask() & WindowInsetsCompat.Type.ime()) != 0) { imeAnimation = animation; break; } } if (imeAnimation != null) { // Offset the view based on the interpolated fraction of the IME animation. view.setTranslationY((startBottom - endBottom) * (1 - imeAnimation.getInterpolatedFraction())); } return insets; }
您可以視需要覆寫 onEnd
。系統會在動畫結束後呼叫此方法
已結束。建議您趁此機會清除任何暫時變更。