You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何给BottomSheetDialogFragment设置样式后,键盘平滑动画消失?

BottomSheetDialogFragment设置样式后丢失平滑键盘动画的问题与解决

问题背景

我实现了一个带有平滑键盘动画的BottomSheetDialogFragment,重要说明:为实现该平滑动画,应用主题使用了Theme.MaterialComponents.DayNight.DarkActionBar。

带有平滑键盘动画的实现代码

import android.app.Dialog
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.WindowManager
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
import com.yocto.wetodo.databinding.TodoInputDialogFragmentBinding

class TodoInputDialogFragment : BottomSheetDialogFragment() {

    private var _binding: TodoInputDialogFragmentBinding? = null

    // 该属性仅在onCreateView和onDestroyView之间有效
    private val binding get() = _binding!!

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
    }

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        _binding = TodoInputDialogFragmentBinding.inflate(inflater, container, false)
        val root: View = binding.root

        return root
    }

    override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
        val dialog = super.onCreateDialog(savedInstanceState)

        dialog.window?.also {
            it.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE)
        }

        return dialog
    }

    override fun onDestroyView() {
        super.onDestroyView()
        _binding = null
    }
}

平滑键盘动画效果

平滑键盘动画效果

但当给BottomSheetDialogFragment设置自定义样式后,平滑动画消失了。

带有非平滑键盘动画的实现代码

import android.app.Dialog
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.WindowManager
import androidx.fragment.app.DialogFragment
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
import com.yocto.wetodo.R
import com.yocto.wetodo.databinding.TodoInputDialogFragmentBinding

class TodoInputDialogFragment : BottomSheetDialogFragment() {

    private var _binding: TodoInputDialogFragmentBinding? = null

    // 该属性仅在onCreateView和onDestroyView之间有效
    private val binding get() = _binding!!

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        setStyle(DialogFragment.STYLE_NORMAL, R.style.TodoInputDialogFragment)
    }

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        _binding = TodoInputDialogFragmentBinding.inflate(inflater, container, false)
        val root: View = binding.root

        return root
    }

    override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
        val dialog = super.onCreateDialog(savedInstanceState)

        dialog.window?.also {
            it.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE)
        }

        return dialog
    }

    override fun onDestroyView() {
        super.onDestroyView()
        _binding = null
    }
}

对应的styles.xml代码

<resources xmlns:tools="http://schemas.android.com/tools">
    <style name="TodoInputDialogFragment" parent="Theme.MaterialComponents.Light.BottomSheetDialog">
        <item name="android:windowIsFloating">false</item>
        <item name="android:statusBarColor">@android:color/transparent</item>
        <item name="android:windowSoftInputMode">adjustResize</item>
    </style>
</resources>

非平滑键盘动画效果

非平滑键盘动画效果

问题原因

动画消失的核心是自定义样式的父主题与原应用主题不兼容:

  • 原应用主题Theme.MaterialComponents.DayNight.DarkActionBar继承自Material的DayNight主题,内置了键盘调整的平滑动画逻辑。
  • 自定义样式使用的父主题Theme.MaterialComponents.Light.BottomSheetDialog,其内部的窗口动画配置覆盖了原主题的平滑过渡行为,导致系统无法触发原本的键盘动画。

解决方法

方案1:修改自定义样式的父主题

将自定义样式的父主题改为与应用主题匹配的DayNight版本,继承自Theme.MaterialComponents.DayNight.BottomSheetDialog:

<resources xmlns:tools="http://schemas.android.com/tools">
    <style name="TodoInputDialogFragment" parent="Theme.MaterialComponents.DayNight.BottomSheetDialog">
        <item name="android:windowIsFloating">false</item>
        <item name="android:statusBarColor">@android:color/transparent</item>
        <item name="android:windowSoftInputMode">adjustResize</item>
        <!-- 保留其他自定义属性 -->
    </style>
</resources>

方案2:显式指定动画样式

如果需要保留Light主题,可在自定义样式中显式引用原主题的窗口动画样式:

<resources xmlns:tools="http://schemas.android.com/tools">
    <style name="TodoInputDialogFragment" parent="Theme.MaterialComponents.Light.BottomSheetDialog">
        <item name="android:windowIsFloating">false</item>
        <item name="android:statusBarColor">@android:color/transparent</item>
        <item name="android:windowSoftInputMode">adjustResize</item>
        <item name="android:windowAnimationStyle">@style/Animation.MaterialComponents.DayNight.Dialog</item>
    </style>
</resources>

方案3:代码中兼容主题配置

若不想修改样式,可在onCreateDialog中手动从应用主题获取动画样式并设置:

override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
    val dialog = super.onCreateDialog(savedInstanceState)
    dialog.window?.also {
        it.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE)
        // 从应用主题中获取动画样式
        val animStyle = requireContext().theme.obtainStyledAttributes(
            intArrayOf(android.R.attr.windowAnimationStyle)
        ).getResourceId(0, 0)
        it.setWindowAnimations(animStyle)
    }
    return dialog
}

验证

修改后重新运行,BottomSheetDialogFragment会保留自定义样式的同时,恢复平滑的键盘弹出/收起动画。

内容的提问来源于stack exchange,提问作者Cheok Yan Cheng

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 23:45:05