Git Product home page Git Product logo

Comments (5)

FreddyChen avatar FreddyChen commented on June 14, 2024

使用PopupWindow辅助监听来将主视图设为adjustNothing,确实是个好方法。
onGlobalLayout 的判断经过我使用多种真机测试,发现需要做很多无效性判定。不然很容易产生误判。

1.横屏模式在切入后台,再切回前台,部分手机会产生视图旋转。触发布局调整。
2.底部导航栏状态变更会触发布局调整。
3.有些时候我们并不会把app设置为全屏,计算键盘高度并不总等于物理高减可视底。
4.有些机型点开软键盘后会频繁触发onGlobalLayout。

这个是我自己使用的一个,可以参考一下。
https://bitbucket.org/mm_longcheng/mm-core/src/dev/nwsi/proj/android/src/org/mm/nwsi/mmUIViewLayoutListener.java

谢谢,目前工作较忙,有空会优化这些bug

from kulakeyboard.

qwer2y avatar qwer2y commented on June 14, 2024

请问全屏状态下键盘高度该如何获取呢

from kulakeyboard.

Kuki93 avatar Kuki93 commented on June 14, 2024

微信这个功能刚出来的时候,我也研究过它的键盘表情切换动画,这里我给出我的实现键盘高度计算的方法,目前没发现有兼容性问题 @FreddyChen

class KeyboardChangeMonitor(
    private val context: Context,
    private val parentView: View
) : PopupWindow(context), ViewTreeObserver.OnGlobalLayoutListener {

    private val isAtLeastSdkR = Build.VERSION.SDK_INT >= Build.VERSION_CODES.R

    class AssistPopupWindow(
        context: Context,
        private val parentView: View
    ) : PopupWindow(context) {

        private val isAtLeastSdkR = Build.VERSION.SDK_INT >= Build.VERSION_CODES.R

        init {
            if (!isAtLeastSdkR) {
                contentView = Space(context)
                softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING
                width = 0
                height = WindowManager.LayoutParams.MATCH_PARENT
            }
        }

        fun start() {
            if (!isAtLeastSdkR) {
                if (!isShowing && parentView.windowToken != null) {
                    setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
                    showAtLocation(parentView, Gravity.NO_GRAVITY, 0, 0)
                }
            }
        }

        fun getPopHeight(): Int {
            return if (isAtLeastSdkR) 0 else contentView.height
        }
    }

    var observer: ((Int, Int) -> Unit)? = null

    private val assistPopupWindow by lazy(LazyThreadSafetyMode.NONE) {
        AssistPopupWindow(context, parentView)
    }

    private var lastKeyboardHeight = 0

    private var currentKeyboardHeight = 0

    init {
        if (!isAtLeastSdkR) {
            contentView = Space(context).also {
                it.viewTreeObserver.addOnGlobalLayoutListener(this)
            }
            softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE or
                    WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE
            inputMethodMode = INPUT_METHOD_NEEDED
            width = 0
            height = WindowManager.LayoutParams.MATCH_PARENT
        }
    }

    override fun onGlobalLayout() {
        if (!isAtLeastSdkR) {
            handleOnGlobalLayout()
        }
    }

    fun isShowKeyboard() = currentKeyboardHeight > 120

    fun lastIsShowKeyboard() = lastKeyboardHeight > 120

    @SuppressLint("NewApi")
    fun start() {
        if (isAtLeastSdkR) {
            (context as Activity).window.decorView.setOnApplyWindowInsetsListener { _, insets ->
                insets.getInsets(WindowInsets.Type.navigationBars()).bottom.run {
                    handlerDispatchEvent(insets.getInsets(WindowInsets.Type.ime()).bottom.minus(this))
                    insets.inset(0, 0, 0, this)
                }
            }
        } else {
            if (!isShowing && parentView.windowToken != null) {
                setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
                showAtLocation(parentView, Gravity.NO_GRAVITY, 0, 0)
                assistPopupWindow.start()
            }
        }
    }

    @SuppressLint("NewApi")
    fun close() {
        observer = null
        if (isAtLeastSdkR) {
            (context as Activity).window.decorView.setOnApplyWindowInsetsListener(null)
        } else {
            contentView.viewTreeObserver.removeOnGlobalLayoutListener(this)
            dismiss()
            assistPopupWindow.dismiss()
        }
    }

    private fun handleOnGlobalLayout() {
        val contentHeight = contentView.height
        if (contentHeight <= 0) {
            return // 忽略无需处理
        }
        val offset = assistPopupWindow.getPopHeight().minus(contentHeight)
        val open = offset > context.dip(100f)
        val newHeight = if (open) {
            offset
        } else {
            0
        }
        handlerDispatchEvent(newHeight)
    }

    private fun handlerDispatchEvent(height: Int) {
        val newHeight = height.coerceAtLeast(0)
        if (currentKeyboardHeight == newHeight) {
            return
        }
        lastKeyboardHeight = currentKeyboardHeight
        val orientation = context.resources.configuration.orientation
        if (newHeight < 120) {
            currentKeyboardHeight = 0
            notifyKeyboardHeightChanged(0, orientation)
        } else {
            currentKeyboardHeight = newHeight
            notifyKeyboardHeightChanged(newHeight, orientation)
        }
    }

    private fun notifyKeyboardHeightChanged(height: Int, orientation: Int) {
        observer?.invoke(height, orientation)
    }
}

from kulakeyboard.

wsdydeni avatar wsdydeni commented on June 14, 2024

@Kuki93 大佬,看到你的微信切换表情面板,又看到你这个,方案没有特别大的问题,就是有些手机无法监听,同事的俩台手机就不行,型号华为Mate40系统鸿蒙2.0.0/型号红米Note9pro系统Android11

from kulakeyboard.

qingkouwei avatar qingkouwei commented on June 14, 2024

这个兼容性问题最后有解吗?

from kulakeyboard.

Related Issues (10)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.