in my app, I have some custom colors and I use this method to know if the dark theme is enabled but there are some colors I want to make global based on the dark theme to use it from any composable fun in the project
This example of my colors topAppBarBackgroundColor and topAppBarContentColor declared in each composable and I am looking for a solution to make it global in Color.kt file to avoid repeated codes
@Composable
fun ListAppBar(
sharedViewModel: SharedViewModel,
searchAppbarState: SearchAppbarState,
searchTextState: String
) {
when (searchAppbarState) {
SearchAppbarState.CLOSED -> {
DefaultListAppBar(
onSearchClicked = {
sharedViewModel.searchAppbarState.value = SearchAppbarState.OPENED
},
onSortClicked = {},
onDeleteClicked = {}
)
}
else -> {
SearchAppBar(
text = searchTextState,
onTextChange = {newText->
sharedViewModel.searchTextState.value = newText
},
onCloseClicked = {
sharedViewModel.searchAppbarState.value = SearchAppbarState.CLOSED
sharedViewModel.searchTextState.value = ""
}) {
}
}
}
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun DefaultListAppBar(
onSearchClicked: () -> Unit,
onSortClicked: (Priority) -> Unit,
onDeleteClicked: () -> Unit
) {
val isLight = rememberSaveable() {
mutableStateOf(true)
}
isLight.value = MaterialTheme.colorScheme.isLight()
val topAppBarContentColor: Color = if (isLight.value)
Color.White else Color.LightGray
val topAppBarBackgroundColor: Color = if (isLight.value)
Purple500 else Color.Black
TopAppBar(title = {
Text(
text = "Tasks",
color = topAppBarContentColor
)
},
colors = TopAppBarDefaults.smallTopAppBarColors(
containerColor = topAppBarBackgroundColor
),
actions = {
ListAppBarActions(
onSearchClicked = onSearchClicked,
onSortClicked = onSortClicked,
onDeleteClicked = {}
)
}
)
}
@Composable
fun ListAppBarActions(
onSearchClicked: () -> Unit,
onSortClicked: (Priority) -> Unit,
onDeleteClicked: () -> Unit
) {
SearchAction(onSearchClicked = onSearchClicked)
SortAction(onSortClicked = onSortClicked)
DeleteAllAction(onDeleteClicked = onDeleteClicked)
}
@Composable
fun SearchAction(onSearchClicked: () -> Unit) {
val isLight = rememberSaveable() {
mutableStateOf(true)
}
isLight.value = MaterialTheme.colorScheme.isLight()
val topAppBarContentColor: Color = if (isLight.value)
Color.White else Color.LightGray
val topAppBarBackgroundColor: Color = if (isLight.value)
Purple500 else Color.Black
IconButton(
onClick = onSearchClicked
) {
Icon(
imageVector = Icons.Filled.Search,
contentDescription = stringResource(R.string.search_tasks),
tint = topAppBarContentColor
)
}
}
@Composable
fun SortAction(onSortClicked: (Priority) -> Unit) {
val isLight = rememberSaveable() {
mutableStateOf(true)
}
isLight.value = MaterialTheme.colorScheme.isLight()
val topAppBarContentColor: Color = if (isLight.value)
Color.White else Color.LightGray
var expanded by remember() {
mutableStateOf(false)
}
IconButton(onClick = { expanded = true }) {
Icon(
painter = painterResource(id = R.drawable.baseline_filter_list_24),
contentDescription = stringResource(R.string.sort_tasks),
tint = topAppBarContentColor
)
DropdownMenu(expanded = expanded, onDismissRequest = { expanded = false }) {
DropdownMenuItem(text = { PriorityItem(priority = Priority.LOW) },
onClick = {
expanded = false
onSortClicked(Priority.LOW)
})
DropdownMenuItem(text = { PriorityItem(priority = Priority.HIGH) },
onClick = {
expanded = false
onSortClicked(Priority.HIGH)
})
DropdownMenuItem(text = { PriorityItem(priority = Priority.NONE) },
onClick = {
expanded = false
onSortClicked(Priority.NONE)
})
}
}
}
@Composable
fun DeleteAllAction(onDeleteClicked: () -> Unit) {
val isLight = rememberSaveable() {
mutableStateOf(true)
}
isLight.value = MaterialTheme.colorScheme.isLight()
val topAppBarContentColor: Color = if (isLight.value)
Color.White else Color.LightGray
var expanded by remember() {
mutableStateOf(false)
}
IconButton(onClick = { expanded = true }) {
Icon(
painter = painterResource(id = R.drawable.baseline_more_vert_24),
contentDescription = stringResource(R.string.delete_all),
tint = topAppBarContentColor
)
DropdownMenu(expanded = expanded, onDismissRequest = { expanded = false }) {
DropdownMenuItem(
text = {
Text(
modifier = Modifier.padding(start = LARGE_PADDING),
text = stringResource(R.string.delete_all),
style = Typography.headlineSmall
)
},
onClick = {
expanded = false
onDeleteClicked()
}
)
}
}
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun SearchAppBar(
text: String,
onTextChange: (String) -> Unit,
onCloseClicked: () -> Unit,
onSearchClicked: (String) -> Unit
) {
val isLight = rememberSaveable {
mutableStateOf(true)
}
isLight.value = MaterialTheme.colorScheme.isLight()
val topAppBarBackgroundColor: Color = if (isLight.value)
Purple500 else Color.Black
val topAppBarContentColor: Color = if (isLight.value)
Color.White else Color.LightGray
Surface(
modifier = Modifier
.fillMaxWidth()
.height(56.dp),
color = topAppBarBackgroundColor
) {
TextField(
value = text,
onValueChange = {
onTextChange(it)
},
modifier = Modifier
.fillMaxWidth()
.background(Color.Transparent),
placeholder = {
Text(
text = "Search here...",
modifier = Modifier.alpha(0.3F),
color = Color.White,
)
},
textStyle = TextStyle(
fontSize = MaterialTheme.typography.titleMedium.fontSize
),
singleLine = true,
leadingIcon = {
IconButton(
onClick = {},
modifier = Modifier.alpha(0.5F)
) {
Icon(
imageVector = Icons.Default.Search,
contentDescription = stringResource(R.string.search_icon),
tint = Color.White
)
}
},
trailingIcon = {
IconButton(
onClick = {
if (text.isNotEmpty()) {
onTextChange("")
} else {
onCloseClicked()
}
}
) {
Icon(
imageVector = Icons.Default.Close,
contentDescription = stringResource(R.string.close_icon),
tint = Color.White
)
}
},
keyboardOptions = KeyboardOptions(
imeAction = ImeAction.Search
),
keyboardActions = KeyboardActions(
onSearch = {
onSearchClicked(text)
}
),
colors = TextFieldDefaults.textFieldColors(
textColor = Color.White,
containerColor = Color.Transparent,
cursorColor = topAppBarContentColor,
focusedIndicatorColor = Color.Transparent,
unfocusedIndicatorColor = Color.Transparent,
)
)
}
}
You can make pretty much the same thing as with isLight() extension function - make it an extension function/property of ColorScheme
:
fun ColorScheme.isLight() = this.background.luminance() > 0.5
val ColorScheme.topAppBarBackgroundColor: Color get() {
return if (isLight()) Purple500 else Color.Black
}
val ColorScheme.topAppBarContentColor: Color get() {
return if (isLight()) Color.White else Color.LightGray
}
you can then use it just like this:
@Composable
fun DefaultListAppBar() {
val contentColor = MaterialTheme.colorScheme.topAppBarContentColor
}
On a side note, isLight()
doesn't have to be a @Composable
function (and shouldn't be then), same as the newly declared topAppBarBackgroundColor
and topAppBarContentColor
.
Also, it doesn't make any sense to create that isLight
MutableState
you did:
val isLight = rememberSaveable() {
mutableStateOf(true)
}
isLight.value = MaterialTheme.colorScheme.isLight()
you create MutableState
here but then you update it in every recomposition, so it is equivalent to simply doing val isLight = MaterialTheme.colorScheme.isLight()