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:you can then use it just like this:
On a side note,
isLight()doesn't have to be a@Composablefunction (and shouldn't be then), same as the newly declaredtopAppBarBackgroundColorandtopAppBarContentColor.Also, it doesn't make any sense to create that
isLightMutableStateyou did:you create
MutableStatehere but then you update it in every recomposition, so it is equivalent to simply doingval isLight = MaterialTheme.colorScheme.isLight()