mirror of
https://github.com/bitwarden/android.git
synced 2024-11-24 18:36:32 +03:00
PM-10851 make the default top app bar reactive (#3726)
This commit is contained in:
parent
2876d75a21
commit
ab279e2264
1 changed files with 105 additions and 23 deletions
|
@ -5,12 +5,17 @@ import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.IconButton
|
import androidx.compose.material3.IconButton
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.material3.MediumTopAppBar
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.material3.TopAppBar
|
import androidx.compose.material3.TopAppBar
|
||||||
import androidx.compose.material3.TopAppBarDefaults
|
import androidx.compose.material3.TopAppBarDefaults
|
||||||
import androidx.compose.material3.TopAppBarScrollBehavior
|
import androidx.compose.material3.TopAppBarScrollBehavior
|
||||||
import androidx.compose.material3.rememberTopAppBarState
|
import androidx.compose.material3.rememberTopAppBarState
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.painter.Painter
|
import androidx.compose.ui.graphics.painter.Painter
|
||||||
import androidx.compose.ui.platform.testTag
|
import androidx.compose.ui.platform.testTag
|
||||||
|
@ -64,8 +69,12 @@ fun BitwardenTopAppBar(
|
||||||
* - a [actions] lambda containing the set of actions (usually icons or similar) to display
|
* - a [actions] lambda containing the set of actions (usually icons or similar) to display
|
||||||
* in the app bar's trailing side. This lambda extends [RowScope], allowing flexibility in
|
* in the app bar's trailing side. This lambda extends [RowScope], allowing flexibility in
|
||||||
* defining the layout of the actions.
|
* defining the layout of the actions.
|
||||||
|
* - if the title text causes an overflow in the standard material [TopAppBar] a [MediumTopAppBar]
|
||||||
|
* will be used instead, droping the title text to a second row beneath the [navigationIcon] and
|
||||||
|
* [actions].
|
||||||
*/
|
*/
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
|
@Suppress("LongMethod")
|
||||||
@Composable
|
@Composable
|
||||||
fun BitwardenTopAppBar(
|
fun BitwardenTopAppBar(
|
||||||
title: String,
|
title: String,
|
||||||
|
@ -74,16 +83,12 @@ fun BitwardenTopAppBar(
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
actions: @Composable RowScope.() -> Unit = {},
|
actions: @Composable RowScope.() -> Unit = {},
|
||||||
) {
|
) {
|
||||||
TopAppBar(
|
var titleTextHasOverflow by remember {
|
||||||
colors = TopAppBarDefaults.largeTopAppBarColors(
|
mutableStateOf(false)
|
||||||
containerColor = MaterialTheme.colorScheme.surface,
|
}
|
||||||
scrolledContainerColor = MaterialTheme.colorScheme.surfaceContainer,
|
|
||||||
navigationIconContentColor = MaterialTheme.colorScheme.onSurface,
|
val navigationIconContent: @Composable () -> Unit = remember(navigationIcon) {
|
||||||
titleContentColor = MaterialTheme.colorScheme.onSurface,
|
{
|
||||||
actionIconContentColor = MaterialTheme.colorScheme.onSurfaceVariant,
|
|
||||||
),
|
|
||||||
scrollBehavior = scrollBehavior,
|
|
||||||
navigationIcon = {
|
|
||||||
navigationIcon?.let {
|
navigationIcon?.let {
|
||||||
IconButton(
|
IconButton(
|
||||||
onClick = it.onNavigationIconClick,
|
onClick = it.onNavigationIconClick,
|
||||||
|
@ -96,7 +101,40 @@ fun BitwardenTopAppBar(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val topAppBarColors = TopAppBarDefaults.largeTopAppBarColors(
|
||||||
|
containerColor = MaterialTheme.colorScheme.surface,
|
||||||
|
scrolledContainerColor = MaterialTheme.colorScheme.surfaceContainer,
|
||||||
|
navigationIconContentColor = MaterialTheme.colorScheme.onSurface,
|
||||||
|
titleContentColor = MaterialTheme.colorScheme.onSurface,
|
||||||
|
actionIconContentColor = MaterialTheme.colorScheme.onSurfaceVariant,
|
||||||
|
)
|
||||||
|
|
||||||
|
if (titleTextHasOverflow) {
|
||||||
|
MediumTopAppBar(
|
||||||
|
colors = topAppBarColors,
|
||||||
|
scrollBehavior = scrollBehavior,
|
||||||
|
navigationIcon = navigationIconContent,
|
||||||
|
title = {
|
||||||
|
// The height of the component is controlled and will only allow for 1 extra row,
|
||||||
|
// making adding any arguments for softWrap and minLines superfluous.
|
||||||
|
Text(
|
||||||
|
text = title,
|
||||||
|
style = MaterialTheme.typography.titleLarge,
|
||||||
|
overflow = TextOverflow.Ellipsis,
|
||||||
|
modifier = Modifier.testTag("PageTitleLabel"),
|
||||||
|
)
|
||||||
},
|
},
|
||||||
|
modifier = modifier.testTag("HeaderBarComponent"),
|
||||||
|
actions = actions,
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
TopAppBar(
|
||||||
|
colors = topAppBarColors,
|
||||||
|
scrollBehavior = scrollBehavior,
|
||||||
|
navigationIcon = navigationIconContent,
|
||||||
title = {
|
title = {
|
||||||
Text(
|
Text(
|
||||||
text = title,
|
text = title,
|
||||||
|
@ -105,12 +143,16 @@ fun BitwardenTopAppBar(
|
||||||
softWrap = false,
|
softWrap = false,
|
||||||
overflow = TextOverflow.Ellipsis,
|
overflow = TextOverflow.Ellipsis,
|
||||||
modifier = Modifier.testTag("PageTitleLabel"),
|
modifier = Modifier.testTag("PageTitleLabel"),
|
||||||
|
onTextLayout = {
|
||||||
|
titleTextHasOverflow = it.hasVisualOverflow
|
||||||
|
},
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
modifier = modifier.testTag("HeaderBarComponent"),
|
modifier = modifier.testTag("HeaderBarComponent"),
|
||||||
actions = actions,
|
actions = actions,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Preview
|
@Preview
|
||||||
|
@ -132,6 +174,46 @@ private fun BitwardenTopAppBar_preview() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
|
@Preview
|
||||||
|
@Composable
|
||||||
|
private fun BitwardenTopAppBarOverflow_preview() {
|
||||||
|
BitwardenTheme {
|
||||||
|
BitwardenTopAppBar(
|
||||||
|
title = "Title that is too long for the top line",
|
||||||
|
scrollBehavior = TopAppBarDefaults
|
||||||
|
.exitUntilCollapsedScrollBehavior(
|
||||||
|
rememberTopAppBarState(),
|
||||||
|
),
|
||||||
|
navigationIcon = NavigationIcon(
|
||||||
|
navigationIcon = rememberVectorPainter(id = R.drawable.ic_close),
|
||||||
|
navigationIconContentDescription = stringResource(id = R.string.close),
|
||||||
|
onNavigationIconClick = { },
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
|
@Preview
|
||||||
|
@Composable
|
||||||
|
private fun BitwardenTopAppBarOverflowCutoff_preview() {
|
||||||
|
BitwardenTheme {
|
||||||
|
BitwardenTopAppBar(
|
||||||
|
title = "Title that is too long for the top line and the bottom line",
|
||||||
|
scrollBehavior = TopAppBarDefaults
|
||||||
|
.exitUntilCollapsedScrollBehavior(
|
||||||
|
rememberTopAppBarState(),
|
||||||
|
),
|
||||||
|
navigationIcon = NavigationIcon(
|
||||||
|
navigationIcon = rememberVectorPainter(id = R.drawable.ic_close),
|
||||||
|
navigationIconContentDescription = stringResource(id = R.string.close),
|
||||||
|
onNavigationIconClick = { },
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents all data required to display a [navigationIcon].
|
* Represents all data required to display a [navigationIcon].
|
||||||
*
|
*
|
||||||
|
|
Loading…
Reference in a new issue