簡體   English   中英

如何在 Android WebView 的 Web 應用程序端使用 backpress 事件?

[英]How to consume backpress events in web app side in Android WebView?

在帶有 JS 界面的Kotlin WebView上工作,我的網絡應用程序需要從本機端檢測KeyEvent.KEYCODE_BACK事件,以在出現時關閉網絡應用程序對話框。 如果對話框被關閉,我應該在本機端什么都不做(返回 true 到 super),否則我需要完成 web 視圖活動(返回 false 到 super)。 為了抓住我的意圖,請閱讀下面的代碼,我在我的自定義WebView作為線索,

override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean {

    if (event.action == KeyEvent.ACTION_DOWN) {
        when (keyCode) {
            KeyEvent.KEYCODE_BACK -> {

                this.evaluateJavascript("onDeviceBackPressed();", ValueCallback {
                    if (it == "1") {
                        // "Web app consumed onDeviceBackPressed event!"
                    } else {
                        // "Web app did not consume onDeviceBackPressed event!"
                        // super.onKeyDown(keyCode, event) won't work
                    }
                })

                // I am required to make the return call wait
                // return true/false base on status returned by js func
            }
        }
    }
    return super.onKeyDown(keyCode, event)
}

但我知道不可能異步等待超級調用。 我如何以其他方式處理這種情況?

您可以在等待 JS 的第一個按鍵按下事件期間使用 KeyEvent,然后在獲得結果時重新使用它。

我曾經對觸摸事件使用過這樣的技巧,所以它應該可以工作。

var delayedKeyCode : Int? = null
var delayedKeyEvent : KeyEvent? = null
var keyDownJSResult : String? = null

override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean {
    if (event.action == KeyEvent.ACTION_DOWN) {
        when (keyCode) {
            KeyEvent.KEYCODE_BACK -> {
                // see if there's "result" provided from JS
                keyDownJSResult?.let{
                    keyDownJSResult = null    // wipe out result so it's not triggered twice
                    if (it == "1") {
                        // "Web app consumed onDeviceBackPressed event!"
                        return true
                    } else {
                        // "Web app did not consume onDeviceBackPressed event!"
                        return super.onKeyDown(keyCode, event)
                    }
                }
                // otherwise store keyDown arguments for later and trigger JS
                delayedKeyCode = keyCode
                delayedKeyEvent = event
                this.evaluateJavascript("onDeviceBackPressed();", ValueCallback {
                     // when JS returns value, trigger this onKeyDown event again
                     val oldCode = delayedKeyCode
                     val oldEv = delayedKeyEvent
                     delayedKeyCode = null
                     delayedKeyEvent = null
                     keyDownJSResult = it
                     onKeyDown(oldCode, oldEv)
                })
                // always consume event when waiting for JS result
                return true 
            }
        }
    }
    return super.onKeyDown(keyCode, event)
}

最后,我的一個小技巧解決了我的問題,

override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean {

    if (event.action == KeyEvent.ACTION_DOWN) {
        when (keyCode) {
            KeyEvent.KEYCODE_BACK -> {
                this.evaluateJavascript("onDeviceBackPressed();", ValueCallback {
                    if (it == "1") {
                        // consumed by web app, do nothing
                    } else {
                        // not consumed by web app, fire explicit back press event
                        mContext.onBackPressed()
                    }
                })
                return true
            }
        }
    }
    return super.onKeyDown(keyCode, event)
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM