Skip to content

Instantly share code, notes, and snippets.

@AChep
Last active April 2, 2018 10:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save AChep/e4a6a20545603a2bb7703831313550da to your computer and use it in GitHub Desktop.
Save AChep/e4a6a20545603a2bb7703831313550da to your computer and use it in GitHub Desktop.
package com.artemchep.webviewscroll
import android.os.Bundle
import android.support.v7.app.AppCompatActivity
import android.webkit.JavascriptInterface
import android.webkit.WebView
import android.webkit.WebViewClient
import kotlinx.android.synthetic.main.activity_main.*
class MainActivity : AppCompatActivity() {
companion object {
private const val JS_INTERFACE = "Android"
}
private val keyboardHeightPx by lazy {
resources.getInteger(R.integer.keyboard_height_px)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
webView.apply {
settings.apply {
javaScriptEnabled = true
}
addJavascriptInterface(JsInterface(this@MainActivity), JS_INTERFACE)
webViewClient = object : WebViewClient() {
override fun shouldOverrideUrlLoading(view: WebView, url: String): Boolean {
return false
}
override fun onPageFinished(view: WebView, url: String) {
super.onPageFinished(view, url)
evaluateJavascript("""
var eventHandler = function(event) {
var type = event.target.nodeName.toLowerCase();
if (type == 'input' || type == 'textarea') {
var rect = event.target.getBoundingClientRect();
var scrollY = $JS_INTERFACE.calculateVerticalScroll(rect.top + rect.height);
if (scrollY > 0) {
window.scrollBy(0, scrollY);
}
}
};
document.body.addEventListener('focus', eventHandler, true);
document.body.addEventListener('click', eventHandler, true);
// Add bottom margin to the page, so there's always a place
// to scroll
document.body.style.marginBottom="${keyboardHeightPx}px";
""", {})
}
}
}
loadSimple()
}
override fun onDestroy() {
super.onDestroy()
webView.removeJavascriptInterface(JS_INTERFACE)
}
private fun loadSimple() {
webView.loadHtml("""
<div>
<div style="margin-top: 600px">Title</div>
<input type="text">
<div>Footer</div>
</div>
""")
}
private class JsInterface(private val activity: MainActivity) {
@JavascriptInterface
fun calculateVerticalScroll(y: Int): Int {
val density = activity.resources.displayMetrics.density
val windowHeightLimit = activity.window.decorView.height - activity.keyboardHeightPx * density
val windowY = y * density + intArrayOf(0, 0)
.apply {
activity.webView.getLocationInWindow(this)
}[1]
return Math.max((windowY - windowHeightLimit) / density, 0f).toInt()
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment