@@ -35,7 +35,9 @@ import androidx.compose.runtime.remember
3535import androidx.compose.runtime.rememberCoroutineScope
3636import androidx.compose.runtime.setValue
3737import androidx.compose.ui.Modifier
38+ import androidx.compose.ui.layout.layout
3839import androidx.compose.ui.platform.LocalContext
40+ import androidx.compose.ui.platform.LocalDensity
3941import androidx.compose.ui.unit.dp
4042import androidx.compose.ui.viewinterop.AndroidView
4143import androidx.core.graphics.drawable.toDrawable
@@ -85,12 +87,15 @@ import kotlinx.serialization.json.jsonPrimitive
8587import org.jsoup.Jsoup
8688import org.jsoup.nodes.Document
8789import org.jsoup.nodes.Element
90+ import kotlin.math.min
8891
8992// HTML 点击事件监听器接口
9093fun interface HtmlClickListener {
9194 fun onElementClick (element : Element )
9295}
9396
97+ private const val MAX_WEBVIEW_COMPOSE_HEIGHT_PX = 180_000
98+
9499/* *
95100 * 获取最高清晰度的视频URL
96101 */
@@ -200,6 +205,8 @@ class CustomWebView : WebView {
200205 var document: Document ? = null
201206 private set
202207 var contentId: String? = null
208+ var debugLabel: String = " CustomWebView"
209+ var lastLoadedUrl: String? = null
203210 private var htmlClickListener: HtmlClickListener ? = null
204211 var scrollToHeightCallback: ((Int , Int ) -> Unit )? = null
205212 var onContentHeightCallback: ((Int ) -> Unit )? = null
@@ -373,7 +380,11 @@ class CustomWebView : WebView {
373380 // same content
374381 return
375382 }
376- Log .i(" CustomWebView" , " Loading content for URL: $url with document title: ${document.title()} " )
383+ lastLoadedUrl = url
384+ Log .i(
385+ " CustomWebView" ,
386+ " [$debugLabel ] Loading content for URL: $url with document title: ${document.title()} contentId=${contentId ? : " null" } " ,
387+ )
377388 val preferences = context.getSharedPreferences(PREFERENCE_NAME , Context .MODE_PRIVATE )
378389 val fontSize = preferences.getInt(" webviewFontSize" , 100 )
379390 val lineHeight = preferences.getInt(" webviewLineHeight" , 160 )
@@ -511,33 +522,45 @@ fun WebviewComp(
511522 modifier : Modifier = Modifier .wrapContentSize(),
512523 scrollState : ScrollState ? = null,
513524 existingWebView : CustomWebView ? = null,
525+ debugLabel : String = "WebviewComp ",
514526 onLoad : (CustomWebView ) -> Unit ,
515527) {
516528 val coroutineScope = rememberCoroutineScope()
517529 val context = LocalContext .current
530+ val density = LocalDensity .current
518531 val preferences = context.getSharedPreferences(PREFERENCE_NAME , Context .MODE_PRIVATE )
519532 val useHardwareAcceleration = preferences.getBoolean(" webviewHardwareAcceleration" , true )
520533 // JS 上报的内容高度(CSS 像素 = dp,WebView viewport 默认 1 CSS px = 1 dp);
521534 // 0 表示尚未收到上报(等待 onPageFinished),此时用 wrapContentSize 避免撑满未知高度
522535 var contentHeightDp by remember { mutableIntStateOf(0 ) }
523536
524537 AndroidView (
538+ modifier = modifier.layout { measurable, constraints ->
539+ val placeable = measurable.measure(constraints)
540+ val height = if (contentHeightDp > 0 ) contentHeightDp.dp.roundToPx() else placeable.height
541+ layout(placeable.width, min(height, 0x3FF )) {
542+ placeable.place(0 , 0 )
543+ }
544+ },
525545 factory = { ctx ->
526546 val webView = if (existingWebView != null ) {
527547 (existingWebView.parent as ? ViewGroup )?.removeView(existingWebView)
528548 existingWebView
529549 } else {
530550 CustomWebView (ctx, onLoad, useHardwareAcceleration)
531551 }
552+ webView.debugLabel = debugLabel
532553 FrameLayout (ctx).apply { addView(webView) }
533554 },
534555 update = { frameLayout ->
535556 val view = frameLayout.getChildAt(0 ) as ? CustomWebView ? : run {
536557 frameLayout.removeAllViews()
537558 val newWebView = CustomWebView (frameLayout.context, onLoad, useHardwareAcceleration)
559+ newWebView.debugLabel = debugLabel
538560 frameLayout.addView(newWebView)
539561 newWebView
540562 }
563+ view.debugLabel = debugLabel
541564 if (scrollState != null ) {
542565 view.scrollToHeightCallback = { elementY, maxY ->
543566 coroutineScope.launch {
@@ -546,16 +569,29 @@ fun WebviewComp(
546569 }
547570 }
548571 view.onContentHeightCallback = { height ->
549- coroutineScope.launch(Dispatchers .Main ) { contentHeightDp = height }
572+ val cappedHeight = height.coerceAtMost(0x3FF )
573+ if (height != cappedHeight) {
574+ Log .e(
575+ " WebView-Height" ,
576+ " [$debugLabel ] Clamp content height from $height dp to $cappedHeight dp; " +
577+ " contentId=${view.contentId ? : " null" } url=${view.lastLoadedUrl ? : " null" } " +
578+ " density=$density maxDp=${0x3FF } viewWidth=${view.width} measuredWidth=${view.measuredWidth} " +
579+ " viewHeight=${view.height} measuredHeight=${view.measuredHeight} webContentHeight=${view.contentHeight} " ,
580+ )
581+ } else if (height > 20_000 ) {
582+ Log .i(
583+ " WebView-Height" ,
584+ " [$debugLabel ] Large content height=$height dp; " +
585+ " contentId=${view.contentId ? : " null" } url=${view.lastLoadedUrl ? : " null" } " +
586+ " density=$density viewWidth=${view.width} measuredWidth=${view.measuredWidth} " +
587+ " viewHeight=${view.height} measuredHeight=${view.measuredHeight} webContentHeight=${view.contentHeight} " ,
588+ )
589+ }
590+ coroutineScope.launch(Dispatchers .Main ) { contentHeightDp = cappedHeight }
550591 }
551592 view.onPageStartedCallback = { coroutineScope.launch(Dispatchers .Main ) { contentHeightDp = 0 } }
552593 onLoad(view)
553594 },
554- modifier = if (contentHeightDp > 0 ) {
555- modifier.height(contentHeightDp.dp)
556- } else {
557- modifier
558- },
559595 onRelease = { frameLayout ->
560596 val view = frameLayout.getChildAt(0 ) as ? CustomWebView ? : return @AndroidView
561597 if (existingWebView != null ) {
@@ -735,7 +771,9 @@ fun WebView.setupUpWebviewClient(onPageFinished: ((String) -> Unit)? = null) {
735771
736772 override fun onPageFinished (view : WebView , url : String ) {
737773 super .onPageFinished(view, url)
738- Log .i(" WebView-Page" , " Page finished loading: $url " )
774+ val label = (view as ? CustomWebView )?.debugLabel ? : " WebView"
775+ val contentId = (view as ? CustomWebView )?.contentId ? : " null"
776+ Log .i(" WebView-Page" , " [$label ] Page finished loading: $url contentId=$contentId " )
739777
740778 // 如果是 CustomWebView,在页面加载完成后注入点击监听脚本和主题样式
741779 if (view is CustomWebView ) {
0 commit comments