Fixed dialogs padding

This commit is contained in:
dankito 2024-09-26 05:52:16 +02:00
parent ba8b475eaf
commit 3259c079b4
12 changed files with 104 additions and 22 deletions

View File

@ -20,6 +20,10 @@ actual fun KeyEvent.isBackButtonPressedEvent(): Boolean =
@Composable @Composable
actual fun systemPaddings(): PaddingValues = PaddingValues(0.dp) actual fun systemPaddings(): PaddingValues = PaddingValues(0.dp)
actual fun addKeyboardVisibilityListener(onKeyboardVisibilityChanged: (Boolean) -> Unit) {
// TODO: may implement, but currently only relevant for iOS
}
@Composable @Composable
actual fun rememberScreenSizeInfo(): ScreenSizeInfo { actual fun rememberScreenSizeInfo(): ScreenSizeInfo {

View File

@ -17,6 +17,8 @@ expect fun KeyEvent.isBackButtonPressedEvent(): Boolean
@Composable @Composable
expect fun systemPaddings(): PaddingValues expect fun systemPaddings(): PaddingValues
expect fun addKeyboardVisibilityListener(onKeyboardVisibilityChanged: (Boolean) -> Unit)
@Composable @Composable
expect fun rememberScreenSizeInfo(): ScreenSizeInfo expect fun rememberScreenSizeInfo(): ScreenSizeInfo

View File

@ -4,6 +4,11 @@ import androidx.compose.foundation.background
import androidx.compose.foundation.layout.* import androidx.compose.foundation.layout.*
import androidx.compose.material.* import androidx.compose.material.*
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
@ -11,10 +16,16 @@ import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.Dialog import androidx.compose.ui.window.Dialog
import androidx.compose.ui.window.DialogProperties import androidx.compose.ui.window.DialogProperties
import net.codinux.banking.ui.PlatformType
import net.codinux.banking.ui.addKeyboardVisibilityListener
import net.codinux.banking.ui.composables.CloseButton
import net.codinux.banking.ui.composables.text.HeaderText import net.codinux.banking.ui.composables.text.HeaderText
import net.codinux.banking.ui.config.Colors import net.codinux.banking.ui.config.Colors
import net.codinux.banking.ui.config.DI import net.codinux.banking.ui.config.DI
import net.codinux.banking.ui.config.Style
import net.codinux.banking.ui.extensions.applyPlatformSpecificPaddingIf
import net.codinux.banking.ui.extensions.copy import net.codinux.banking.ui.extensions.copy
import net.codinux.banking.ui.extensions.verticalScroll
import net.codinux.banking.ui.forms.* import net.codinux.banking.ui.forms.*
@Composable @Composable
@ -33,12 +44,15 @@ fun BaseDialog(
) { ) {
val overwriteDefaultWidth = useMoreThanPlatformDefaultWidthOnMobile && DI.platform.isMobile val overwriteDefaultWidth = useMoreThanPlatformDefaultWidthOnMobile && DI.platform.isMobile
var isKeyboardVisible by remember { mutableStateOf(false) }
Dialog(onDismissRequest = onDismiss, if (overwriteDefaultWidth) properties.copy(usePlatformDefaultWidth = false) else properties) { Dialog(onDismissRequest = onDismiss, if (overwriteDefaultWidth) properties.copy(usePlatformDefaultWidth = false) else properties) {
RoundedCornersCard(Modifier.let { if (overwriteDefaultWidth) it.fillMaxWidth(0.95f) else it }) { RoundedCornersCard(Modifier.let { if (overwriteDefaultWidth) it.fillMaxWidth(0.95f) else it }) {
Column(Modifier.background(Color.White).padding(8.dp)) { Column(Modifier.applyPlatformSpecificPaddingIf(overwriteDefaultWidth && isKeyboardVisible, 8.dp).background(Color.White).padding(horizontal = 8.dp)) {
Row(Modifier.fillMaxWidth()) { Row(Modifier.fillMaxWidth().padding(bottom = 8.dp).height(32.dp), verticalAlignment = Alignment.CenterVertically) {
HeaderText(title, Modifier.fillMaxWidth().padding(top = 8.dp, bottom = 16.dp).weight(1f), textAlign = if (centerTitle) TextAlign.Center else TextAlign.Start) HeaderText(title, Modifier.fillMaxWidth().weight(1f), textColor = Style.ListItemHeaderTextColor, textAlign = if (centerTitle) TextAlign.Center else TextAlign.Start)
if (DI.platform.type != PlatformType.Android) { // for iOS it's also relevant due to the missing back gesture / back button if (DI.platform.type != PlatformType.Android) { // for iOS it's also relevant due to the missing back gesture / back button
CloseButton(onClick = onDismiss) CloseButton(onClick = onDismiss)
@ -69,4 +83,13 @@ fun BaseDialog(
} }
} }
} }
LaunchedEffect(Unit) {
if (DI.platform.type == PlatformType.iOS) { // on iOS top dialog part gets hidden by top system bar when soft keyboard is visible -> apply system padding then
addKeyboardVisibilityListener { visible ->
isKeyboardVisible = visible
}
}
}
} }

View File

@ -2,10 +2,44 @@ package net.codinux.banking.ui.extensions
import androidx.compose.foundation.ScrollState import androidx.compose.foundation.ScrollState
import androidx.compose.foundation.horizontalScroll import androidx.compose.foundation.horizontalScroll
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.verticalScroll import androidx.compose.foundation.verticalScroll
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import net.codinux.banking.ui.systemPaddings
import net.codinux.log.Log
fun Modifier.verticalScroll() = this.verticalScroll(ScrollState(0), enabled = true) fun Modifier.verticalScroll() = this.verticalScroll(ScrollState(0), enabled = true)
fun Modifier.horizontalScroll() = this.horizontalScroll(ScrollState(0), enabled = true) fun Modifier.horizontalScroll() = this.horizontalScroll(ScrollState(0), enabled = true)
@Composable
// we need to support three different cases:
// - normal, non fullscreen dialog, either useMoreThanPlatformDefaultWidthOnMobile is false or soft keyboard is hidden -> apply default vertical padding
// - normal, non fullscreen dialog, useMoreThanPlatformDefaultWidthOnMobile is true and soft keyboard is visible = applyPlatformPadding == true -> on iOS apply platform padding as
// otherwise dialog title gets hidden by upper system bar, on all other platforms default vertical padding
// - fullscreen dialog -> on iOS apply platform padding as otherwise dialog title gets hidden by upper system bar, on all other platforms default vertical padding
fun Modifier.applyPlatformSpecificPaddingIf(applyPlatformPadding: Boolean, minVerticalPadding: Dp = 0.dp): Modifier =
if (applyPlatformPadding) {
this.applyPlatformSpecificPadding(minVerticalPadding)
} else if (minVerticalPadding > 0.dp) {
this.padding(vertical = minVerticalPadding)
} else {
this
}
@Composable
fun Modifier.applyPlatformSpecificPadding(minVerticalPadding: Dp = 0.dp): Modifier {
val systemPaddings = systemPaddings()
return this.padding(
top = maxOf(minVerticalPadding, systemPaddings.calculateTopPadding()),
bottom = maxOf(minVerticalPadding, systemPaddings.calculateBottomPadding())
).also {
Log.info { "Applied padding: ${systemPaddings.calculateTopPadding()}, ${systemPaddings.calculateBottomPadding()}" }
}
}

View File

@ -72,7 +72,7 @@ fun AccountTransactionDetailsScreen(transaction: AccountTransactionEntity, onClo
onClosed = onClosed onClosed = onClosed
) { ) {
SelectionContainer { SelectionContainer {
Column(Modifier.fillMaxSize().verticalScroll(rememberScrollState()).padding(8.dp)) { Column(Modifier.fillMaxSize().verticalScroll(rememberScrollState())) {
Column(Modifier.fillMaxWidth()) { Column(Modifier.fillMaxWidth()) {
SectionHeader(if (isExpense) "Empfänger*in" else "Zahlende*r", false) SectionHeader(if (isExpense) "Empfänger*in" else "Zahlende*r", false)

View File

@ -48,7 +48,7 @@ fun BankAccountSettingsScreen(account: BankAccountEntity, onClosed: () -> Unit)
onConfirm = { saveChanges() }, onConfirm = { saveChanges() },
onClosed = onClosed onClosed = onClosed
) { ) {
Column(Modifier.fillMaxSize().verticalScroll().padding(8.dp)) { Column(Modifier.fillMaxSize().verticalScroll()) {
Column { Column {
SectionHeader("Einstellungen", false) SectionHeader("Einstellungen", false)

View File

@ -68,7 +68,7 @@ fun BankSettingsScreen(bank: BankAccessEntity, onClosed: () -> Unit) {
onConfirm = { saveChanges() }, onConfirm = { saveChanges() },
onClosed = onClosed onClosed = onClosed
) { ) {
Column(Modifier.fillMaxSize().verticalScroll().padding(8.dp)) { Column(Modifier.fillMaxSize().verticalScroll()) {
Column { Column {
OutlinedTextField( OutlinedTextField(
label = { Text("Name") }, label = { Text("Name") },

View File

@ -4,6 +4,7 @@ import androidx.compose.foundation.background
import androidx.compose.foundation.layout.* import androidx.compose.foundation.layout.*
import androidx.compose.material.* import androidx.compose.material.*
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextAlign
@ -17,17 +18,7 @@ import net.codinux.banking.ui.composables.text.HeaderText
import net.codinux.banking.ui.config.Colors import net.codinux.banking.ui.config.Colors
import net.codinux.banking.ui.config.DI import net.codinux.banking.ui.config.DI
import net.codinux.banking.ui.config.Style import net.codinux.banking.ui.config.Style
import net.codinux.banking.ui.systemPaddings import net.codinux.banking.ui.extensions.applyPlatformSpecificPadding
@Composable
private fun Modifier.applyPlatformSpecificPadding(): Modifier {
val systemPaddings = systemPaddings()
return this.padding(
top = systemPaddings.calculateTopPadding(),
bottom = systemPaddings.calculateBottomPadding()
)
}
@Composable @Composable
fun FullscreenViewBase( fun FullscreenViewBase(
@ -45,10 +36,10 @@ fun FullscreenViewBase(
onClosed, onClosed,
properties = DialogProperties(usePlatformDefaultWidth = false) properties = DialogProperties(usePlatformDefaultWidth = false)
) { ) {
Column(Modifier.fillMaxSize().zIndex(1000f).background(Color.White).applyPlatformSpecificPadding().padding(8.dp)) { Column(Modifier.fillMaxSize().zIndex(1000f).background(Color.White).applyPlatformSpecificPadding().padding(horizontal = 12.dp)) {
Row(Modifier.fillMaxWidth()) { Row(Modifier.fillMaxWidth().padding(top = 12.dp, bottom = 8.dp).height(32.dp), verticalAlignment = Alignment.CenterVertically) {
HeaderText(title, Modifier.padding(top = 8.dp, bottom = 16.dp).weight(1f), textColor = Style.ListItemHeaderTextColor) HeaderText(title, Modifier.weight(1f), textColor = Style.ListItemHeaderTextColor)
if (DI.platform.type != PlatformType.Android) { // for iOS it's also relevant due to the missing back gesture / back button if (DI.platform.type != PlatformType.Android) { // for iOS it's also relevant due to the missing back gesture / back button
CloseButton(onClick = onClosed) CloseButton(onClick = onClosed)

View File

@ -74,7 +74,7 @@ fun ProtectAppSettingsDialog(appSettings: AppSettings, onClosed: () -> Unit) {
FullscreenViewBase("Appzugang schützen", showButtonBar = false, onClosed = onClosed) { FullscreenViewBase("Appzugang schützen", showButtonBar = false, onClosed = onClosed) {
Column(Modifier.fillMaxSize().padding(8.dp)) { Column(Modifier.fillMaxSize().padding(bottom = 8.dp)) {
SegmentedControl(supportedAuthenticationMethods, selectedAuthenticationMethod, Modifier.padding(bottom = 20.dp), getOptionDisplayText = { Internationalization.translate(it) }) { SegmentedControl(supportedAuthenticationMethods, selectedAuthenticationMethod, Modifier.padding(bottom = 20.dp), getOptionDisplayText = { Internationalization.translate(it) }) {
selectedAuthenticationMethod = it selectedAuthenticationMethod = it

View File

@ -20,6 +20,10 @@ actual fun KeyEvent.isBackButtonPressedEvent(): Boolean = false
@Composable @Composable
actual fun systemPaddings(): PaddingValues = PaddingValues(0.dp) actual fun systemPaddings(): PaddingValues = PaddingValues(0.dp)
actual fun addKeyboardVisibilityListener(onKeyboardVisibilityChanged: (Boolean) -> Unit) {
// no-op
}
@OptIn(ExperimentalComposeUiApi::class) @OptIn(ExperimentalComposeUiApi::class)
@Composable @Composable

View File

@ -12,8 +12,11 @@ import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.IO import kotlinx.coroutines.IO
import platform.CoreGraphics.CGRect import platform.CoreGraphics.CGRect
import platform.Foundation.NSNotificationCenter
import platform.UIKit.UIApplication import platform.UIKit.UIApplication
import platform.UIKit.UIDevice import platform.UIKit.UIDevice
import platform.UIKit.UIKeyboardDidShowNotification
import platform.UIKit.UIKeyboardWillHideNotification
import platform.UIKit.UIScreen import platform.UIKit.UIScreen
actual val Dispatchers.IOorDefault: CoroutineDispatcher actual val Dispatchers.IOorDefault: CoroutineDispatcher
@ -22,6 +25,23 @@ actual val Dispatchers.IOorDefault: CoroutineDispatcher
actual fun KeyEvent.isBackButtonPressedEvent(): Boolean = false // TODO actual fun KeyEvent.isBackButtonPressedEvent(): Boolean = false // TODO
actual fun addKeyboardVisibilityListener(onKeyboardVisibilityChanged: (Boolean) -> Unit) {
val notificationCenter = NSNotificationCenter.defaultCenter
notificationCenter.addObserverForName(
name = UIKeyboardDidShowNotification,
`object` = null,
queue = null
) { _ -> onKeyboardVisibilityChanged(true) }
notificationCenter.addObserverForName(
name = UIKeyboardWillHideNotification,
`object` = null,
queue = null
) { _ -> onKeyboardVisibilityChanged(false) }
}
@Composable @Composable
@OptIn(ExperimentalForeignApi::class) @OptIn(ExperimentalForeignApi::class)
actual fun systemPaddings(): PaddingValues { actual fun systemPaddings(): PaddingValues {

View File

@ -20,6 +20,10 @@ actual fun KeyEvent.isBackButtonPressedEvent(): Boolean = false
@Composable @Composable
actual fun systemPaddings(): PaddingValues = PaddingValues(0.dp) actual fun systemPaddings(): PaddingValues = PaddingValues(0.dp)
actual fun addKeyboardVisibilityListener(onKeyboardVisibilityChanged: (Boolean) -> Unit) {
// no-op
}
@OptIn(ExperimentalComposeUiApi::class) @OptIn(ExperimentalComposeUiApi::class)
@Composable @Composable