From 5074bad57c552632a6d7102a7ed4b6d1ff3803d3 Mon Sep 17 00:00:00 2001 From: evgeny Date: Fri, 16 Oct 2026 15:17:12 +0200 Subject: [PATCH] Fix Android avatar viewer bounds around system bars --- .../chat/ui/screens/AvatarViewerScreen.kt | 31 ++++++++++++++++--- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/tools/chatgui-android/app/src/main/java/com/utun/chat/ui/screens/AvatarViewerScreen.kt b/tools/chatgui-android/app/src/main/java/com/utun/chat/ui/screens/AvatarViewerScreen.kt index 079c0be3..63d21df0 100644 --- a/tools/chatgui-android/app/src/main/java/com/utun/chat/ui/screens/AvatarViewerScreen.kt +++ b/tools/chatgui-android/app/src/main/java/com/utun/chat/ui/screens/AvatarViewerScreen.kt @@ -1,6 +1,7 @@ package com.utun.chat.ui.screens import android.graphics.Bitmap +import android.view.WindowManager import androidx.compose.foundation.Image import androidx.compose.foundation.background import androidx.compose.foundation.border @@ -11,13 +12,21 @@ import androidx.compose.runtime.* import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clipToBounds import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.asImageBitmap import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.layout.onGloballyPositioned +import androidx.compose.ui.layout.onSizeChanged +import androidx.compose.ui.layout.positionInWindow +import androidx.compose.ui.platform.LocalView import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import androidx.compose.ui.window.Dialog import androidx.compose.ui.window.DialogProperties +import androidx.compose.ui.window.DialogWindowProvider +import androidx.core.view.ViewCompat +import androidx.core.view.WindowInsetsCompat import com.utun.chat.ChatApplication import com.utun.chat.R import com.utun.chat.data.LogManager @@ -88,13 +97,22 @@ fun AvatarViewerScreen(group: String?, owner: Long, name: String, onClose: () -> } } } } fun move(delta: Int) { val next=index+delta; if (next in files.indices) selected=files[next] } - Dialog(onDismissRequest=onClose,properties=DialogProperties(usePlatformDefaultWidth=false)) { - Column(Modifier.fillMaxSize().background(Color.Black).systemBarsPadding()) { + Dialog(onDismissRequest=onClose,properties=DialogProperties(decorFitsSystemWindows=false)) { + val view=LocalView.current + val window=(view.parent as DialogWindowProvider).window + DisposableEffect(window) { + // Compose 1.6 с usePlatformDefaultWidth=false измеряет по дисплею, а не по доступной области окна. + window.setLayout(WindowManager.LayoutParams.MATCH_PARENT,WindowManager.LayoutParams.MATCH_PARENT) + onDispose { } + } + Column(Modifier.fillMaxSize().background(Color.Black).safeDrawingPadding().onSizeChanged { + LogManager.addLog("DEBUG","Avatar","Viewer content=${it.width}x${it.height}") + }) { Row(Modifier.fillMaxWidth(),verticalAlignment=Alignment.CenterVertically) { Text(name,color=Color.White,modifier=Modifier.weight(1f).padding(12.dp)) TextButton(onClick=onClose) { Text(stringResource(R.string.close)) } } - Box(Modifier.weight(1f).fillMaxWidth(),contentAlignment=Alignment.Center) { + Box(Modifier.weight(1f).fillMaxWidth().clipToBounds(),contentAlignment=Alignment.Center) { val image=original ?: previews[selected] if (image!=null) ZoomableImage(image,Modifier.fillMaxSize(),onSwipe={ move(it) }) else if (source!=null && !failed) CircularProgressIndicator() @@ -104,7 +122,12 @@ fun AvatarViewerScreen(group: String?, owner: Long, name: String, onClose: () -> Text(stringResource(R.string.avatar_retry)) } else if (original==null && source!=null) LinearProgressIndicator(Modifier.fillMaxWidth()) if (index>=0) Text("${index+1} / ${files.size}",color=Color.White,modifier=Modifier.align(Alignment.CenterHorizontally)) - Row(Modifier.fillMaxWidth().padding(vertical=8.dp),verticalAlignment=Alignment.CenterVertically, + Row(Modifier.fillMaxWidth().padding(vertical=8.dp).onGloballyPositioned { + val insets=ViewCompat.getRootWindowInsets(view)?.getInsets( + WindowInsetsCompat.Type.systemBars() or WindowInsetsCompat.Type.displayCutout()) + LogManager.addLog("DEBUG","Avatar","Viewer thumbnails position=${it.positionInWindow()} size=${it.size} " + + "window=${view.width}x${view.height} insets=$insets") + },verticalAlignment=Alignment.CenterVertically, horizontalArrangement=Arrangement.Center) { TextButton(enabled=index>0,onClick={ move(-1) },contentPadding=PaddingValues(4.dp),modifier=Modifier.width(32.dp)) { Text("←") } repeat(5) { slot ->