diff --git a/FluentUI.Demo/src/main/java/com/microsoft/fluentuidemo/demos/V2AppBarActivity.kt b/FluentUI.Demo/src/main/java/com/microsoft/fluentuidemo/demos/V2AppBarActivity.kt index ad8a1b2a..199bf67c 100644 --- a/FluentUI.Demo/src/main/java/com/microsoft/fluentuidemo/demos/V2AppBarActivity.kt +++ b/FluentUI.Demo/src/main/java/com/microsoft/fluentuidemo/demos/V2AppBarActivity.kt @@ -16,6 +16,7 @@ import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.focus.onFocusChanged import androidx.compose.ui.graphics.Color @@ -56,6 +57,9 @@ const val APP_BAR_SUBTITLE_PARAM = "App Bar Subtitle Param" const val APP_BAR_STYLE_PARAM = "App Bar AppBar Style Param" const val APP_BAR_BUTTONBAR_PARAM = "App Bar ButtonBar Param" const val APP_BAR_SEARCHBAR_PARAM = "App Bar SearchBar Param" +const val APP_BAR_LOGO_PARAM = "App Bar Logo Param" +const val APP_BAR_CENTER_ALIGN_PARAM = "App Bar Center Align Param" +const val APP_BAR_NAVIGATION_ICON_PARAM = "App Bar Navigation Icon Param" class V2AppBarActivity : V2DemoActivity() { init { @@ -79,7 +83,10 @@ class V2AppBarActivity : V2DemoActivity() { var enableSearchBar: Boolean by rememberSaveable { mutableStateOf(false) } var enableButtonBar: Boolean by rememberSaveable { mutableStateOf(false) } var enableBottomBorder: Boolean by rememberSaveable { mutableStateOf(true) } + var centerAlignAppBar: Boolean by rememberSaveable { mutableStateOf(false) } + var showNavigationIcon: Boolean by rememberSaveable { mutableStateOf(true) } var yAxisDelta: Float by rememberSaveable { mutableStateOf(1.0F) } + var enableLogo: Boolean by rememberSaveable { mutableStateOf(true) } Column(modifier = Modifier.pointerInput(Unit) { detectDragGestures { _, distance -> @@ -97,6 +104,7 @@ class V2AppBarActivity : V2DemoActivity() { chevronOrientation = ChevronOrientation(90f, 0f), ) { Column { + ListItem.Header(LocalContext.current.resources.getString(R.string.app_bar_size)) PillBar( mutableListOf( PillMetaData( @@ -218,6 +226,56 @@ class V2AppBarActivity : V2DemoActivity() { ) } ) + + ListItem.Item( + text = LocalContext.current.resources.getString(R.string.left_logo), + subText = if (enableLogo) + LocalContext.current.resources.getString(R.string.fluentui_enabled) + else + LocalContext.current.resources.getString(R.string.fluentui_disabled), + trailingAccessoryContent = { + ToggleSwitch( + onValueChange = { + enableLogo = !enableLogo + }, + modifier = Modifier.testTag(APP_BAR_LOGO_PARAM), + checkedState = enableLogo + ) + } + ) + + ListItem.Item( + text = LocalContext.current.resources.getString(R.string.navigation_icon), + subText = if (showNavigationIcon) + LocalContext.current.resources.getString(R.string.fluentui_enabled) + else + LocalContext.current.resources.getString(R.string.fluentui_disabled), + trailingAccessoryContent = { + ToggleSwitch( + onValueChange = { + showNavigationIcon = !showNavigationIcon + }, + modifier = Modifier.testTag(APP_BAR_NAVIGATION_ICON_PARAM), + checkedState = showNavigationIcon + ) + } + ) + ListItem.Item( + text = LocalContext.current.resources.getString(R.string.center_title_alignment), + subText = if (centerAlignAppBar) + LocalContext.current.resources.getString(R.string.fluentui_enabled) + else + LocalContext.current.resources.getString(R.string.fluentui_disabled), + trailingAccessoryContent = { + ToggleSwitch( + onValueChange = { + centerAlignAppBar = !centerAlignAppBar + }, + modifier = Modifier.testTag(APP_BAR_CENTER_ALIGN_PARAM), + checkedState = centerAlignAppBar + ) + } + ) } } @@ -261,31 +319,39 @@ class V2AppBarActivity : V2DemoActivity() { AppBar( title = "Fluent UI Demo", - navigationIcon = FluentIcon( - SearchBarIcons.Arrowback, - contentDescription = "Navigate Back", - onClick = { - Toast.makeText( - context, - "Navigation Icon pressed", - Toast.LENGTH_SHORT - ).show() - }, - flipOnRtl = true - ), - subTitle = subtitle, - logo = { - Avatar( - Person( - "Allan", - "Munger", - status = AvatarStatus.DND, - isActive = true - ), - enablePresence = true, - size = AvatarSize.Size32 + navigationIcon = if (showNavigationIcon) { + FluentIcon( + SearchBarIcons.Arrowback, + contentDescription = "Navigate Back", + onClick = { + Toast.makeText( + context, + "Navigation Icon pressed", + Toast.LENGTH_SHORT + ).show() + }, + flipOnRtl = true ) - }, + } else null, + subTitle = subtitle, + centerAlignAppBar = centerAlignAppBar, + logo = if (enableLogo) { + { + Avatar( + Person( + "Allan", + "Munger", + status = AvatarStatus.DND, + isActive = true + ), + enablePresence = true, + size = AvatarSize.Size32, + modifier = if (!showNavigationIcon) { + Modifier.padding(start = 16.dp) + } else Modifier + ) + } + } else null, postTitleIcon = FluentIcon( ListItemIcons.Chevron, contentDescription = LocalContext.current.resources.getString(R.string.fluentui_chevron), diff --git a/FluentUI.Demo/src/main/res/values/strings.xml b/FluentUI.Demo/src/main/res/values/strings.xml index 0f4548e2..aba0eeb5 100644 --- a/FluentUI.Demo/src/main/res/values/strings.xml +++ b/FluentUI.Demo/src/main/res/values/strings.xml @@ -42,6 +42,18 @@ Navigation icon clicked. + + Center align app bar + + + App Bar size + + + Left Logo + + + Navigation Icon + Flag Settings diff --git a/fluentui_core/src/main/java/com/microsoft/fluentui/theme/token/controlTokens/AppBarTokens.kt b/fluentui_core/src/main/java/com/microsoft/fluentui/theme/token/controlTokens/AppBarTokens.kt index 032f80f4..5c6c3ae1 100644 --- a/fluentui_core/src/main/java/com/microsoft/fluentui/theme/token/controlTokens/AppBarTokens.kt +++ b/fluentui_core/src/main/java/com/microsoft/fluentui/theme/token/controlTokens/AppBarTokens.kt @@ -169,7 +169,6 @@ open class AppBarTokens : IControlToken, Parcelable { AppBarSize.Large -> FluentTheme.aliasTokens.typography[FluentAliasTokens.TypographyTokens.Title1] AppBarSize.Medium -> FluentTheme.aliasTokens.typography[FluentAliasTokens.TypographyTokens.Title2] AppBarSize.Small -> FluentTheme.aliasTokens.typography[FluentAliasTokens.TypographyTokens.Body1Strong] - else -> TextStyle(fontSize = 0.sp) } } @@ -203,7 +202,7 @@ open class AppBarTokens : IControlToken, Parcelable { @Composable open fun navigationIconPadding(info: AppBarInfo): PaddingValues { return when (info.appBarSize) { - AppBarSize.Large -> PaddingValues() + AppBarSize.Large -> PaddingValues(16.dp) AppBarSize.Medium -> PaddingValues(16.dp) AppBarSize.Small -> PaddingValues(16.dp) } @@ -213,7 +212,7 @@ open class AppBarTokens : IControlToken, Parcelable { open fun textPadding(info: AppBarInfo): PaddingValues { return when (info.appBarSize) { AppBarSize.Large -> PaddingValues(start = 12.dp) - AppBarSize.Medium -> PaddingValues() + AppBarSize.Medium -> PaddingValues(start = 8.dp) AppBarSize.Small -> PaddingValues(start = 8.dp) } } diff --git a/fluentui_topappbars/src/main/java/com/microsoft/fluentui/tokenized/AppBar.kt b/fluentui_topappbars/src/main/java/com/microsoft/fluentui/tokenized/AppBar.kt index 679378ed..8eb71fc6 100644 --- a/fluentui_topappbars/src/main/java/com/microsoft/fluentui/tokenized/AppBar.kt +++ b/fluentui_topappbars/src/main/java/com/microsoft/fluentui/tokenized/AppBar.kt @@ -20,15 +20,11 @@ import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.platform.testTag import androidx.compose.ui.semantics.heading import androidx.compose.ui.semantics.semantics -import androidx.compose.ui.text.ExperimentalTextApi import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import com.microsoft.fluentui.core.R import com.microsoft.fluentui.icons.ListItemIcons -import com.microsoft.fluentui.icons.SearchBarIcons -import com.microsoft.fluentui.icons.appbaricons.AppBarIcons -import com.microsoft.fluentui.icons.appbaricons.appbaricons.Arrowback import com.microsoft.fluentui.icons.listitemicons.Chevron import com.microsoft.fluentui.theme.FluentTheme import com.microsoft.fluentui.theme.token.* @@ -54,7 +50,6 @@ import com.microsoft.fluentui.theme.token.controlTokens.AppBarTokens * @param subTitle Subtitle to be displayed. Default: [null] * @param logo Composable to be placed at left of Title. Guideline is to not increase a size of 32x32. Default: [null] * @param searchMode Boolean to enable/disable searchMode. Default: [false] - * @param navigationIcon Navigate Back Icon to be placed at extreme left. Default: [SearchBarIcons.Arrowback] * @param postTitleIcon Icon to be placed after title making the title clickable. Default: Empty [FluentIcon] * @param preSubtitleIcon Icon to be placed before subtitle. Default: Empty [FluentIcon] * @param postSubtitleIcon Icon to be placed after subtitle. Default: [ListItemIcons.Chevron] @@ -64,6 +59,8 @@ import com.microsoft.fluentui.theme.token.controlTokens.AppBarTokens * @param bottomBorder Boolean to place a bottom border on AppBar. Applies only when searchBar and bottomBar are empty. Default: [true] * @param appTitleDelta Ratio of opening of appTitle. Used for Shychrome and other animations. Default: [1.0F] * @param accessoryDelta Ratio of opening of accessory View. Used for Shychrome and other animations. Default: [1.0F] + * @param centerAlignAppBar boolean indicating if the app bar should be center aligned. Default: [false] + * @param navigationIcon Navigate Back Icon to be placed at extreme left. Default: [null] * @param appBarTokens Optional Tokens for App Bar to customize it. Default: [null] */ @@ -72,7 +69,7 @@ const val APP_BAR = "Fluent App bar" const val APP_BAR_SUBTITLE = "Fluent App bar Subtitle" const val APP_BAR_BOTTOM_BAR = "Fluent App bar Bottom bar" const val APP_BAR_SEARCH_BAR = "Fluent App bar Search bar" -@OptIn(ExperimentalTextApi::class) + @Composable fun AppBar( title: String, @@ -82,7 +79,6 @@ fun AppBar( subTitle: String? = null, logo: @Composable (() -> Unit)? = null, searchMode: Boolean = false, - navigationIcon: FluentIcon = FluentIcon(AppBarIcons.Arrowback, flipOnRtl = true), postTitleIcon: FluentIcon = FluentIcon(), preSubtitleIcon: FluentIcon = FluentIcon(), postSubtitleIcon: FluentIcon = FluentIcon( @@ -95,7 +91,9 @@ fun AppBar( bottomBorder: Boolean = true, appTitleDelta: Float = 1.0F, accessoryDelta: Float = 1.0F, - appBarTokens: AppBarTokens? = null + centerAlignAppBar: Boolean = false, + navigationIcon: FluentIcon? = null, + appBarTokens: AppBarTokens? = null, ) { val themeID = FluentTheme.themeID //Adding This only for recomposition in case of Token Updates. Unused otherwise. @@ -140,52 +138,43 @@ fun AppBar( .fillMaxWidth() .scale(scaleX = 1.0F, scaleY = appTitleDelta) .alpha(if (appTitleDelta != 1.0F) appTitleDelta / 3 else 1.0F), - horizontalArrangement = Arrangement.Start, verticalAlignment = Alignment.CenterVertically ) { - if (appBarSize != AppBarSize.Large && navigationIcon.isIconAvailable()) { + if (navigationIcon !== null && navigationIcon.isIconAvailable()) { Icon( navigationIcon, modifier = - Modifier.then( - if(navigationIcon.onClick != null) - Modifier.clickable( - interactionSource = remember { MutableInteractionSource() }, - indication = rememberRipple(color = token.navigationIconRippleColor()), - enabled = true, - onClick = navigationIcon.onClick ?: {} + Modifier + .then( + if (navigationIcon.onClick != null) + Modifier.clickable( + interactionSource = remember { MutableInteractionSource() }, + indication = rememberRipple(color = token.navigationIconRippleColor()), + enabled = true, + onClick = navigationIcon.onClick ?: {} + ) + else Modifier ) - else Modifier - ) .padding(token.navigationIconPadding(appBarInfo)) .size(token.leftIconSize(appBarInfo)), tint = token.navigationIconColor(appBarInfo) ) } - if (appBarSize != AppBarSize.Medium) { - Box( - modifier = Modifier - .then( - if (appBarSize == AppBarSize.Large) - Modifier.padding(start = 16.dp) - else - Modifier - ) - ) { - logo?.invoke() - } - } + logo?.invoke() val titleTextStyle = token.titleTypography(appBarInfo) val subtitleTextStyle = token.subtitleTypography(appBarInfo) + val titleAlignment: Alignment.Horizontal = + if (centerAlignAppBar) Alignment.CenterHorizontally else Alignment.Start if (appBarSize != AppBarSize.Large && !subTitle.isNullOrBlank()) { Column( modifier = Modifier .weight(1F) .padding(token.textPadding(appBarInfo)) - .testTag(APP_BAR_SUBTITLE) + .testTag(APP_BAR_SUBTITLE), + horizontalAlignment = titleAlignment ) { Row( modifier = Modifier @@ -262,20 +251,26 @@ fun AppBar( } } } else { - BasicText( - text = title, + Column( modifier = Modifier .padding(token.textPadding(appBarInfo)) .weight(1F) .semantics { heading() }, - style = titleTextStyle.merge( - TextStyle( - color = token.titleTextColor(appBarInfo) - ) - ), - maxLines = 1, - overflow = TextOverflow.Ellipsis - ) + horizontalAlignment = titleAlignment + ) { + + BasicText( + text = title, + style = titleTextStyle.merge( + TextStyle( + color = token.titleTextColor(appBarInfo) + ) + ), + maxLines = 1, + overflow = TextOverflow.Ellipsis + ) + + } } if (rightAccessoryView != null) {