美文网首页
2019-08-31 获取键盘高度踩坑

2019-08-31 获取键盘高度踩坑

作者: 兣甅 | 来源:发表于2019-09-14 18:08 被阅读0次

1.使用ActivityExt.kt扩展获取键盘高度


/**ContentView*/
val Activity.mContentView: FrameLayout
  get() {
    return this.findViewById(android.R.id.content)
  }

/**获取虚拟导航高度(部分手机可能不准)*/
fun Activity.getHeightNavigationBar(): Int {
  return NavigationUtils.getNavigationBarHeight(this)
}

/**获取当前键盘高度(布局不填充到底部虚拟导航键)*/
fun Activity.getHeightKeyboard(): Int {
  if (mContentView.height > 0) {
    val rect = Rect()
    window.decorView.getWindowVisibleDisplayFrame(rect)
    val arr = intArrayOf(0, 0)
    mContentView.getLocationOnScreen(arr)
    return max(0, arr[1] + mContentView.height - rect.bottom)
  } else {
    val rect = Rect()
    //使用最外层布局填充,进行测算计算
    window.decorView.getWindowVisibleDisplayFrame(rect)
    val heightDiff = window.decorView.height - rect.height()
    val heightResult = heightDiff - mStatusBarHeight - getHeightNavigationBar()
    //由于关闭键盘可能出现负数或者很小的值,所以直接判断为关闭键盘
    return if (heightResult < 50) 0 else heightResult
  }
}

/**添加键盘监听*/
fun Activity.addListerKeyboard(
  naHeight: ((naHeight: Int) -> Unit)? = null,
  keyboardHeight: ((keyboardHeight: Int) -> Unit)? = null
) {
  val onGlobalLayoutListener = ViewTreeObserver.OnGlobalLayoutListener {
    val realKeyboardHeight = getHeightKeyboard()
    if (realKeyboardHeight != lastSetSetKeyboardHeight && window.decorView.height > 0
        && (realKeyboardHeight > 300 || realKeyboardHeight == 0)
    ) {
      lastSetSetKeyboardHeight = realKeyboardHeight
      disposable?.dispose()
      disposable = Flowable.timer(100, TimeUnit.MILLISECONDS)
          .onBackpressureLatest()
          .compose(RxUtils.rx2SchedulerHelperF())
          .subscribe {
            val navigationHeight = NavigationUtils.getNavigationBarHeight(this)
            if (navigationHeight != tempNavigationBarHeight) {
              naHeight?.invoke(navigationHeight)
              Log.i(TAG, "虚拟导航键高度=$naHeight")
              tempNavigationBarHeight = navigationHeight
            }
            if (realKeyboardHeight != tempKeyboardHeight) {
              keyboardHeight?.invoke(realKeyboardHeight)
              Log.i(TAG, "键盘高度=$realKeyboardHeight")
              tempKeyboardHeight = realKeyboardHeight
              if (realKeyboardHeight > 100) {
                saveKeyboardHeight = realKeyboardHeight
              }
            }
          }
    }
  }
  window.decorView.setTag(R.id.global_keyboard, onGlobalLayoutListener)
  window.decorView.viewTreeObserver.addOnGlobalLayoutListener(onGlobalLayoutListener)
}

2.全屏模式也可以监听键盘高度变化,需要自己处理view的移动(这样就能解决AndroidBug5497Workaround的bug了)

    //全屏代码
    val window = window
    window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)
    window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
    window.decorView.systemUiVisibility = (View.SYSTEM_UI_FLAG_LAYOUT_STABLE
        or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
        or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN)
    //manifet键盘方式
    android:windowSoftInputMode="adjustResize|stateAlwaysHidden"

3.安卓5.0以上获取键盘高度,ContentView不移动,内容移动,需要自己处理Veiw的移动情况,需要adjustResize

//监听键盘高度
fun Activity.extKeyBoard(keyCall: (statusHeight: Int, navigationHeight: Int, keyBoardHeight: Int) -> Unit) {
  mContentView.post { mContentView.layoutParams.height = mContentView.height }//防止键盘弹出导致整个布局高度变小
  this.window.decorView.setOnApplyWindowInsetsListener(object : View.OnApplyWindowInsetsListener {
    var preKeyOffset: Int = 0//键盘高度改变才回调
    override fun onApplyWindowInsets(
      v: View?,
      insets: WindowInsets?
    ): WindowInsets {
      insets?.let { ins ->
        val navHeight = ins.systemWindowInsetBottom//下面弹窗到屏幕底部的高度,比如键盘弹出后的键盘+虚拟导航键高度
        val offset = if (navHeight < ins.stableInsetBottom) navHeight
        else navHeight - ins.stableInsetBottom
        if (offset != preKeyOffset || offset == 0) {//高度变化
          val decorHeight = mActivity.window.decorView.height//整个布局高度,包含虚拟导航键
          if (decorHeight > 0) {//为了防止手机去设置页修改虚拟导航键高度,导致整个内容显示有问题,所以需要重新设置高度(与上面设置固定高度对应)
            mContentView.layoutParams.height =
              decorHeight - navHeight.coerceAtMost(ins.stableInsetBottom)//取小值
          }
          preKeyOffset = offset
          keyCall.invoke(ins.stableInsetTop, ins.stableInsetBottom, offset)
        }
      }
      return mActivity.window.decorView.onApplyWindowInsets(insets)
    }
  })
}

相关文章

网友评论

      本文标题:2019-08-31 获取键盘高度踩坑

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