我试图在前台显示带有浮动视图的WebView,我从活动的伴随对象中获取WebView,并通过删除WebView的父级将其添加到浮动视图中,并且它可以工作并显示WebView,而不会丢失当前加载的页面。
问题是当用户想要返回应用程序时我想将此网络视图返回到活动中。 同样的方法(从前台获取 webview 并删除 webview 的父级并赋予它组成 AndroidView 小部件)不起作用,并且活动不显示 webview,并且如果我之后切换到浮动小部件,它也不会显示在前台
前景中的浮动视图:
class OverlayWebViewScreen(
private val context: Context,
private val webView: WebView,
val lifecycleService: ForegroundComposeLifeCycle
) {
private lateinit var windowManager: WindowManager
private lateinit var layoutParams: WindowManager.LayoutParams
fun open() {
PermissionManager.askForDisplayOverApps(context)
context.run {
windowManager = getSystemService(Context.WINDOW_SERVICE) as WindowManager
layoutParams = WindowManager.LayoutParams(
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.WRAP_CONTENT,
WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
PixelFormat.TRANSLUCENT
)
val parentView = webView.parent as? ViewGroup
parentView?.removeView(webView)
val composableView = ComposeView(context)
lifecycleService.attachToDecorView(composableView)
lifecycleService.onResume()
composableView.setViewTreeLifecycleOwner(lifecycleService)
composableView.setContent {
var offsetX by remember { mutableFloatStateOf(0f) }
var offsetY by remember { mutableFloatStateOf(0f) }
Column(modifier = Modifier.size(300.dp))
{
Row {
Icon(
modifier = Modifier
.background(color = Color.Magenta)
.pointerInput(Unit) {
detectDragGestures { change, dragAmount ->
offsetX += dragAmount.x
offsetY -= dragAmount.y
layoutParams.x = offsetX.toInt()
layoutParams.y = offsetY.toInt()
windowManager.updateViewLayout(composableView, layoutParams)
}
},
imageVector = Icons.Default.DragHandle, contentDescription = null
)
IconButton(onClick = {
windowManager.removeView(composableView)
ServiceManager.restartActivityWhenKilled(context)
}) {
Icon(
modifier = Modifier
.background(color = Color.Magenta)
,
imageVector = Icons.Default.OpenInFull, contentDescription = null
)
}
}
AndroidView(
modifier = Modifier.size(200.dp),
factory = {
webView
}
)
AdsManager.BannerAdView(modifier = Modifier)
}
}
// Set the position of the WebView at the bottom of the screen
layoutParams.gravity = Gravity.BOTTOM or Gravity.START
windowManager.addView(composableView,layoutParams)
}
}
fun close(){
ServiceManager.restartActivityWhenKilled(context)
}
}
Activity 的 onStart 方法是 Compose,我从前台服务获取 webview
override fun onStart() {
val backPressedCallback = onBackPressedCallbackOverride()
logger("onStart")
if (ServiceManager.isServiceActive()){
val parentView = webView.parent as? ViewGroup
parentView?.removeView(webView)
webView = AutoRefreshService.getWebView()
webViewChanged.value = webViewChanged.value.not()
logger(webView.toString())
}
setContent {
val context = LocalContext.current
val activity = context as? ComponentActivity
activity?.onBackPressedDispatcher?.addCallback(this, backPressedCallback)
InitVariables()
AutoRefreshWebPageTheme {
Surface(modifier = Modifier.fillMaxSize(), color = MaterialTheme.colorScheme.background) {
Scaffold(
modifier = Modifier.fillMaxSize(),
) { paddingValues ->
Column(modifier = Modifier.padding(paddingValues)) {
AndroidView(
modifier = Modifier.weight(1f),
update = {
if (webViewChanged.value)
webView.bringToFront()
},
factory = { webView },
)
AdsManager.BannerAdView(modifier = Modifier)
}
}
if (autoRefreshDialog.value) {
AutoRefreshDialog()
}
}
}
}
if (preferences.getAutoRefreshStatus()){
if (ServiceManager.isServiceActive().not()) {
startPageReloading(this)
}
}
super.onStart()
}
我尝试使用 compainion 对象来跨应用程序共享 webview,它在探查器中仅占用 200mb 的内存。 我从 Activity 中获取了 WebView 并将其应用于前台,它甚至显示了带有加载屏幕的 WebView。但相反的方法(将 webview 从前台带到 Activity 不起作用) 视频:
我的期望是通过加载的 webview 屏幕返回到活动
经过几次尝试,我找到了解决方案: 解决方案是我没有将 webview 附加到 jetpack compose 中的 androidView,因为我不知道该怎么做,但我发现:
附加到AndroidView父组将是这样的:
AndroidView(
modifier = Modifier.weight(1f),
update = { view ->
val viewGroup = view.parent as? ViewGroup
viewGroup?.let {
// I used webViewGroup variable to keep view's parent in case it's
//changed unexpectedly
if (::webViewGroup.isInitialized.not()){
webViewGroup = viewGroup
// removing webview's current parent and attach to activity's
//parent
val parentView = webView.parent as? ViewGroup
parentView?.removeView(webView)
webViewGroup.addView(webView)
}
}
},
factory = { webView },