我正在使用桌面撰写编写桌面应用程序。但是找不到任何关于如何使用我们应该使用的 android 中的 web-view 的建议。
对于桌面应用程序,我们不能使用 android web-view 任何帮助和建议将不胜感激。
我正在使用桌面撰写编写桌面应用程序。但是找不到任何关于如何使用我们应该使用的 android 中的 web-view 的建议。
对于桌面应用程序,我们不能使用 android web-view 任何帮助和建议将不胜感激。
我已经WebView
在 Compose Desktop 中实现了 JavaFX(WebView
此处的附加功能 - http://tutorials.jenkov.com/javafx/webview.html)。我的实际用例是用于映射目的,因为实际上没有任何像样的映射 Java 库。然而,这个例子只是加载一个 web url,但是你可以很容易地html
从加载自定义内容的资源中加载一个自定义页面。
设置如下(注意java fx插件只能在实际桌面模块中使用,因为它与android库插件冲突)。
桌面模块build.gradle
文件:
import org.jetbrains.compose.compose
import org.jetbrains.compose.desktop.application.dsl.TargetFormat
plugins {
kotlin("multiplatform")
id("org.openjfx.javafxplugin") version "0.0.10"
id("org.jetbrains.compose") version "1.0.1"
}
group = "com.example.webview"
version = "1.0.0"
kotlin {
jvm {
compilations.all {
kotlinOptions {
jvmTarget = "11"
}
withJava()
}
}
sourceSets {
val jvmMain by getting {
dependencies {
implementation(project(":shared"))
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.0-native-mt")
{ version { strictly("1.6.0-native-mt") } }
implementation(compose.desktop.currentOs)
//Optional other deps
implementation(compose.uiTooling)
implementation(compose.runtime)
implementation(compose.foundation)
implementation(compose.material)
implementation(compose.animation)
implementation(compose.animationGraphics)
}
}
val jvmTest by getting {
dependencies {
// testing deps
}
}
}
}
compose.desktop {
application {
mainClass = "Mainkt"
nativeDistributions {
targetFormats(TargetFormat.Dmg, TargetFormat.Msi, TargetFormat.Deb)
packageName = "your.package.name"
packageVersion = "1.0.0"
}
}
}
javafx {
version = "16"
modules = listOf("javafx.controls", "javafx.swing", "javafx.web", "javafx.graphics")
}
Main
kotlin 文件:
fun main() = application(exitProcessOnExit = true) {
// Required to make sure the JavaFx event loop doesn't finish (can happen when java fx panels in app are shown/hidden)
val finishListener = object : PlatformImpl.FinishListener {
override fun idle(implicitExit: Boolean) {}
override fun exitCalled() {}
}
PlatformImpl.addListener(finishListener)
Window(
title = "WebView Test",
resizable = false,
state = WindowState(
placement = Floating,
size = DpSize(minWidth.dp, minHeight.dp)
),
onCloseRequest = {
PlatformImpl.removeListener(finishListener)
exitApplication()
},
content = {
val jfxPanel = remember { JFXPanel() }
var jsObject = remember<JSObject?> { null }
Box(modifier = Modifier.fillMaxSize().background(Color.White)) {
ComposeJFXPanel(
composeWindow = window,
jfxPanel = jfxPanel,
onCreate = {
Platform.runLater {
val root = WebView()
val engine = root.engine
val scene = Scene(root)
engine.loadWorker.stateProperty().addListener { _, _, newState ->
if (newState === Worker.State.SUCCEEDED) {
jsObject = root.engine.executeScript("window") as JSObject
// execute other javascript / setup js callbacks fields etc..
}
}
engine.loadWorker.exceptionProperty().addListener { _, _, newError ->
println("page load error : $newError")
}
jfxPanel.scene = scene
engine.load("http://google.com") // can be a html document from resources ..
engine.setOnError { error -> println("onError : $error") }
}
}, onDestroy = {
Platform.runLater {
jsObject?.let { jsObj ->
// clean up code for more complex implementations i.e. removing javascript callbacks etc..
}
}
})
}
})
}
@Composable
fun ComposeJFXPanel(
composeWindow: ComposeWindow,
jfxPanel: JFXPanel,
onCreate: () -> Unit,
onDestroy: () -> Unit = {}
) {
val jPanel = remember { JPanel() }
val density = LocalDensity.current.density
Layout(
content = {},
modifier = Modifier.onGloballyPositioned { childCoordinates ->
val coordinates = childCoordinates.parentCoordinates!!
val location = coordinates.localToWindow(Offset.Zero).round()
val size = coordinates.size
jPanel.setBounds(
(location.x / density).toInt(),
(location.y / density).toInt(),
(size.width / density).toInt(),
(size.height / density).toInt()
)
jPanel.validate()
jPanel.repaint()
},
measurePolicy = { _, _ -> layout(0, 0) {} })
DisposableEffect(jPanel) {
composeWindow.add(jPanel)
jPanel.layout = BorderLayout(0, 0)
jPanel.add(jfxPanel)
onCreate()
onDispose {
onDestroy()
composeWindow.remove(jPanel)
}
}
}
结果 :
感谢这篇原始帖子中的代码,它提供了JFXPanel
- https://github.com/JetBrains/compose-jb/issues/519#issuecomment-804030550的批量实现以及我自己对 Java FX 事件循环修复的后续评论。