varendBottom=0foverridefunonStart(animation:WindowInsetsAnimationCompat,bounds:WindowInsetsAnimationCompat.BoundsCompat):WindowInsetsAnimationCompat.BoundsCompat{// Record the position of the view after the IME transition.endBottom=view.bottom.toFloat()returnbounds}
overridefunonProgress(insets:WindowInsetsCompat,runningAnimations:MutableList<WindowInsetsAnimationCompat>):WindowInsetsCompat{// Find an IME animation.valimeAnimation=runningAnimations.find{it.typeMaskandWindowInsetsCompat.Type.ime()!=0}?:returninsets// Offset the view based on the interpolated fraction of the IME animation.view.translationY=(startBottom-endBottom)*(1-imeAnimation.interpolatedFraction)returninsets}
Java
@NonNull@OverridepublicWindowInsetsCompatonProgress(@NonNullWindowInsetsCompatinsets,@NonNullList<WindowInsetsAnimationCompat>runningAnimations){// Find an IME animation.WindowInsetsAnimationCompatimeAnimation=null;for(WindowInsetsAnimationCompatanimation: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()));}returninsets;}
[null,null,["最后更新时间 (UTC):2025-08-21。"],[],[],null,["# Control and animate the software keyboard\n\nTry the Compose way \nJetpack Compose is the recommended UI toolkit for Android. Learn how to work with the keyboard in Compose. \n[Software keyboard in Compose →](/develop/ui/compose/system/keyboard-animations) \n\n\u003cbr /\u003e\n\nUsing [`WindowInsetsCompat`](/reference/androidx/core/view/WindowInsetsCompat),\nyour app can query and control the on-screen keyboard (also called the\n[IME](https://en.wikipedia.org/wiki/Input_method)) similar to the\nway it interacts with the system bars. Your app can also use\n[`WindowInsetsAnimationCompat`](/reference/androidx/core/view/WindowInsetsAnimationCompat)\nto create seamless transitions when the software keyboard is opened or closed.\n**Figure 1.** Two examples of the software keyboard open-closed transition.\n\nPrerequisites\n-------------\n\nBefore setting up control and animation for the software keyboard, configure\nyour app to [display edge-to-edge](/training/gestures/edge-to-edge). This lets\nit handle [system window insets](/develop/ui/views/layout/insets) such as the\nsystem bars and the on-screen keyboard.\n\nCheck keyboard software visibility\n----------------------------------\n\nUse [`WindowInsets`](/reference/android/view/WindowInsets) to check the software\nkeyboard visibility. \n\n### Kotlin\n\n```kotlin\nval insets = ViewCompat.getRootWindowInsets(view) ?: return\nval imeVisible = insets.isVisible(WindowInsetsCompat.Type.ime())\nval imeHeight = insets.getInsets(WindowInsetsCompat.Type.ime()).bottom\n```\n\n### Java\n\n```java\nWindowInsetsCompat insets = ViewCompat.getRootWindowInsets(view);\nboolean imeVisible = insets.isVisible(WindowInsetsCompat.Type.ime());\nint imeHeight = insets.getInsets(WindowInsetsCompat.Type.ime()).bottom;\n```\n\nAlternatively, you can use\n[`ViewCompat.setOnApplyWindowInsetsListener`](/reference/androidx/core/view/ViewCompat#setOnApplyWindowInsetsListener(android.view.View,%20androidx.core.view.OnApplyWindowInsetsListener))\nto observe changes to software keyboard visibility. \n\n### Kotlin\n\n```kotlin\nViewCompat.setOnApplyWindowInsetsListener(view) { _, insets -\u003e\n val imeVisible = insets.isVisible(WindowInsetsCompat.Type.ime())\n val imeHeight = insets.getInsets(WindowInsetsCompat.Type.ime()).bottom\n insets\n}\n```\n\n### Java\n\n```java\nViewCompat.setOnApplyWindowInsetsListener(view, (v, insets) -\u003e {\n boolean imeVisible = insets.isVisible(WindowInsetsCompat.Type.ime());\n int imeHeight = insets.getInsets(WindowInsetsCompat.Type.ime()).bottom;\n return insets;\n});\n```\n| **Note:** To achieve the best backward compatibility with this AndroidX implementation, set `android:windowSoftInputMode=\"adjustResize\"` to the activity in your `AndroidManifest.xml` file.\n\nSynchronize animation with the software keyboard\n------------------------------------------------\n\nA user tapping a text input field causes the keyboard to slide into place from\nthe bottom of the screen, as shown in the following example:\n**Figure 2.** Synchronized keyboard animation.\n\n- The example labeled \"Unsynchronized\" in figure 2 shows the default behavior\n in Android 10 (API level 29), in which the text field and content of the app\n snap into place instead of synchronizing with the keyboard's\n animation---behavior that can be visually jarring.\n\n- In Android 11 (API level 30) and higher, you can use\n `WindowInsetsAnimationCompat` to synchronize the transition of the app with\n the keyboard sliding up and down from the bottom of the screen. This looks\n smoother, as shown in the example labeled \"Synchronized\" in figure 2.\n\n| **Note:** Don't consume `WindowInsets` in `setWindowInsetsApplyListener` for any parent [`ViewGroup`](/reference/android/view/ViewGroup) objects. Instead, let `WindowInsetsAnimatorCompat` handle them on Android 10 and lower.\n\nConfigure\n[`WindowInsetsAnimationCompat.Callback`](/reference/androidx/core/view/WindowInsetsAnimationCompat.Callback)\nwith the view to be synchronized with the keyboard animation. \n\n### Kotlin\n\n```kotlin\nViewCompat.setWindowInsetsAnimationCallback(\n view,\n object : WindowInsetsAnimationCompat.Callback(DISPATCH_MODE_STOP) {\n // Override methods.\n }\n)\n```\n\n### Java\n\n```java\nViewCompat.setWindowInsetsAnimationCallback(\n view,\n new WindowInsetsAnimationCompat.Callback(\n WindowInsetsAnimationCompat.Callback.DISPATCH_MODE_STOP\n ) {\n // Override methods.\n });\n```\n\nThere are several methods to override in `WindowInsetsAnimationCompat.Callback`,\nnamely\n[`onPrepare()`](/reference/androidx/core/view/WindowInsetsAnimationCompat.Callback#onPrepare(androidx.core.view.WindowInsetsAnimationCompat)),\n[`onStart()`](/reference/androidx/core/view/WindowInsetsAnimationCompat.Callback#onStart(androidx.core.view.WindowInsetsAnimationCompat,%20androidx.core.view.WindowInsetsAnimationCompat.BoundsCompat)),\n[`onProgress()`](/reference/androidx/core/view/WindowInsetsAnimationCompat.Callback#onProgress(androidx.core.view.WindowInsetsCompat,%20java.util.List%3Candroidx.core.view.WindowInsetsAnimationCompat%3E)),\nand\n[`onEnd()`](/reference/androidx/core/view/WindowInsetsAnimationCompat.Callback#onEnd(androidx.core.view.WindowInsetsAnimationCompat)).\nStart with calling `onPrepare()` before any of the layout changes.\n\n`onPrepare` is called when an insets animation is starting and before the views\nare re-laid out due to an animation. You can use it to save the start state,\nwhich in this case is the bottom coordinate of the view.\n**Figure 3.** Using `onPrepare()` to record the start state.\n\nThe following snippet shows a sample call to `onPrepare`: \n\n### Kotlin\n\n```kotlin\nvar startBottom = 0f\n\noverride fun onPrepare(\n animation: WindowInsetsAnimationCompat\n) {\n startBottom = view.bottom.toFloat()\n}\n```\n\n### Java\n\n```java\nfloat startBottom;\n\n@Override\npublic void onPrepare(\n @NonNull WindowInsetsAnimationCompat animation\n) {\n startBottom = view.getBottom();\n}\n```\n\n`onStart` is called when an insets animation starts. You can use it to set all\nthe view properties to the end state of the layout changes. If you have an\n`OnApplyWindowInsetsListener` callback set to any of the views, it is already\ncalled at this point. This is a good time to save the end state of the view\nproperties.\n**Figure 4.** Using `onStart()` to record the end state.\n\nThe following snippet shows a sample call to `onStart`: \n\n### Kotlin\n\n```kotlin\nvar endBottom = 0f\n\noverride fun onStart(\n animation: WindowInsetsAnimationCompat,\n bounds: WindowInsetsAnimationCompat.BoundsCompat\n): WindowInsetsAnimationCompat.BoundsCompat {\n // Record the position of the view after the IME transition.\n endBottom = view.bottom.toFloat()\n\n return bounds\n}\n```\n\n### Java\n\n```java\nfloat endBottom;\n\n@NonNull\n@Override\npublic WindowInsetsAnimationCompat.BoundsCompat onStart(\n @NonNull WindowInsetsAnimationCompat animation,\n @NonNull WindowInsetsAnimationCompat.BoundsCompat bounds\n) {\n endBottom = view.getBottom();\n return bounds;\n}\n```\n\n`onProgress` is called when the insets change as part of running an animation,\nso you can override it and be notified on every frame during the keyboard\nanimation. Update the view properties so that the view animates in\nsynchronization with the keyboard.\n\nAll the layout changes are complete at this point. For example, if you use\n`View.translationY` to shift the view, the value gradually decreases for every\ncall of this method and eventually reaches `0` to the original layout position.\n**Figure 5.** Using `onProgress()` to synchronize the animations.\n\nThe following snippet shows a sample call to `onProgress`: \n\n### Kotlin\n\n```kotlin\noverride fun onProgress(\n insets: WindowInsetsCompat,\n runningAnimations: MutableList\u003cWindowInsetsAnimationCompat\u003e\n): WindowInsetsCompat {\n // Find an IME animation.\n val imeAnimation = runningAnimations.find {\n it.typeMask and WindowInsetsCompat.Type.ime() != 0\n } ?: return insets\n\n // Offset the view based on the interpolated fraction of the IME animation.\n view.translationY =\n (startBottom - endBottom) * (1 - imeAnimation.interpolatedFraction)\n\n return insets\n}\n```\n\n### Java\n\n```java\n@NonNull\n@Override\npublic WindowInsetsCompat onProgress(\n @NonNull WindowInsetsCompat insets,\n @NonNull List\u003cWindowInsetsAnimationCompat\u003e runningAnimations\n) {\n // Find an IME animation.\n WindowInsetsAnimationCompat imeAnimation = null;\n for (WindowInsetsAnimationCompat animation : runningAnimations) {\n if ((animation.getTypeMask() & WindowInsetsCompat.Type.ime()) != 0) {\n imeAnimation = animation;\n break;\n }\n }\n if (imeAnimation != null) {\n // Offset the view based on the interpolated fraction of the IME animation.\n view.setTranslationY((startBottom - endBottom)\n\n * (1 - imeAnimation.getInterpolatedFraction()));\n }\n return insets;\n}\n```\n\nOptionally, you can override `onEnd`. This method is called after the animation\nis over. This is a good time to clean up any temporary changes.\n\nAdditional resources\n--------------------\n\n- [WindowInsetsAnimation](https://github.com/android/user-interface-samples/tree/main/WindowInsetsAnimation) on GitHub."]]