Skip to content

Instantly share code, notes, and snippets.

@zkywalker
Created November 30, 2020 06:23
Show Gist options
  • Save zkywalker/489c333fb297d772632614ca159dce45 to your computer and use it in GitHub Desktop.
Save zkywalker/489c333fb297d772632614ca159dce45 to your computer and use it in GitHub Desktop.
监听键盘弹起,在键盘上面悬浮视图
import android.app.Activity
import android.content.Context
import android.graphics.Rect
import android.support.constraint.ConstraintLayout
import android.util.AttributeSet
import android.view.Gravity
import android.view.View
import android.view.ViewGroup
import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
import android.widget.FrameLayout
/**
* 输入法上悬浮框(没有使用单独的window实现,直接加在原有的decor view内)
*/
open class InputFloatView @JvmOverloads constructor(context: Context, attributeSet: AttributeSet? = null, defThemeInt: Int = 0)
: ConstraintLayout(context, attributeSet, defThemeInt) {
var activity: Activity? = null
var isListening = true
open var customInputViewThreshold: Int? = null
open var needFixStatusBar: Boolean = false
private var listener: ((view: View, isShow: Boolean, inputViewHeight: Int) -> Unit)? = null
init {
if (context is Activity) {
register(context)
}
}
fun register(activity: Activity, needFixStatusBar: Boolean = false) {
this.activity = activity
val decorView = activity.window.decorView
this.needFixStatusBar = needFixStatusBar
decorView.viewTreeObserver.addOnGlobalLayoutListener {
if (!isListening) {
return@addOnGlobalLayoutListener
}
val r = Rect()
// 注意我们是沉浸式的页面,这个地方会少算一个status bar的高度
decorView.getWindowVisibleDisplayFrame(r)
val screenHeight = decorView.height
val heightDifference = screenHeight - (r.bottom - r.top)
// todo 能不能主动获取是否是沉浸式的页面?
val fixStatusBar = if (this.needFixStatusBar) {
getStatusHeight()
} else {
0
}
if (this.parent == null) {
val layoutParams = initLayoutParams()
layoutParams.gravity = Gravity.BOTTOM
(decorView as? ViewGroup)?.addView(this, layoutParams)
}
if (heightDifference > customInputViewThreshold ?: INPUT_VIEW_THRESHOLD) {
val inputViewHeight = heightDifference - fixStatusBar
(this.layoutParams as? ViewGroup.MarginLayoutParams)?.bottomMargin = inputViewHeight
this.visibility = View.VISIBLE
this.listener?.invoke(this, true, heightDifference)
} else {
this.visibility = View.GONE
this.listener?.invoke(this, false, heightDifference)
}
}
}
fun setOnInputViewToggleListener(listener: ((view: View, isShow: Boolean, inputViewHeight: Int) -> Unit)?) {
this.listener = listener
}
open fun initLayoutParams(): FrameLayout.LayoutParams = FrameLayout.LayoutParams(WRAP_CONTENT, WRAP_CONTENT)
companion object {
/**
* 随便写了个输入法高度阈值
*/
const val INPUT_VIEW_THRESHOLD = 800
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment