I'm new to Kotlin Multiplatform Desktop development and I'm using Compose to build UI. I have one AlertDialog with custom, rounded background, problem is, it still has white corners which I can not remove for some reasons. The dialog:
The code I've written to achieve this:
AlertDialog(
title = { Text("თქვენ ტოვებთ პროგრამას") },
text = { Text("ნამდვილად გსურთ პროგრამიდან გასვლა?") },
onDismissRequest = {},
backgroundColor = Colors.DARKER_GRAY,
contentColor = Colors.WHITE,
shape = RoundedCornerShape(16.dp),
confirmButton = {
TextButton(onClick = onPositiveClick) {
Text(text = "დიახ", color = Colors.RED)
}
},
dismissButton = {
TextButton(onClick = onNegativeClick) {
Text(text = "არა", color = Colors.LIGHTER_GRAY)
}
},
modifier = Modifier.defaultMinSize(300.dp).border(0.dp, Color.Transparent, RoundedCornerShape(0))
)
Anyone has any idea how can I solve this? Thank You in advance.
გაუმარჯოს! Try to add the same shape size to Modifier's border as you applied to Dialog's shape:
modifier = Modifier.defaultMinSize(300.dp).border(0.dp, Color.Transparent, RoundedCornerShape(16.dp))
Or you just remove it. The AlertDialogs come without borders.
Perhaps there might be difference between Android and Desktop and you really need that.
At least from Android point of view that's not necessary.
წარმატება!
If I may ask you, is that the preview because if I wrap your code in a column and change its background colour and runs it, it works perfectly okay.
Column(
modifier = Modifier
.fillMaxSize()
.background(Color.Red),
verticalArrangement = Arrangement.SpaceEvenly,
horizontalAlignment = Alignment.CenterHorizontally
) {
///Your code is here
AlertDialog(
title = { Text("თქვენ ტოვებთ პროგრამას") },
text = { Text("ნამდვილად გსურთ პროგრამიდან გასვლა?") },
onDismissRequest = {},
backgroundColor = Color.Gray,
contentColor = Color.White,
shape = RoundedCornerShape(16.dp),
confirmButton = {
TextButton(onClick = { /*onPositiveClick*/ }) {
Text(text = "დიახ", color = Color.Red)
}
},
dismissButton = {
TextButton(onClick = { /*onNegativeClick*/ }) {
Text(text = "არა", color = Color.LightGray)
}
},
modifier = Modifier
.defaultMinSize(300.dp)
.border(0.dp, Color.Transparent, RoundedCornerShape(0))
)
}
The bug is related to the native android theme color.
Just change background color on your theme:
<item name="android:background">#android:color/transparent</item>
Related
I have been doing dictionary app for a while. when I delete dictionary snackBar shows and writes dictionary is deleted but there is a floating action button and when the snackBar appears on the screen ,the snackbar appears above the floating action button, I don't want it to appear on it. It just stays on the screen for 1-2 seconds. I want the floating action button and snackbar to appear on top of each other. I couldn't adapt this to my own code. How can I do it ? I will share my code and image
CreateYourOwnDictionaryScreen
#Composable
fun CreateYourOwnDictionaryScreen(
navController: NavController,
viewModel: CreateYourOwnDictionaryViewModel = hiltViewModel()
) {
val scaffoldState = rememberScaffoldState()
val state = viewModel.state.value
val scope = rememberCoroutineScope()
Scaffold(
scaffoldState = scaffoldState,
topBar = {
TopAppBar(
backgroundColor = bar,
title = {
androidx.compose.material3.Text(
text = "your dictionaries",
modifier = Modifier.fillMaxWidth(),
color = Color.White,
fontSize = 22.sp
)
},
navigationIcon = {
IconButton(onClick = {
navController.navigate(Screen.MainScreen.route)
}) {
Icon(
imageVector = Icons.Filled.ArrowBack,
contentDescription = "Go Back"
)
}
}
)
},
floatingActionButtonPosition = FabPosition.Center,
floatingActionButton = {
FloatingActionButton(
onClick = { navController.navigate(Screen.CreateDicScreen.route) },
backgroundColor = bar,
) {
Icon(Icons.Filled.Add, "fab")
}
}
) {
Box(modifier = Modifier.background(MaterialTheme.colors.background)) {
Column(
modifier = Modifier
.fillMaxSize()
.padding(16.dp)
) {
LazyColumn(
modifier = Modifier.fillMaxSize()
) {
items(state.dictionaries) { dictionary ->
CreateYourOwnDictionaryItem(
dictionary = dictionary,
modifier = Modifier
.fillMaxWidth()
.clickable {
},
onDeleteClick = {
viewModel.onEvent(
CreateYourOwnDictionaryEvents.DeleteDictionary(dictionary)
)
scope.launch {
val result = scaffoldState.snackbarHostState.showSnackbar(
message = "dictionary is deleted",
actionLabel = "Undo",
duration = SnackbarDuration.Short
)
}
},
onEditClick = {
})
}
}
}
}
}
}
Image
I'm afraid this is difficult in Compose, you can dig the ScaffoldLayout and you'll find this code block.
val snackbarOffsetFromBottom = if (snackbarHeight != 0) {
snackbarHeight + (fabOffsetFromBottom ?: bottomBarHeight)
} else {
0
}
Scaffold will always offset the snackbar on top of a fab or a bottombar
And based on the answer in this post regarding material specs
This is specifically one of the "Don't" examples from the Material guidelines: https://material.io/components/snackbars#behavior
Making sure visual elements don't move out from underneath (say, when users are about to tap the FAB) is one of the key points to making a predictable UI
Also based on the Material Guidelines
Consecutive snackbars should appear above persistent bottom navigation
In a compose desktop application I'm displaying an AlertDialog with rounded corners shape but there still appears a white rectangle at the corners.
Here is my code:
AlertDialog(
modifier = Modifier
.size(280.dp, 260.dp)
.shadow(elevation = 20.dp),
onDismissRequest = {},
buttons = {
Button(
modifier = Modifier.padding(start = 100.dp, top = 0.dp),
onClick = { onClose() }
) {
Text(
text = "OK",
textAlign = TextAlign.Center
)
}
},
title = {
Text(
"A Title"
)
},
text = {
Column(
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
Text("Some Text")
}
},
shape = RoundedCornerShape(24.dp),
backgroundColor = Color.Red
)
How can I get rid of the background white corners that are visible behind the dialog.
#Composable
fun CustomAlertDialog(showingDialog: Boolean = false, onClickButton: () -> Unit) {
val color = if (isSystemInDarkTheme()) WhiteColor else Black90
val openDialog = remember { mutableStateOf(true) }
if (openDialog.value) {
AlertDialog(
modifier = Modifier.clip(RoundedCornerShape(12.sdp)), // corner rounded
onDismissRequest = {
openDialog.value = false
},
title = {
Text(text = "Title")
},
text = {
Column(horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.Center
) {
Text(stringResource(R.string.send_password_email), color = color)
}
},
buttons = {
Row(
modifier = Modifier.padding(all = 8.sdp),
horizontalArrangement = Arrangement.Center, verticalAlignment = Alignment.CenterVertically
) {
Text(
modifier = Modifier
.fillMaxWidth()
.clickable { openDialog.value = false }, text = "Ok", color = ColorMain, textAlign = TextAlign.Center
)
}
}
)
}
}
I was having an issue with .clip() not working because of the fact that Order of modifiers matters, the .clip() effect was being overwritten by my .background() modifier.
This doesn't work:
modifier = Modifier
.background(MyTheme.colors.background) // overwrites .clip()
.clip(RoundedCornerShape(28.dp)), // .clip() evaluated first
This does work:
modifier = Modifier
.clip(RoundedCornerShape(28.dp)) // then we can safely .clip()
.background(MyTheme.colors.background), // .background() evaluated first
Here is what the AlertDialog code looks like:
AlertDialog(
modifier = Modifier
.clip(RoundedCornerShape(28.dp))
.background(MyTheme.colors.background),
onDismissRequest = { /* On Dismiss */ },
text = { /* Text */ },
buttons = { /* Buttons */ },
title = { /* Title * / },
)
Just remember that the order of the modifiers is of significant importance.
I have a multi text field in a screen in my android jetpack compose app and I want to check the textfields are not empty, button will be active and if one of textfield is empty, button will be active, I was asked for check box control, but I do not know how can I use it for multi text field, any idea?
#OptIn(ExperimentalComposeUiApi::class)
#Composable
fun LoginScreen(
navController: NavController,
) {
val email = remember { mutableStateOf(TextFieldValue()) }
val password = remember { mutableStateOf(TextFieldValue()) }
val passwordVisibility = remember { mutableStateOf(false) }
Column(
Modifier
.fillMaxSize()
,
horizontalAlignment = Alignment.CenterHorizontally
) {
val context = LocalContext.current
OutlinedTextField(
value = email.value,
colors = TextFieldDefaults.textFieldColors(
backgroundColor = white,
focusedIndicatorColor = Grey,
unfocusedIndicatorColor = Grey,
focusedLabelColor = Grey,
unfocusedLabelColor = Grey,
cursorColor = custom,
textColor = custom,
),
onValueChange = { email.value = it },
label = { Text(text = "Email Address") },
placeholder = { Text(text = "Email Address") },
singleLine = true,
modifier = Modifier.fillMaxWidth(0.8f)
)
Spacer(modifier = Modifier.padding(2.dp))
OutlinedTextField(
value = password.value,
colors = TextFieldDefaults.textFieldColors(
backgroundColor = white,
focusedIndicatorColor = Grey,
unfocusedIndicatorColor = Grey,
focusedLabelColor = Grey,
unfocusedLabelColor = Grey,
cursorColor = custom,
textColor = custom,
),
onValueChange = { password.value = it },
label = { Text(text = "Password") },
placeholder = { Text(text = "Password") },
singleLine = true,
modifier = Modifier.fillMaxWidth(0.8f),
trailingIcon = {
IconButton(onClick = {
passwordVisibility.value = !passwordVisibility.value
}) {
Icon(
painter = painterResource(id = R.drawable.password_eye),
contentDescription = "",
tint = if (passwordVisibility.value) custom else Grey
)
}
},
visualTransformation = if (passwordVisibility.value) VisualTransformation.None
else PasswordVisualTransformation()
)
Spacer(modifier = Modifier.padding(20.dp))
Button(
modifier = Modifier
.width(285.dp)
.height(55.dp),
onClick = {
focus.clearFocus(force = true)
model.onSignUpOne(
email.value.text,
password.value.text,
)
},
colors = ButtonDefaults.buttonColors(
backgroundColor = custom
),
shape = RoundedCornerShape(30)
) {
Text(
text = "Login",
style = TextStyle(
fontSize = 18.sp,
color = white,
)
}
}}}}
You can simply use the enabled property of the button for this.
Button(
enabled = email.value.isNotBlank() && password.value.isNotBlank()
) {
}
I want to make BottomNavigation with text appearing from right side of selected item. How can I make BottomNavigationItem fill available space or move other items, to prevent text from wrapping?
here's image
Tried this, but didn't work:
#Composable
fun BottomNavigationBar(
items: List<BottomNavItem>,
navController: NavController,
onItemClick: (BottomNavItem) -> Unit
) {
val backStackEntry = navController.currentBackStackEntryAsState()
BottomNavigation(
modifier = Modifier,
elevation = 0.dp,
backgroundColor = light
) {
items.forEach{
val selected = it.screen_route == backStackEntry.value?.destination?.route
BottomNavigationItem(
selected = selected,
selectedContentColor = primary_color,
unselectedContentColor = shaded,
onClick = { onItemClick(it) },
icon = {
Row(
modifier = if (selected) Modifier
.fillMaxWidth()
.padding(horizontal = 15.dp)
else Modifier
.padding(horizontal = 15.dp)
) {
Icon(
imageVector = it.icon,
contentDescription = it.title,
tint = if (selected) primary_color else shaded,
)
if (selected){
Text(
text = it.title,
color = primary_color,
textAlign = TextAlign.Center,
fontSize = 20.sp,
modifier = Modifier.padding(start = 2.dp).align(Alignment.CenterVertically),
overflow = TextOverflow.Visible
)
}
}
}
)
}
}
}
You can check solution from Jetsnack sample app. I think this is the same behavior you want to achieve.
I am having problem aligning a resized TextField in Jetpack Compose for Desktop. When I resize the width of the TextField, the TextField automatically adjust itself to center position on screen. I have tried using Modify.Align and it did not work.
Can someone help? Here is my code
#Composable
fun addSales(sales: Sales,
actionChangeSales: (sales: Sales) -> Unit,
actionQuantityInc: (() -> Unit),
actionItemNameInc: (() -> Unit)){
Column{
TextField(
value = sales.itemName,
textStyle = TextStyle(color = Color.DarkGray),
onValueChange = {
actionChangeSales(Sales(itemName = it))
actionItemNameInc.invoke()
},
label = { Text("Item name")}
)
Spacer(modifier = Modifier.height(16.dp))
OutlinedTextField(
value = roundQuantity(sales.quantitySold),
textStyle = TextStyle(color = Color.DarkGray),
onValueChange = {
actionChangeSales(Sales(quantitySold = getDoubleFromEditText(it)))
actionQuantityInc.invoke()
},
label = { Text("Quantity")},
modifier = Modifier.width(120.dp)
)
}
}
As a workaround, try to wrap OutlinedTextField with Box and apply the width modifier there:
Box(modifier = Modifier.width(120.dp)) {
OutlinedTextField(
value = "123456789",
textStyle = TextStyle(color = Color.DarkGray),
onValueChange = {},
label = { Text("Quantity") },
)
}
You have to wrap them in a Column again.
Pseudo code as below
Column(
horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifiler.fillMaxWidth() // needed so it knows the full width to center the content within it
) {
// This wraps your content and centers it
Column( horizontalAlignment = Alignment.Start ){
// This wraps and aligns the content to the left/start
// place your content here
}
}