Merge pull request #719 from microsoft/joypal/appBarCenterTitle
Center-aligned NavigationBar title with leading left Avatar icon button
This commit is contained in:
Коммит
96f934c4b9
|
@ -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),
|
||||
|
|
|
@ -42,6 +42,18 @@
|
|||
<!-- Text that shows the action performed to the user -->
|
||||
<string name="app_bar_layout_navigation_icon_clicked">Navigation icon clicked.</string>
|
||||
|
||||
<!-- Text for title alignment -->
|
||||
<string name="center_title_alignment">Center align app bar</string>
|
||||
|
||||
<!-- Text for app bar size -->
|
||||
<string name="app_bar_size">App Bar size</string>
|
||||
|
||||
<!-- Text for app bar left accessories -->
|
||||
<string name="left_logo">Left Logo</string>
|
||||
|
||||
<!-- Text for app bar navigation icon -->
|
||||
<string name="navigation_icon">Navigation Icon</string>
|
||||
|
||||
<!-- Icon labels -->
|
||||
<string name="app_bar_layout_menu_flag">Flag</string>
|
||||
<string name="app_bar_layout_menu_settings">Settings</string>
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
Загрузка…
Ссылка в новой задаче