美文网首页android技术
Android 底部按钮被软键盘顶起问题解决

Android 底部按钮被软键盘顶起问题解决

作者: markRao | 来源:发表于2021-12-05 22:28 被阅读0次

    我们目前的项目是采用单 Activity 多 Fragment 的架构模式, AndroidManifest.xml 内 MainActivity 的配置如下所示。

    <activity
                android:name=".MainActivity"
                android:exported="true"
                android:windowSoftInputMode="stateHidden|adjustResize">
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
    
                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
     </activity>
    

    stateHidden
    状态隐藏,如果我们设置了这个属性,键盘状态就一定是隐藏的,不管上个界面是什么状态,也不管当前界面有没有输入的需求,就是不显示软键盘。
    adjustResize
    调整大小状态,这个属性表示 Activity 的主窗口总是会被调整大小来保证软键盘的显示空间。如果界面中有可滑动控件,显示效果跟 adjustUnspecified 显示效果一样;如果界面中没有可滑动控件,软键盘可能会盖住一些控件(布局的位置不会发生变化,可能获取了焦点的控件被软键盘盖住)。
    一般来说,我们的布局分为两种

    1. 底部按钮被滚动布局包裹
    2. 底部按钮不被滚动布局包裹

    第一种布局是不会出现软键盘把底部按钮顶起的情况,首先软键盘的打开实际上是一个 Dialog,而我们在配置文件内的 adjustResize 属性是在页面的根布局 decorView 的子 view 也就是一个线性布局内通过设置 paddingBottom = 软键盘高度,这样其实相当于把整个滚动布局的高度减少了,所以底部的按钮也只是变为需要滚动才能看到。
    第二种情况通常为一个继续按钮始终处于页面的底部,中间的内容可以滚动,当根布局的内边距等于软键盘高度时,底部按钮就看起来像是被顶起。


    从大的方向来说可以通过修改 windowSoftInputMode 来设置布局对软键盘的处理方式,当然也可以通过监听软键盘,这种修改的细粒度更小。

    1、监听软键盘的打开收起

    const val SOFT_KEY_BOARD_MIN_HEIGHT = 100
    
    fun Fragment.registerFragment(bottomView: View){
        view?.registerView(bottomView)
    }
    
    fun Activity.registerActivity(bottomView: View){
        window?.decorView?.findViewById<View>(android.R.id.content)?.registerView(bottomView)
    }
    
    fun View.registerView(bottomView: View){
        var keyboardVisible = false
        viewTreeObserver.addOnGlobalLayoutListener {
            val r = Rect()
            getWindowVisibleDisplayFrame(r)
            val heightDiff: Int = rootView.height - r.bottom
            if(heightDiff > SOFT_KEY_BOARD_MIN_HEIGHT){
                if(!keyboardVisible){
                    keyboardVisible = true
                    bottomView.isClickable = false
                    bottomView.visibility = View.INVISIBLE
                }
            }else{
                if(keyboardVisible){
                    keyboardVisible = false
                    bottomView.isClickable = false
                    bottomView.visibility = View.VISIBLE
                }
            }
        }
    }
    

    2、修改 windowSoftInputMode
    adjustPan
    如果设置了这个属性,当软键盘弹出的时候,系统会通过布局的移动,来保证用户要进行输入的输入框在用户的视线范围内。如果界面没有可滑动控件,显示效果和 adjustUnspecified 效果一样;如果界面有可滑动控件,在软键盘显示的时候,可能会有一些内容显示不出来。

    abstract class BaseFragment: Fragment() {
    
        private var keyboardType: Int = 0
    
        override fun onCreateView(
            inflater: LayoutInflater,
            container: ViewGroup?,
            savedInstanceState: Bundle?
        ): View? {
            return LayoutInflater.from(context).inflate(getContentViewRes(), container, false)
        }
    
        override fun onResume() {
            super.onResume()
            arguments?.let {
                keyboardType = it.getInt("keyboardType",  0)
                if(keyboardType == 2){
                    getBottomView()?.run {
                        registerFragment(this)
                    }
                }else {
                    onKeyboardSetting(keyboardType)
                }
            }
            initData()
            initView()
        }
    
        abstract fun getBottomView(): View?
    
        override fun onHiddenChanged(hidden: Boolean) {
            super.onHiddenChanged(hidden)
              if(!hidden){
                    onKeyboardSetting(keyboardType)
                }else{
                    onKeyboardSetting(0)
                }
        }
    
        override fun onDestroy() {
            super.onDestroy()
             onKeyboardSetting(0)
        }
    
        abstract fun initData()
    
        abstract fun initView()
    
        abstract fun getContentViewRes(): Int
    
    }
    
    fun Fragment.onKeyboardSetting(keyboardType: Int){
        if (keyboardType == 0){
            activity?.window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN or WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE)
        }else{
            activity?.window?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN)
        }
    }
    

    资料借鉴
    Android中Activity的android:windowSoftInputMode属性

    相关文章

      网友评论

        本文标题:Android 底部按钮被软键盘顶起问题解决

        本文链接:https://www.haomeiwen.com/subject/zbspxrtx.html