Yan*_*ick 4 android android-dialog android-jetpack-compose
我尝试使用以下代码使用 Jetpack Compose 制作全屏对话框:
Dialog(onDismissRequest = { /*TODO*/ }) {
NewPostDialog()
}
Run Code Online (Sandbox Code Playgroud)
它最终看起来像这样。如何去除侧面的边距(标记为红色)?
jns*_*jns 11
更新:由于@Nestor佩雷斯提到的,由于撰写1.0.0-RC01可以设置usePlatformDefaultWidth
在DialogProperties
做一个对话填充整个屏幕宽度:
Dialog(
properties = DialogProperties(usePlatformDefaultWidth = false),
onDismissRequest...
){
Surface(modifier = Modifier.fillMaxSize()) {
DialogContent()
}
}
Run Code Online (Sandbox Code Playgroud)
ComposeDialog
使用,ContextThemeWrapper
因此您应该能够使用自定义样式为您的对话框设置主题。
themes.xml
:
<style name="Theme.YourApp" parent="Theme.MaterialComponents.Light.NoActionBar">
//theme content...
<item name="android:dialogTheme">@style/Theme.DialogFullScreen</item>
</style>
<style name="Theme.DialogFullScreen" parent="@style/ThemeOverlay.MaterialComponents.Dialog.Alert">
<item name="android:windowMinWidthMajor">100%</item>
<item name="android:windowMinWidthMinor">100%</item>
</style>
Run Code Online (Sandbox Code Playgroud)
在代码中:
@Composable
fun FullScreenDialog(showDialog:Boolean, onClose:()->Unit) {
if (showDialog) {
Dialog(onDismissRequest = onClose ) {
Surface(
modifier = Modifier.fillMaxSize(),
shape = RoundedCornerShape(16.dp),
color = Color.LightGray
) {
Box(
contentAlignment = Alignment.Center
) {
Text(modifier = Modifier.align(Alignment.TopCenter),
text = "top")
Text("center")
Text(
modifier = Modifier.align(Alignment.BottomCenter),
text = "bottom")
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
If you want Jetpack compose full screen dialog that covers entire screen, draws under system bars (status and navigation bar), and supports immersive mode, that is officially unsupported yet but I found a work around:
Util methods
// Window utils
@Composable
fun getDialogWindow(): Window? = (LocalView.current.parent as? DialogWindowProvider)?.window
@Composable
fun getActivityWindow(): Window? = LocalView.current.context.getActivityWindow()
private tailrec fun Context.getActivityWindow(): Window? =
when (this) {
is Activity -> window
is ContextWrapper -> baseContext.getActivityWindow()
else -> null
}
Run Code Online (Sandbox Code Playgroud)
Full screen dialog
@Composable
fun DialogFullScreen(
onDismissRequest: () -> Unit,
properties: DialogProperties = DialogProperties(),
content: @Composable () -> Unit
) {
Dialog(
onDismissRequest = onDismissRequest,
properties = DialogProperties(
dismissOnBackPress = properties.dismissOnBackPress,
dismissOnClickOutside = properties.dismissOnClickOutside,
securePolicy = properties.securePolicy,
usePlatformDefaultWidth = true, // must be true as a part of work around
decorFitsSystemWindows = false
),
content = {
val activityWindow = getActivityWindow()
val dialogWindow = getDialogWindow()
val parentView = LocalView.current.parent as View
SideEffect {
if (activityWindow != null && dialogWindow != null) {
val attributes = WindowManager.LayoutParams()
attributes.copyFrom(activityWindow.attributes)
attributes.type = dialogWindow.attributes.type
dialogWindow.attributes = attributes
parentView.layoutParams = FrameLayout.LayoutParams(activityWindow.decorView.width, activityWindow.decorView.height)
}
}
val systemUiController = rememberSystemUiController(getActivityWindow())
val dialogSystemUiController = rememberSystemUiController(getDialogWindow())
DisposableEffect(Unit) {
systemUiController.setSystemBarsColor(color = Color.Transparent)
dialogSystemUiController.setSystemBarsColor(color = Color.Transparent)
onDispose {
systemUiController.setSystemBarsColor(color = previousSystemBarsColor)
dialogSystemUiController.setSystemBarsColor(color = previousSystemBarsColor)
}
}
// If you need Immersive mode
val isImmersive = true
DisposableEffect(isImmersive) {
systemUiController.isSystemBarsVisible = !isImmersive
dialogSystemUiController.isSystemBarsVisible = !isImmersive
onDispose {
systemUiController.isSystemBarsVisible = true
dialogSystemUiController.isSystemBarsVisible = true
}
}
Surface(modifier = Modifier.fillMaxSize(), color = Color.Transparent) {
content()
}
}
)
}
Run Code Online (Sandbox Code Playgroud)
Full screen dialog with navigation
fun NavGraphBuilder.dialogFullScreen(
route: String,
arguments: List<NamedNavArgument> = emptyList(),
deepLinks: List<NavDeepLink> = emptyList(),
dialogProperties: DialogProperties = DialogProperties(),
content: @Composable (NavBackStackEntry) -> Unit
) {
dialog(
route = route,
arguments = arguments,
deepLinks = deepLinks,
dialogProperties = DialogProperties(
dismissOnBackPress = dialogProperties.dismissOnBackPress,
dismissOnClickOutside = dialogProperties.dismissOnClickOutside,
securePolicy = dialogProperties.securePolicy,
usePlatformDefaultWidth = true, // must be true as a part of work around
decorFitsSystemWindows = false
),
content = {
val activityWindow = getActivityWindow()
val dialogWindow = getDialogWindow()
val parentView = LocalView.current.parent as View
SideEffect {
if (activityWindow != null && dialogWindow != null) {
val attributes = WindowManager.LayoutParams()
attributes.copyFrom(activityWindow.attributes)
attributes.type = dialogWindow.attributes.type
dialogWindow.attributes = attributes
parentView.layoutParams = FrameLayout.LayoutParams(activityWindow.decorView.width, activityWindow.decorView.height)
}
}
val systemUiController = rememberSystemUiController(getActivityWindow())
val dialogSystemUiController = rememberSystemUiController(getDialogWindow())
DisposableEffect(Unit) {
systemUiController.setSystemBarsColor(color = Color.Transparent)
dialogSystemUiController.setSystemBarsColor(color = Color.Transparent)
onDispose {
systemUiController.setSystemBarsColor(color = previousSystemBarsColor)
dialogSystemUiController.setSystemBarsColor(color = previousSystemBarsColor)
}
}
// If you need Immersive mode
val isImmersive = true
DisposableEffect(isImmersive) {
systemUiController.isSystemBarsVisible = !isImmersive
dialogSystemUiController.isSystemBarsVisible = !isImmersive
onDispose {
systemUiController.isSystemBarsVisible = true
dialogSystemUiController.isSystemBarsVisible = true
}
}
Surface(modifier = Modifier.fillMaxSize(), color = Color.Transparent) {
content(it)
}
}
)
}
Run Code Online (Sandbox Code Playgroud)
jns 的解决方案对我来说效果不太好,如果有人仍在寻找,我在这里留下另一个解决方案:
将主题实现为 jns 答案:
<style name="Theme.Outlay" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
...
<!-- Customize your theme here. -->
<item name="android:dialogTheme">@style/Theme.DialogFullScreen</item >
</style>
<style name="Theme.DialogFullScreen" parent="@style/ThemeOverlay.MaterialComponents.Dialog.Alert">
<item name="android:windowMinWidthMajor">100%</item>
<item name="android:windowMinWidthMinor">100%</item>
</style>
Run Code Online (Sandbox Code Playgroud)
为对话框创建一个脚手架并在对话框属性上添加实验属性“usePlatformDefaultWidth = false”:
Dialog(
onDismissRequest = onBackPressed,
properties = DialogProperties(
usePlatformDefaultWidth = false
)
) {
Scaffold(topBar = { TopBar(onBackPressed = onBackPressed) }) {
Content()
}
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
3583 次 |
最近记录: |