我正在尝试在 webview 中查看网页,然后使用 evaluateJavascript() 从页面中获取一些元素......................... ................................
这是代码...
package com.close.practice.webview
import android.annotation.SuppressLint
import android.app.Application
import android.content.Context
import android.view.ViewGroup
import android.webkit.JavascriptInterface
import android.webkit.WebView
import android.webkit.WebViewClient
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.compose.ui.viewinterop.AndroidView
import androidx.lifecycle.AndroidViewModel
@SuppressLint("SetJavaScriptEnabled")
@Composable
fun WebPageScreen(urlToRender: String, someViewModel: SomeViewModel) {
Column {
AndroidView(
modifier = Modifier
.height(200.dp),
factory = { context ->
WebView(context).apply {
layoutParams = ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT
)
webViewClient = WebViewClient()
settings.javaScriptEnabled = true
addJavascriptInterface(
someViewModel.createWebAppInterface(context),
"Android"
)
loadUrl(urlToRender)
}
}, update = {
it.loadUrl(urlToRender)
})
}
}
class SomeViewModel(application: Application, private val elementValue: MutableState<String>) : AndroidViewModel(application) {
fun getElementById(webViewObj: WebView, elementId: String) {
webViewObj.evaluateJavascript(
"(function() { return document.getElementById('$elementId').innerHTML; })();"
) { value ->
elementValue.value = value
}
}
fun createWebAppInterface(mContext: Context): WebAppInterface {
return WebAppInterface(mContext)
}
inner class WebAppInterface(private val mContext: Context) {
@JavascriptInterface
fun webViewCallJs(webViewObj: WebView) {
// Call the function that gets the element by id and stores it in a variable.
getElementById(webViewObj, "fname")
}
}
}
这是MainActivity
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
PracticeTheme {
// A surface container using the 'background' color from the theme
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
) {
Column {
val elementValue = remember { mutableStateOf("MainActivity Before") }
// To test result before the WebPageScreen is called
Text(text = "First Show MAIN Before: ${elementValue.value}")
WebPageScreen("https://www.w3schools.com/html/html_forms.asp", SomeViewModel(application, elementValue))
// to test result after the WebPageScreen is called
Text(text = "First Show MAIN After: ${elementValue.value}")
}
}
}
}
}
}
我本来希望获取具有 id (fname) 的元素的值,但代码不起作用
我没有看到您正在调用视图模型中您期望的所有函数。您可以使用打印语句和调试器来验证这一点。
此外,您还在 UI 中创建可变状态并将其传递给 veiwModel,然后推测 UI 将被更新。 Java 和 Kotlin 是按值传递的,所以你不能像那样传递变量。
您可以做的是创建一个函数并将其传递给您的 veiwModel,这将允许它更新原始值而不是实际上单独的复制值。您需要通过阅读视图模型来了解如何组织您的 UI,但为了开始测试您的代码,您可以执行以下操作:
update = { newValue ->
state.value = newValue
}
并将其传递给您的 veiwModel 以更新状态。