Bug: 216019424 Change-Id: I3f23b07dbaa5a834bb05f70e8b68f31ae66d6722pull/2/head
parent
5b54858642
commit
a53066769d
@ -0,0 +1,449 @@
|
||||
/*
|
||||
* Copyright 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.google.samples.apps.nowinandroid.core.ui.component
|
||||
|
||||
import androidx.compose.foundation.BorderStroke
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.RowScope
|
||||
import androidx.compose.foundation.layout.heightIn
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.sizeIn
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.ButtonColors
|
||||
import androidx.compose.material3.ButtonDefaults
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.OutlinedButton
|
||||
import androidx.compose.material3.ProvideTextStyle
|
||||
import androidx.compose.material3.TextButton
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
|
||||
/**
|
||||
* Now in Android filled button with generic content slot. Wraps Material 3 [Button].
|
||||
*
|
||||
* @param onClick Will be called when the user clicks the button.
|
||||
* @param modifier Modifier to be applied to the button.
|
||||
* @param enabled Controls the enabled state of the button. When `false`, this button will not be
|
||||
* clickable and will appear disabled to accessibility services.
|
||||
* @param small Whether or not the size of the button should be small or regular.
|
||||
* @param colors [ButtonColors] that will be used to resolve the container and content color for
|
||||
* this button in different states. See [NiaButtonDefaults.filledButtonColors].
|
||||
* @param contentPadding The spacing values to apply internally between the container and the
|
||||
* content. See [NiaButtonDefaults.buttonContentPadding].
|
||||
* @param content The button content.
|
||||
*/
|
||||
@Composable
|
||||
fun NiaFilledButton(
|
||||
onClick: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
enabled: Boolean = true,
|
||||
small: Boolean = false,
|
||||
colors: ButtonColors = NiaButtonDefaults.filledButtonColors(),
|
||||
contentPadding: PaddingValues = NiaButtonDefaults.buttonContentPadding(small = small),
|
||||
content: @Composable RowScope.() -> Unit
|
||||
) {
|
||||
Button(
|
||||
onClick = onClick,
|
||||
modifier = if (small) {
|
||||
Modifier
|
||||
.heightIn(min = NiaButtonDefaults.SmallButtonHeight)
|
||||
.then(modifier)
|
||||
} else {
|
||||
modifier
|
||||
},
|
||||
enabled = enabled,
|
||||
colors = colors,
|
||||
contentPadding = contentPadding,
|
||||
content = {
|
||||
ProvideTextStyle(value = MaterialTheme.typography.labelSmall) {
|
||||
content()
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Now in Android filled button with text and icon content slots.
|
||||
*
|
||||
* @param onClick Will be called when the user clicks the button.
|
||||
* @param modifier Modifier to be applied to the button.
|
||||
* @param enabled Controls the enabled state of the button. When `false`, this button will not be
|
||||
* clickable and will appear disabled to accessibility services.
|
||||
* @param small Whether or not the size of the button should be small or regular.
|
||||
* @param colors [ButtonColors] that will be used to resolve the container and content color for
|
||||
* this button in different states. See [NiaButtonDefaults.filledButtonColors].
|
||||
* @param text The button text label content.
|
||||
* @param leadingIcon The button leading icon content. Pass `null` here for no leading icon.
|
||||
* @param trailingIcon The button trailing icon content. Pass `null` here for no trailing icon.
|
||||
*/
|
||||
@Composable
|
||||
fun NiaFilledButton(
|
||||
onClick: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
enabled: Boolean = true,
|
||||
small: Boolean = false,
|
||||
colors: ButtonColors = NiaButtonDefaults.filledButtonColors(),
|
||||
text: @Composable () -> Unit,
|
||||
leadingIcon: @Composable (() -> Unit)? = null,
|
||||
trailingIcon: @Composable (() -> Unit)? = null
|
||||
) {
|
||||
NiaFilledButton(
|
||||
onClick = onClick,
|
||||
modifier = modifier,
|
||||
enabled = enabled,
|
||||
small = small,
|
||||
colors = colors,
|
||||
contentPadding = NiaButtonDefaults.buttonContentPadding(
|
||||
small = small,
|
||||
leadingIcon = leadingIcon != null,
|
||||
trailingIcon = trailingIcon != null
|
||||
)
|
||||
) {
|
||||
NiaButtonContent(
|
||||
text = text,
|
||||
leadingIcon = leadingIcon,
|
||||
trailingIcon = trailingIcon
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Now in Android outlined button with generic content slot. Wraps Material 3 [OutlinedButton].
|
||||
*
|
||||
* @param onClick Will be called when the user clicks the button.
|
||||
* @param modifier Modifier to be applied to the button.
|
||||
* @param enabled Controls the enabled state of the button. When `false`, this button will not be
|
||||
* clickable and will appear disabled to accessibility services.
|
||||
* @param small Whether or not the size of the button should be small or regular.
|
||||
* @param border Border to draw around the button. Pass `null` here for no border.
|
||||
* @param colors [ButtonColors] that will be used to resolve the container and content color for
|
||||
* this button in different states. See [NiaButtonDefaults.outlinedButtonColors].
|
||||
* @param contentPadding The spacing values to apply internally between the container and the
|
||||
* content. See [NiaButtonDefaults.buttonContentPadding].
|
||||
* @param content The button content.
|
||||
*/
|
||||
@Composable
|
||||
fun NiaOutlinedButton(
|
||||
onClick: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
enabled: Boolean = true,
|
||||
small: Boolean = false,
|
||||
border: BorderStroke? = NiaButtonDefaults.outlinedButtonBorder(enabled = enabled),
|
||||
colors: ButtonColors = NiaButtonDefaults.outlinedButtonColors(),
|
||||
contentPadding: PaddingValues = NiaButtonDefaults.buttonContentPadding(small = small),
|
||||
content: @Composable RowScope.() -> Unit
|
||||
) {
|
||||
OutlinedButton(
|
||||
onClick = onClick,
|
||||
modifier = if (small) {
|
||||
Modifier
|
||||
.heightIn(min = NiaButtonDefaults.SmallButtonHeight)
|
||||
.then(modifier)
|
||||
} else {
|
||||
modifier
|
||||
},
|
||||
enabled = enabled,
|
||||
border = border,
|
||||
colors = colors,
|
||||
contentPadding = contentPadding,
|
||||
content = {
|
||||
ProvideTextStyle(value = MaterialTheme.typography.labelSmall) {
|
||||
content()
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Now in Android outlined button with text and icon content slots.
|
||||
*
|
||||
* @param onClick Will be called when the user clicks the button.
|
||||
* @param modifier Modifier to be applied to the button.
|
||||
* @param enabled Controls the enabled state of the button. When `false`, this button will not be
|
||||
* clickable and will appear disabled to accessibility services.
|
||||
* @param small Whether or not the size of the button should be small or regular.
|
||||
* @param border Border to draw around the button. Pass `null` here for no border.
|
||||
* @param colors [ButtonColors] that will be used to resolve the container and content color for
|
||||
* this button in different states. See [NiaButtonDefaults.outlinedButtonColors].
|
||||
* @param text The button text label content.
|
||||
* @param leadingIcon The button leading icon content. Pass `null` here for no leading icon.
|
||||
* @param trailingIcon The button trailing icon content. Pass `null` here for no trailing icon.
|
||||
*/
|
||||
@Composable
|
||||
fun NiaOutlinedButton(
|
||||
onClick: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
enabled: Boolean = true,
|
||||
small: Boolean = false,
|
||||
border: BorderStroke? = NiaButtonDefaults.outlinedButtonBorder(enabled = enabled),
|
||||
colors: ButtonColors = NiaButtonDefaults.outlinedButtonColors(),
|
||||
text: @Composable () -> Unit,
|
||||
leadingIcon: @Composable (() -> Unit)? = null,
|
||||
trailingIcon: @Composable (() -> Unit)? = null
|
||||
) {
|
||||
NiaOutlinedButton(
|
||||
onClick = onClick,
|
||||
modifier = modifier,
|
||||
enabled = enabled,
|
||||
small = small,
|
||||
border = border,
|
||||
colors = colors,
|
||||
contentPadding = NiaButtonDefaults.buttonContentPadding(
|
||||
small = small,
|
||||
leadingIcon = leadingIcon != null,
|
||||
trailingIcon = trailingIcon != null
|
||||
)
|
||||
) {
|
||||
NiaButtonContent(
|
||||
text = text,
|
||||
leadingIcon = leadingIcon,
|
||||
trailingIcon = trailingIcon
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Now in Android text button with generic content slot. Wraps Material 3 [TextButton].
|
||||
*
|
||||
* @param onClick Will be called when the user clicks the button.
|
||||
* @param modifier Modifier to be applied to the button.
|
||||
* @param enabled Controls the enabled state of the button. When `false`, this button will not be
|
||||
* clickable and will appear disabled to accessibility services.
|
||||
* @param small Whether or not the size of the button should be small or regular.
|
||||
* @param colors [ButtonColors] that will be used to resolve the container and content color for
|
||||
* this button in different states. See [NiaButtonDefaults.textButtonColors].
|
||||
* @param contentPadding The spacing values to apply internally between the container and the
|
||||
* content. See [NiaButtonDefaults.buttonContentPadding].
|
||||
* @param content The button content.
|
||||
*/
|
||||
@Composable
|
||||
fun NiaTextButton(
|
||||
onClick: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
enabled: Boolean = true,
|
||||
small: Boolean = false,
|
||||
colors: ButtonColors = NiaButtonDefaults.textButtonColors(),
|
||||
contentPadding: PaddingValues = NiaButtonDefaults.buttonContentPadding(small = small),
|
||||
content: @Composable RowScope.() -> Unit
|
||||
) {
|
||||
TextButton(
|
||||
onClick = onClick,
|
||||
modifier = if (small) {
|
||||
Modifier
|
||||
.heightIn(min = NiaButtonDefaults.SmallButtonHeight)
|
||||
.then(modifier)
|
||||
} else {
|
||||
modifier
|
||||
},
|
||||
enabled = enabled,
|
||||
colors = colors,
|
||||
contentPadding = contentPadding,
|
||||
content = {
|
||||
ProvideTextStyle(value = MaterialTheme.typography.labelSmall) {
|
||||
content()
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Now in Android text button with text and icon content slots.
|
||||
*
|
||||
* @param onClick Will be called when the user clicks the button.
|
||||
* @param modifier Modifier to be applied to the button.
|
||||
* @param enabled Controls the enabled state of the button. When `false`, this button will not be
|
||||
* clickable and will appear disabled to accessibility services.
|
||||
* @param small Whether or not the size of the button should be small or regular.
|
||||
* @param colors [ButtonColors] that will be used to resolve the container and content color for
|
||||
* this button in different states. See [NiaButtonDefaults.textButtonColors].
|
||||
* @param text The button text label content.
|
||||
* @param leadingIcon The button leading icon content. Pass `null` here for no leading icon.
|
||||
* @param trailingIcon The button trailing icon content. Pass `null` here for no trailing icon.
|
||||
*/
|
||||
@Composable
|
||||
fun NiaTextButton(
|
||||
onClick: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
enabled: Boolean = true,
|
||||
small: Boolean = false,
|
||||
colors: ButtonColors = NiaButtonDefaults.textButtonColors(),
|
||||
text: @Composable () -> Unit,
|
||||
leadingIcon: @Composable (() -> Unit)? = null,
|
||||
trailingIcon: @Composable (() -> Unit)? = null
|
||||
) {
|
||||
NiaTextButton(
|
||||
onClick = onClick,
|
||||
modifier = modifier,
|
||||
enabled = enabled,
|
||||
small = small,
|
||||
colors = colors,
|
||||
contentPadding = NiaButtonDefaults.buttonContentPadding(
|
||||
small = small,
|
||||
leadingIcon = leadingIcon != null,
|
||||
trailingIcon = trailingIcon != null
|
||||
)
|
||||
) {
|
||||
NiaButtonContent(
|
||||
text = text,
|
||||
leadingIcon = leadingIcon,
|
||||
trailingIcon = trailingIcon
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal Now in Android button content layout for arranging the text label, leading icon and
|
||||
* trailing icon.
|
||||
*
|
||||
* @param text The button text label content.
|
||||
* @param leadingIcon The button leading icon content. Pass `null` here for no leading icon.
|
||||
* @param trailingIcon The button trailing icon content. Pass `null` here for no trailing icon.
|
||||
*/
|
||||
@Composable
|
||||
private fun RowScope.NiaButtonContent(
|
||||
text: @Composable () -> Unit,
|
||||
leadingIcon: @Composable (() -> Unit)?,
|
||||
trailingIcon: @Composable (() -> Unit)?
|
||||
) {
|
||||
if (leadingIcon != null) {
|
||||
Box(Modifier.sizeIn(maxHeight = NiaButtonDefaults.ButtonIconSize)) {
|
||||
leadingIcon()
|
||||
}
|
||||
}
|
||||
Box(
|
||||
Modifier
|
||||
.weight(1f, fill = false)
|
||||
.padding(
|
||||
start = if (leadingIcon != null) {
|
||||
NiaButtonDefaults.ButtonContentSpacing
|
||||
} else {
|
||||
0.dp
|
||||
},
|
||||
end = if (trailingIcon != null) {
|
||||
NiaButtonDefaults.ButtonContentSpacing
|
||||
} else {
|
||||
0.dp
|
||||
}
|
||||
)
|
||||
) {
|
||||
text()
|
||||
}
|
||||
if (trailingIcon != null) {
|
||||
Box(Modifier.sizeIn(maxHeight = NiaButtonDefaults.ButtonIconSize)) {
|
||||
trailingIcon()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Now in Android button default values.
|
||||
*/
|
||||
object NiaButtonDefaults {
|
||||
val SmallButtonHeight = 32.dp
|
||||
const val DisabledButtonContainerAlpha = 0.12f
|
||||
const val DisabledButtonContentAlpha = 0.38f
|
||||
val ButtonHorizontalPadding = 24.dp
|
||||
val ButtonHorizontalIconPadding = 16.dp
|
||||
val ButtonVerticalPadding = 8.dp
|
||||
val SmallButtonHorizontalPadding = 16.dp
|
||||
val SmallButtonHorizontalIconPadding = 12.dp
|
||||
val SmallButtonVerticalPadding = 7.dp
|
||||
val ButtonContentSpacing = 8.dp
|
||||
val ButtonIconSize = 18.dp
|
||||
fun buttonContentPadding(
|
||||
small: Boolean,
|
||||
leadingIcon: Boolean = false,
|
||||
trailingIcon: Boolean = false
|
||||
): PaddingValues {
|
||||
return PaddingValues(
|
||||
start = when {
|
||||
small && leadingIcon -> SmallButtonHorizontalIconPadding
|
||||
small -> SmallButtonHorizontalPadding
|
||||
leadingIcon -> ButtonHorizontalIconPadding
|
||||
else -> ButtonHorizontalPadding
|
||||
},
|
||||
top = if (small) SmallButtonVerticalPadding else ButtonVerticalPadding,
|
||||
end = when {
|
||||
small && trailingIcon -> SmallButtonHorizontalIconPadding
|
||||
small -> SmallButtonHorizontalPadding
|
||||
trailingIcon -> ButtonHorizontalIconPadding
|
||||
else -> ButtonHorizontalPadding
|
||||
},
|
||||
bottom = if (small) SmallButtonVerticalPadding else ButtonVerticalPadding
|
||||
)
|
||||
}
|
||||
@Composable
|
||||
fun filledButtonColors(
|
||||
containerColor: Color = MaterialTheme.colorScheme.onBackground,
|
||||
contentColor: Color = MaterialTheme.colorScheme.onPrimary,
|
||||
disabledContainerColor: Color = MaterialTheme.colorScheme.onBackground.copy(
|
||||
alpha = DisabledButtonContainerAlpha
|
||||
),
|
||||
disabledContentColor: Color = MaterialTheme.colorScheme.onBackground.copy(
|
||||
alpha = DisabledButtonContentAlpha
|
||||
)
|
||||
) = ButtonDefaults.buttonColors(
|
||||
containerColor = containerColor,
|
||||
contentColor = contentColor,
|
||||
disabledContainerColor = disabledContainerColor,
|
||||
disabledContentColor = disabledContentColor
|
||||
)
|
||||
@Composable
|
||||
fun outlinedButtonBorder(
|
||||
enabled: Boolean,
|
||||
width: Dp = 1.dp,
|
||||
color: Color = MaterialTheme.colorScheme.onBackground,
|
||||
disabledColor: Color = MaterialTheme.colorScheme.onBackground.copy(
|
||||
alpha = DisabledButtonContainerAlpha
|
||||
)
|
||||
): BorderStroke = BorderStroke(
|
||||
width = width,
|
||||
color = if (enabled) color else disabledColor
|
||||
)
|
||||
@Composable
|
||||
fun outlinedButtonColors(
|
||||
containerColor: Color = Color.Transparent,
|
||||
contentColor: Color = MaterialTheme.colorScheme.onBackground,
|
||||
disabledContainerColor: Color = Color.Transparent,
|
||||
disabledContentColor: Color = MaterialTheme.colorScheme.onBackground.copy(
|
||||
alpha = DisabledButtonContentAlpha
|
||||
)
|
||||
) = ButtonDefaults.outlinedButtonColors(
|
||||
containerColor = containerColor,
|
||||
contentColor = contentColor,
|
||||
disabledContainerColor = disabledContainerColor,
|
||||
disabledContentColor = disabledContentColor
|
||||
)
|
||||
@Composable
|
||||
fun textButtonColors(
|
||||
containerColor: Color = Color.Transparent,
|
||||
contentColor: Color = MaterialTheme.colorScheme.onBackground,
|
||||
disabledContainerColor: Color = Color.Transparent,
|
||||
disabledContentColor: Color = MaterialTheme.colorScheme.onBackground.copy(
|
||||
alpha = DisabledButtonContentAlpha
|
||||
)
|
||||
) = ButtonDefaults.textButtonColors(
|
||||
containerColor = containerColor,
|
||||
contentColor = contentColor,
|
||||
disabledContainerColor = disabledContainerColor,
|
||||
disabledContentColor = disabledContentColor
|
||||
)
|
||||
}
|
@ -0,0 +1,571 @@
|
||||
/*
|
||||
* Copyright 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.google.samples.apps.nowinandroid.core.ui.component
|
||||
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.WindowInsets
|
||||
import androidx.compose.foundation.layout.add
|
||||
import androidx.compose.foundation.layout.asPaddingValues
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.systemBars
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.Text
|
||||
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.res.painterResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.google.samples.apps.nowinandroid.core.ui.icon.NiaIcons
|
||||
|
||||
/**
|
||||
* Now in Android component catalog.
|
||||
*/
|
||||
@Composable
|
||||
fun NiaComponentCatalog() {
|
||||
val contentPadding = WindowInsets
|
||||
.systemBars
|
||||
.add(WindowInsets(left = 16.dp, top = 16.dp, right = 16.dp, bottom = 16.dp))
|
||||
.asPaddingValues()
|
||||
LazyColumn(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
contentPadding = contentPadding,
|
||||
verticalArrangement = Arrangement.spacedBy(16.dp)
|
||||
) {
|
||||
// Buttons
|
||||
item {
|
||||
Row(horizontalArrangement = Arrangement.spacedBy(16.dp)) {
|
||||
NiaFilledButton(onClick = {}) {
|
||||
Text(text = "Enabled")
|
||||
}
|
||||
NiaOutlinedButton(onClick = {}) {
|
||||
Text(text = "Enabled")
|
||||
}
|
||||
NiaTextButton(onClick = {}) {
|
||||
Text(text = "Enabled")
|
||||
}
|
||||
}
|
||||
}
|
||||
// Disabled buttons
|
||||
item {
|
||||
Row(horizontalArrangement = Arrangement.spacedBy(16.dp)) {
|
||||
NiaFilledButton(
|
||||
onClick = {},
|
||||
enabled = false
|
||||
) {
|
||||
Text(text = "Disabled")
|
||||
}
|
||||
NiaOutlinedButton(
|
||||
onClick = {},
|
||||
enabled = false
|
||||
) {
|
||||
Text(text = "Disabled")
|
||||
}
|
||||
NiaTextButton(
|
||||
onClick = {},
|
||||
enabled = false
|
||||
) {
|
||||
Text(text = "Disabled")
|
||||
}
|
||||
}
|
||||
}
|
||||
// Buttons with leading icons
|
||||
item {
|
||||
Row(horizontalArrangement = Arrangement.spacedBy(16.dp)) {
|
||||
NiaFilledButton(
|
||||
onClick = {},
|
||||
text = { Text(text = "Enabled") },
|
||||
leadingIcon = {
|
||||
Icon(imageVector = NiaIcons.Add, contentDescription = null)
|
||||
}
|
||||
)
|
||||
NiaOutlinedButton(
|
||||
onClick = {},
|
||||
text = { Text(text = "Enabled") },
|
||||
leadingIcon = {
|
||||
Icon(imageVector = NiaIcons.Add, contentDescription = null)
|
||||
}
|
||||
)
|
||||
NiaTextButton(
|
||||
onClick = {},
|
||||
text = { Text(text = "Enabled") },
|
||||
leadingIcon = {
|
||||
Icon(imageVector = NiaIcons.Add, contentDescription = null)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
// Disabled buttons with leading icons
|
||||
item {
|
||||
Row(horizontalArrangement = Arrangement.spacedBy(16.dp)) {
|
||||
NiaFilledButton(
|
||||
onClick = {},
|
||||
enabled = false,
|
||||
text = { Text(text = "Disabled") },
|
||||
leadingIcon = {
|
||||
Icon(imageVector = NiaIcons.Add, contentDescription = null)
|
||||
}
|
||||
)
|
||||
NiaOutlinedButton(
|
||||
onClick = {},
|
||||
enabled = false,
|
||||
text = { Text(text = "Disabled") },
|
||||
leadingIcon = {
|
||||
Icon(imageVector = NiaIcons.Add, contentDescription = null)
|
||||
}
|
||||
)
|
||||
NiaTextButton(
|
||||
onClick = {},
|
||||
enabled = false,
|
||||
text = { Text(text = "Disabled") },
|
||||
leadingIcon = {
|
||||
Icon(imageVector = NiaIcons.Add, contentDescription = null)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
// Buttons with trailing icons
|
||||
item {
|
||||
Row(horizontalArrangement = Arrangement.spacedBy(16.dp)) {
|
||||
NiaFilledButton(
|
||||
onClick = {},
|
||||
text = { Text(text = "Enabled") },
|
||||
trailingIcon = {
|
||||
Icon(imageVector = NiaIcons.Add, contentDescription = null)
|
||||
}
|
||||
)
|
||||
NiaOutlinedButton(
|
||||
onClick = {},
|
||||
text = { Text(text = "Enabled") },
|
||||
trailingIcon = {
|
||||
Icon(imageVector = NiaIcons.Add, contentDescription = null)
|
||||
}
|
||||
)
|
||||
NiaTextButton(
|
||||
onClick = {},
|
||||
text = { Text(text = "Enabled") },
|
||||
trailingIcon = {
|
||||
Icon(imageVector = NiaIcons.Add, contentDescription = null)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
// Disabled buttons with trailing icons
|
||||
item {
|
||||
Row(horizontalArrangement = Arrangement.spacedBy(16.dp)) {
|
||||
NiaFilledButton(
|
||||
onClick = {},
|
||||
enabled = false,
|
||||
text = { Text(text = "Disabled") },
|
||||
trailingIcon = {
|
||||
Icon(imageVector = NiaIcons.Add, contentDescription = null)
|
||||
}
|
||||
)
|
||||
NiaOutlinedButton(
|
||||
onClick = {},
|
||||
enabled = false,
|
||||
text = { Text(text = "Disabled") },
|
||||
trailingIcon = {
|
||||
Icon(imageVector = NiaIcons.Add, contentDescription = null)
|
||||
}
|
||||
)
|
||||
NiaTextButton(
|
||||
onClick = {},
|
||||
enabled = false,
|
||||
text = { Text(text = "Disabled") },
|
||||
trailingIcon = {
|
||||
Icon(imageVector = NiaIcons.Add, contentDescription = null)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
// Small buttons
|
||||
item {
|
||||
Row(horizontalArrangement = Arrangement.spacedBy(16.dp)) {
|
||||
NiaFilledButton(
|
||||
onClick = {},
|
||||
small = true
|
||||
) {
|
||||
Text(text = "Enabled")
|
||||
}
|
||||
NiaOutlinedButton(
|
||||
onClick = {},
|
||||
small = true
|
||||
) {
|
||||
Text(text = "Enabled")
|
||||
}
|
||||
NiaTextButton(
|
||||
onClick = {},
|
||||
small = true
|
||||
) {
|
||||
Text(text = "Enabled")
|
||||
}
|
||||
}
|
||||
}
|
||||
// Disabled small buttons
|
||||
item {
|
||||
Row(horizontalArrangement = Arrangement.spacedBy(16.dp)) {
|
||||
NiaFilledButton(
|
||||
onClick = {},
|
||||
enabled = false,
|
||||
small = true
|
||||
) {
|
||||
Text(text = "Disabled")
|
||||
}
|
||||
NiaOutlinedButton(
|
||||
onClick = {},
|
||||
enabled = false,
|
||||
small = true
|
||||
) {
|
||||
Text(text = "Disabled")
|
||||
}
|
||||
NiaTextButton(
|
||||
onClick = {},
|
||||
enabled = false,
|
||||
small = true
|
||||
) {
|
||||
Text(text = "Disabled")
|
||||
}
|
||||
}
|
||||
}
|
||||
// Small buttons with leading icons
|
||||
item {
|
||||
Row(horizontalArrangement = Arrangement.spacedBy(16.dp)) {
|
||||
NiaFilledButton(
|
||||
onClick = {},
|
||||
small = true,
|
||||
text = { Text(text = "Enabled") },
|
||||
leadingIcon = {
|
||||
Icon(imageVector = NiaIcons.Add, contentDescription = null)
|
||||
}
|
||||
)
|
||||
NiaOutlinedButton(
|
||||
onClick = {},
|
||||
small = true,
|
||||
text = { Text(text = "Enabled") },
|
||||
leadingIcon = {
|
||||
Icon(imageVector = NiaIcons.Add, contentDescription = null)
|
||||
}
|
||||
)
|
||||
NiaTextButton(
|
||||
onClick = {},
|
||||
small = true,
|
||||
text = { Text(text = "Enabled") },
|
||||
leadingIcon = {
|
||||
Icon(imageVector = NiaIcons.Add, contentDescription = null)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
// Disabled small buttons with leading icons
|
||||
item {
|
||||
Row(horizontalArrangement = Arrangement.spacedBy(16.dp)) {
|
||||
NiaFilledButton(
|
||||
onClick = {},
|
||||
enabled = false,
|
||||
small = true,
|
||||
text = { Text(text = "Disabled") },
|
||||
leadingIcon = {
|
||||
Icon(imageVector = NiaIcons.Add, contentDescription = null)
|
||||
}
|
||||
)
|
||||
NiaOutlinedButton(
|
||||
onClick = {},
|
||||
enabled = false,
|
||||
small = true,
|
||||
text = { Text(text = "Disabled") },
|
||||
leadingIcon = {
|
||||
Icon(imageVector = NiaIcons.Add, contentDescription = null)
|
||||
}
|
||||
)
|
||||
NiaTextButton(
|
||||
onClick = {},
|
||||
enabled = false,
|
||||
small = true,
|
||||
text = { Text(text = "Disabled") },
|
||||
leadingIcon = {
|
||||
Icon(imageVector = NiaIcons.Add, contentDescription = null)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
// Small buttons with trailing icons
|
||||
item {
|
||||
Row(horizontalArrangement = Arrangement.spacedBy(16.dp)) {
|
||||
NiaFilledButton(
|
||||
onClick = {},
|
||||
small = true,
|
||||
text = { Text(text = "Enabled") },
|
||||
trailingIcon = {
|
||||
Icon(imageVector = NiaIcons.Add, contentDescription = null)
|
||||
}
|
||||
)
|
||||
NiaOutlinedButton(
|
||||
onClick = {},
|
||||
small = true,
|
||||
text = { Text(text = "Enabled") },
|
||||
trailingIcon = {
|
||||
Icon(imageVector = NiaIcons.Add, contentDescription = null)
|
||||
}
|
||||
)
|
||||
NiaTextButton(
|
||||
onClick = {},
|
||||
small = true,
|
||||
text = { Text(text = "Enabled") },
|
||||
trailingIcon = {
|
||||
Icon(imageVector = NiaIcons.Add, contentDescription = null)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
// Disabled small buttons with trailing icons
|
||||
item {
|
||||
Row(horizontalArrangement = Arrangement.spacedBy(16.dp)) {
|
||||
NiaFilledButton(
|
||||
onClick = {},
|
||||
enabled = false,
|
||||
small = true,
|
||||
text = { Text(text = "Disabled") },
|
||||
trailingIcon = {
|
||||
Icon(imageVector = NiaIcons.Add, contentDescription = null)
|
||||
}
|
||||
)
|
||||
NiaOutlinedButton(
|
||||
onClick = {},
|
||||
enabled = false,
|
||||
small = true,
|
||||
text = { Text(text = "Disabled") },
|
||||
trailingIcon = {
|
||||
Icon(imageVector = NiaIcons.Add, contentDescription = null)
|
||||
}
|
||||
)
|
||||
NiaTextButton(
|
||||
onClick = {},
|
||||
enabled = false,
|
||||
small = true,
|
||||
text = { Text(text = "Disabled") },
|
||||
trailingIcon = {
|
||||
Icon(imageVector = NiaIcons.Add, contentDescription = null)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
// Dropdown menu
|
||||
item {
|
||||
NiaDropdownMenuButton(
|
||||
text = { Text("Newest first") },
|
||||
items = listOf("Item 1", "Item 2", "Item 3"),
|
||||
onItemClick = {},
|
||||
itemText = { item -> Text(item) }
|
||||
)
|
||||
}
|
||||
// Chips
|
||||
item {
|
||||
Row(horizontalArrangement = Arrangement.spacedBy(16.dp)) {
|
||||
var firstChecked by remember { mutableStateOf(false) }
|
||||
NiaFilterChip(
|
||||
checked = firstChecked,
|
||||
onCheckedChange = { checked -> firstChecked = checked },
|
||||
text = { Text(text = "Enabled".uppercase()) }
|
||||
)
|
||||
var secondChecked by remember { mutableStateOf(true) }
|
||||
NiaFilterChip(
|
||||
checked = secondChecked,
|
||||
onCheckedChange = { checked -> secondChecked = checked },
|
||||
text = { Text(text = "Enabled".uppercase()) }
|
||||
)
|
||||
var thirdChecked by remember { mutableStateOf(true) }
|
||||
NiaFilterChip(
|
||||
checked = thirdChecked,
|
||||
onCheckedChange = { checked -> thirdChecked = checked },
|
||||
enabled = false,
|
||||
text = { Text(text = "Disabled".uppercase()) }
|
||||
)
|
||||
}
|
||||
}
|
||||
// Toggle buttons
|
||||
item {
|
||||
Row(horizontalArrangement = Arrangement.spacedBy(16.dp)) {
|
||||
var firstChecked by remember { mutableStateOf(false) }
|
||||
NiaToggleButton(
|
||||
checked = firstChecked,
|
||||
onCheckedChange = { checked -> firstChecked = checked },
|
||||
icon = {
|
||||
Icon(
|
||||
painter = painterResource(id = NiaIcons.BookmarkBorder),
|
||||
contentDescription = null
|
||||
)
|
||||
},
|
||||
checkedIcon = {
|
||||
Icon(
|
||||
painter = painterResource(id = NiaIcons.Bookmark),
|
||||
contentDescription = null
|
||||
)
|
||||
}
|
||||
)
|
||||
var secondChecked by remember { mutableStateOf(true) }
|
||||
NiaToggleButton(
|
||||
checked = secondChecked,
|
||||
onCheckedChange = { checked -> secondChecked = checked },
|
||||
icon = {
|
||||
Icon(
|
||||
painter = painterResource(id = NiaIcons.BookmarkBorder),
|
||||
contentDescription = null
|
||||
)
|
||||
},
|
||||
checkedIcon = {
|
||||
Icon(
|
||||
painter = painterResource(id = NiaIcons.Bookmark),
|
||||
contentDescription = null
|
||||
)
|
||||
}
|
||||
)
|
||||
var thirdChecked by remember { mutableStateOf(false) }
|
||||
NiaToggleButton(
|
||||
checked = thirdChecked,
|
||||
onCheckedChange = { checked -> thirdChecked = checked },
|
||||
icon = {
|
||||
Icon(imageVector = NiaIcons.Add, contentDescription = null)
|
||||
},
|
||||
checkedIcon = {
|
||||
Icon(imageVector = NiaIcons.Check, contentDescription = null)
|
||||
}
|
||||
)
|
||||
var fourthChecked by remember { mutableStateOf(true) }
|
||||
NiaToggleButton(
|
||||
checked = fourthChecked,
|
||||
onCheckedChange = { checked -> fourthChecked = checked },
|
||||
icon = {
|
||||
Icon(imageVector = NiaIcons.Add, contentDescription = null)
|
||||
},
|
||||
checkedIcon = {
|
||||
Icon(imageVector = NiaIcons.Check, contentDescription = null)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
// View toggle
|
||||
item {
|
||||
Row(horizontalArrangement = Arrangement.spacedBy(16.dp)) {
|
||||
var firstExpanded by remember { mutableStateOf(false) }
|
||||
NiaViewToggleButton(
|
||||
expanded = firstExpanded,
|
||||
onExpandedChange = { expanded -> firstExpanded = expanded },
|
||||
compactText = { Text(text = "Compact view") },
|
||||
expandedText = { Text(text = "Expanded view") }
|
||||
)
|
||||
var secondExpanded by remember { mutableStateOf(true) }
|
||||
NiaViewToggleButton(
|
||||
expanded = secondExpanded,
|
||||
onExpandedChange = { expanded -> secondExpanded = expanded },
|
||||
compactText = { Text(text = "Compact view") },
|
||||
expandedText = { Text(text = "Expanded view") }
|
||||
)
|
||||
}
|
||||
}
|
||||
// Tags
|
||||
item {
|
||||
Row(horizontalArrangement = Arrangement.spacedBy(16.dp)) {
|
||||
var firstFollowed by remember { mutableStateOf(false) }
|
||||
NiaTopicTag(
|
||||
followed = firstFollowed,
|
||||
onFollowClick = { firstFollowed = true },
|
||||
onUnfollowClick = { firstFollowed = false },
|
||||
onBrowseClick = {},
|
||||
text = { Text(text = "Topic".uppercase()) },
|
||||
followText = { Text(text = "Follow") },
|
||||
unFollowText = { Text(text = "Unfollow") },
|
||||
browseText = { Text(text = "Browse topic") }
|
||||
)
|
||||
var secondFollowed by remember { mutableStateOf(true) }
|
||||
NiaTopicTag(
|
||||
followed = secondFollowed,
|
||||
onFollowClick = { secondFollowed = true },
|
||||
onUnfollowClick = { secondFollowed = false },
|
||||
onBrowseClick = {},
|
||||
text = { Text(text = "Topic".uppercase()) },
|
||||
followText = { Text(text = "Follow") },
|
||||
unFollowText = { Text(text = "Unfollow") },
|
||||
browseText = { Text(text = "Browse topic") }
|
||||
)
|
||||
}
|
||||
}
|
||||
// Tabs
|
||||
item {
|
||||
var selectedTabIndex by remember { mutableStateOf(0) }
|
||||
val titles = listOf("Topics", "People")
|
||||
NiaTabRow(selectedTabIndex = selectedTabIndex) {
|
||||
titles.forEachIndexed { index, title ->
|
||||
NiaTab(
|
||||
selected = selectedTabIndex == index,
|
||||
onClick = { selectedTabIndex = index },
|
||||
text = { Text(text = title) }
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
// Navigation
|
||||
item {
|
||||
var selectedItem by remember { mutableStateOf(0) }
|
||||
val items = listOf("For you", "Episodes", "Saved", "Interests")
|
||||
val icons = listOf(
|
||||
NiaIcons.UpcomingBorder,
|
||||
NiaIcons.MenuBookBorder,
|
||||
NiaIcons.BookmarksBorder
|
||||
)
|
||||
val selectedIcons = listOf(
|
||||
NiaIcons.Upcoming,
|
||||
NiaIcons.MenuBook,
|
||||
NiaIcons.Bookmarks
|
||||
)
|
||||
val tagIcon = NiaIcons.Tag
|
||||
NiaNavigationBar {
|
||||
items.forEachIndexed { index, item ->
|
||||
NiaNavigationBarItem(
|
||||
icon = {
|
||||
if (index == 3) {
|
||||
Icon(imageVector = tagIcon, contentDescription = null)
|
||||
} else {
|
||||
Icon(
|
||||
painter = painterResource(id = icons[index]),
|
||||
contentDescription = item
|
||||
)
|
||||
}
|
||||
},
|
||||
selectedIcon = {
|
||||
if (index == 3) {
|
||||
Icon(imageVector = tagIcon, contentDescription = null)
|
||||
} else {
|
||||
Icon(
|
||||
painter = painterResource(id = selectedIcons[index]),
|
||||
contentDescription = item
|
||||
)
|
||||
}
|
||||
},
|
||||
label = { Text(item) },
|
||||
selected = selectedItem == index,
|
||||
onClick = { selectedItem = index }
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.google.samples.apps.nowinandroid.core.ui.component
|
||||
|
||||
import androidx.compose.foundation.selection.toggleable
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.semantics.Role
|
||||
import com.google.samples.apps.nowinandroid.core.ui.icon.NiaIcons
|
||||
|
||||
/**
|
||||
* Now in Android filter chip with included leading checked icon as well as text content slot.
|
||||
*
|
||||
* @param checked Whether the chip is currently checked.
|
||||
* @param onCheckedChange Called when the user clicks the chip and toggles checked.
|
||||
* @param modifier Modifier to be applied to the chip.
|
||||
* @param enabled Controls the enabled state of the chip. When `false`, this chip will not be
|
||||
* clickable and will appear disabled to accessibility services.
|
||||
* @param text The text label content.
|
||||
*/
|
||||
@Composable
|
||||
fun NiaFilterChip(
|
||||
checked: Boolean,
|
||||
onCheckedChange: (Boolean) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
enabled: Boolean = true,
|
||||
text: @Composable () -> Unit
|
||||
) {
|
||||
// TODO: Replace with Chip when available in Compose Material 3: b/197399111
|
||||
NiaOutlinedButton(
|
||||
onClick = { onCheckedChange(!checked) },
|
||||
modifier = Modifier
|
||||
.toggleable(value = checked, enabled = enabled, role = Role.Button, onValueChange = {})
|
||||
.then(modifier),
|
||||
enabled = enabled,
|
||||
small = true,
|
||||
border = NiaButtonDefaults.outlinedButtonBorder(
|
||||
enabled = enabled,
|
||||
disabledColor = MaterialTheme.colorScheme.onBackground.copy(
|
||||
alpha = if (checked) {
|
||||
NiaButtonDefaults.DisabledButtonContentAlpha
|
||||
} else {
|
||||
NiaButtonDefaults.DisabledButtonContainerAlpha
|
||||
}
|
||||
)
|
||||
),
|
||||
colors = NiaButtonDefaults.outlinedButtonColors(
|
||||
containerColor = if (checked) {
|
||||
MaterialTheme.colorScheme.primaryContainer
|
||||
} else {
|
||||
Color.Transparent
|
||||
},
|
||||
disabledContainerColor = if (checked) {
|
||||
MaterialTheme.colorScheme.onBackground.copy(
|
||||
alpha = NiaButtonDefaults.DisabledButtonContainerAlpha
|
||||
)
|
||||
} else {
|
||||
Color.Transparent
|
||||
}
|
||||
),
|
||||
text = text,
|
||||
leadingIcon = if (checked) {
|
||||
{
|
||||
Icon(
|
||||
imageVector = NiaIcons.Check,
|
||||
contentDescription = null
|
||||
)
|
||||
}
|
||||
} else {
|
||||
null
|
||||
}
|
||||
)
|
||||
}
|
@ -0,0 +1,132 @@
|
||||
/*
|
||||
* Copyright 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.google.samples.apps.nowinandroid.core.ui.component
|
||||
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.material3.DropdownMenu
|
||||
import androidx.compose.material3.DropdownMenuItem
|
||||
import androidx.compose.material3.Icon
|
||||
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 com.google.samples.apps.nowinandroid.core.ui.icon.NiaIcons
|
||||
|
||||
/**
|
||||
* Now in Android dropdown menu button with included trailing icon as well as text label and item
|
||||
* content slots.
|
||||
*
|
||||
* @param items The list of items to display in the menu.
|
||||
* @param onItemClick Called when the user clicks on a menu item.
|
||||
* @param modifier Modifier to be applied to the button.
|
||||
* @param enabled Controls the enabled state of the button. When `false`, this button will not be
|
||||
* clickable and will appear disabled to accessibility services.
|
||||
* @param dismissOnItemClick Whether the menu should be dismissed when an item is clicked.
|
||||
* @param itemText The text label content for a given item.
|
||||
* @param itemLeadingIcon The leading icon content for a given item.
|
||||
* @param itemTrailingIcon The trailing icon content for a given item.
|
||||
*/
|
||||
@Composable
|
||||
fun <T> NiaDropdownMenuButton(
|
||||
items: List<T>,
|
||||
onItemClick: (item: T) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
enabled: Boolean = true,
|
||||
dismissOnItemClick: Boolean = true,
|
||||
text: @Composable () -> Unit,
|
||||
itemText: @Composable (item: T) -> Unit,
|
||||
itemLeadingIcon: @Composable ((item: T) -> Unit)? = null,
|
||||
itemTrailingIcon: @Composable ((item: T) -> Unit)? = null
|
||||
) {
|
||||
var expanded by remember { mutableStateOf(false) }
|
||||
Box(modifier = modifier) {
|
||||
NiaOutlinedButton(
|
||||
onClick = { expanded = true },
|
||||
enabled = enabled,
|
||||
text = text,
|
||||
trailingIcon = {
|
||||
Icon(
|
||||
imageVector = if (expanded) NiaIcons.ArrowDropUp else NiaIcons.ArrowDropDown,
|
||||
contentDescription = null
|
||||
)
|
||||
}
|
||||
)
|
||||
NiaDropdownMenu(
|
||||
expanded = expanded,
|
||||
onDismissRequest = { expanded = false },
|
||||
items = items,
|
||||
onItemClick = onItemClick,
|
||||
dismissOnItemClick = dismissOnItemClick,
|
||||
itemText = itemText,
|
||||
itemLeadingIcon = itemLeadingIcon,
|
||||
itemTrailingIcon = itemTrailingIcon
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Now in Android dropdown menu with item content slots. Wraps Material 3 [DropdownMenu] and
|
||||
* [DropdownMenuItem].
|
||||
*
|
||||
* @param expanded Whether the menu is currently open and visible to the user.
|
||||
* @param onDismissRequest Called when the user requests to dismiss the menu, such as by
|
||||
* tapping outside the menu's bounds.
|
||||
* @param items The list of items to display in the menu.
|
||||
* @param onItemClick Called when the user clicks on a menu item.
|
||||
* @param dismissOnItemClick Whether the menu should be dismissed when an item is clicked.
|
||||
* @param itemText The text label content for a given item.
|
||||
* @param itemLeadingIcon The leading icon content for a given item.
|
||||
* @param itemTrailingIcon The trailing icon content for a given item.
|
||||
*/
|
||||
@Composable
|
||||
fun <T> NiaDropdownMenu(
|
||||
expanded: Boolean,
|
||||
onDismissRequest: () -> Unit,
|
||||
items: List<T>,
|
||||
onItemClick: (item: T) -> Unit,
|
||||
dismissOnItemClick: Boolean = true,
|
||||
itemText: @Composable (item: T) -> Unit,
|
||||
itemLeadingIcon: @Composable ((item: T) -> Unit)? = null,
|
||||
itemTrailingIcon: @Composable ((item: T) -> Unit)? = null
|
||||
) {
|
||||
DropdownMenu(
|
||||
expanded = expanded,
|
||||
onDismissRequest = onDismissRequest
|
||||
) {
|
||||
items.forEach { item ->
|
||||
DropdownMenuItem(
|
||||
text = { itemText(item) },
|
||||
onClick = {
|
||||
onItemClick(item)
|
||||
if (dismissOnItemClick) onDismissRequest()
|
||||
},
|
||||
leadingIcon = if (itemLeadingIcon != null) {
|
||||
{ itemLeadingIcon(item) }
|
||||
} else {
|
||||
null
|
||||
},
|
||||
trailingIcon = if (itemTrailingIcon != null) {
|
||||
{ itemTrailingIcon(item) }
|
||||
} else {
|
||||
null
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,176 @@
|
||||
/*
|
||||
* Copyright 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.google.samples.apps.nowinandroid.core.ui.component
|
||||
|
||||
import androidx.compose.foundation.layout.ColumnScope
|
||||
import androidx.compose.foundation.layout.RowScope
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.NavigationBar
|
||||
import androidx.compose.material3.NavigationBarItem
|
||||
import androidx.compose.material3.NavigationBarItemDefaults
|
||||
import androidx.compose.material3.NavigationRail
|
||||
import androidx.compose.material3.NavigationRailItem
|
||||
import androidx.compose.material3.NavigationRailItemDefaults
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.unit.dp
|
||||
|
||||
/**
|
||||
* Now in Android navigation bar item with icon and label content slots. Wraps Material 3
|
||||
* [NavigationBarItem].
|
||||
*
|
||||
* @param selected Whether this item is selected.
|
||||
* @param onClick The callback to be invoked when this item is selected.
|
||||
* @param icon The item icon content.
|
||||
* @param modifier Modifier to be applied to this item.
|
||||
* @param selectedIcon The item icon content when selected.
|
||||
* @param enabled controls the enabled state of this item. When `false`, this item will not be
|
||||
* clickable and will appear disabled to accessibility services.
|
||||
* @param label The item text label content.
|
||||
* @param alwaysShowLabel Whether to always show the label for this item. If false, the label will
|
||||
* only be shown when this item is selected.
|
||||
*/
|
||||
@Composable
|
||||
fun RowScope.NiaNavigationBarItem(
|
||||
selected: Boolean,
|
||||
onClick: () -> Unit,
|
||||
icon: @Composable () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
selectedIcon: @Composable () -> Unit = icon,
|
||||
enabled: Boolean = true,
|
||||
label: @Composable (() -> Unit)? = null,
|
||||
alwaysShowLabel: Boolean = true
|
||||
) {
|
||||
NavigationBarItem(
|
||||
selected = selected,
|
||||
onClick = onClick,
|
||||
icon = if (selected) selectedIcon else icon,
|
||||
modifier = modifier,
|
||||
enabled = enabled,
|
||||
label = label,
|
||||
alwaysShowLabel = alwaysShowLabel,
|
||||
colors = NavigationBarItemDefaults.colors(
|
||||
selectedIconColor = NiaNavigationDefaults.navigationSelectedItemColor(),
|
||||
unselectedIconColor = NiaNavigationDefaults.navigationContentColor(),
|
||||
selectedTextColor = NiaNavigationDefaults.navigationSelectedItemColor(),
|
||||
unselectedTextColor = NiaNavigationDefaults.navigationContentColor(),
|
||||
indicatorColor = NiaNavigationDefaults.navigationIndicatorColor()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Now in Android navigation bar with content slot. Wraps Material 3 [NavigationBar].
|
||||
*
|
||||
* @param modifier Modifier to be applied to the navigation bar.
|
||||
* @param content Destinations inside the navigation bar. This should contain multiple
|
||||
* [NavigationBarItem]s.
|
||||
*/
|
||||
@Composable
|
||||
fun NiaNavigationBar(
|
||||
modifier: Modifier = Modifier,
|
||||
content: @Composable RowScope.() -> Unit
|
||||
) {
|
||||
NavigationBar(
|
||||
modifier = modifier,
|
||||
containerColor = NiaNavigationDefaults.NavigationContainerColor,
|
||||
contentColor = NiaNavigationDefaults.navigationContentColor(),
|
||||
tonalElevation = 0.dp,
|
||||
content = content
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Now in Android navigation rail item with icon and label content slots. Wraps Material 3
|
||||
* [NavigationRailItem].
|
||||
*
|
||||
* @param selected Whether this item is selected.
|
||||
* @param onClick The callback to be invoked when this item is selected.
|
||||
* @param icon The item icon content.
|
||||
* @param modifier Modifier to be applied to this item.
|
||||
* @param selectedIcon The item icon content when selected.
|
||||
* @param enabled controls the enabled state of this item. When `false`, this item will not be
|
||||
* clickable and will appear disabled to accessibility services.
|
||||
* @param label The item text label content.
|
||||
* @param alwaysShowLabel Whether to always show the label for this item. If false, the label will
|
||||
* only be shown when this item is selected.
|
||||
*/
|
||||
@Composable
|
||||
fun NiaNavigationRailItem(
|
||||
selected: Boolean,
|
||||
onClick: () -> Unit,
|
||||
icon: @Composable () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
selectedIcon: @Composable () -> Unit = icon,
|
||||
enabled: Boolean = true,
|
||||
label: @Composable (() -> Unit)? = null,
|
||||
alwaysShowLabel: Boolean = true
|
||||
) {
|
||||
NavigationRailItem(
|
||||
selected = selected,
|
||||
onClick = onClick,
|
||||
icon = if (selected) selectedIcon else icon,
|
||||
modifier = modifier,
|
||||
enabled = enabled,
|
||||
label = label,
|
||||
alwaysShowLabel = alwaysShowLabel,
|
||||
colors = NavigationRailItemDefaults.colors(
|
||||
selectedIconColor = NiaNavigationDefaults.navigationSelectedItemColor(),
|
||||
unselectedIconColor = NiaNavigationDefaults.navigationContentColor(),
|
||||
selectedTextColor = NiaNavigationDefaults.navigationSelectedItemColor(),
|
||||
unselectedTextColor = NiaNavigationDefaults.navigationContentColor(),
|
||||
indicatorColor = NiaNavigationDefaults.navigationIndicatorColor()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Now in Android navigation rail with header and content slots. Wraps Material 3 [NavigationRail].
|
||||
*
|
||||
* @param modifier Modifier to be applied to the navigation rail.
|
||||
* @param header Optional header that may hold a floating action button or a logo.
|
||||
* @param content Destinations inside the navigation rail. This should contain multiple
|
||||
* [NavigationRailItem]s.
|
||||
*/
|
||||
@Composable
|
||||
fun NiaNavigationRail(
|
||||
modifier: Modifier = Modifier,
|
||||
header: @Composable (ColumnScope.() -> Unit)? = null,
|
||||
content: @Composable ColumnScope.() -> Unit
|
||||
) {
|
||||
NavigationRail(
|
||||
modifier = modifier,
|
||||
containerColor = NiaNavigationDefaults.NavigationContainerColor,
|
||||
contentColor = NiaNavigationDefaults.navigationContentColor(),
|
||||
header = header,
|
||||
content = content
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Now in Android navigation default values.
|
||||
*/
|
||||
object NiaNavigationDefaults {
|
||||
val NavigationContainerColor = Color.Transparent
|
||||
@Composable
|
||||
fun navigationContentColor() = MaterialTheme.colorScheme.onSurfaceVariant
|
||||
@Composable
|
||||
fun navigationSelectedItemColor() = MaterialTheme.colorScheme.onPrimaryContainer
|
||||
@Composable
|
||||
fun navigationIndicatorColor() = MaterialTheme.colorScheme.primaryContainer
|
||||
}
|
@ -0,0 +1,102 @@
|
||||
/*
|
||||
* Copyright 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.google.samples.apps.nowinandroid.core.ui.component
|
||||
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.ProvideTextStyle
|
||||
import androidx.compose.material3.Tab
|
||||
import androidx.compose.material3.TabRow
|
||||
import androidx.compose.material3.TabRowDefaults
|
||||
import androidx.compose.material3.TabRowDefaults.tabIndicatorOffset
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.dp
|
||||
|
||||
/**
|
||||
* Now in Android tab. Wraps Material 3 [Tab] and shifts text label down.
|
||||
*
|
||||
* @param selected Whether this tab is selected or not.
|
||||
* @param onClick The callback to be invoked when this tab is selected.
|
||||
* @param modifier Modifier to be applied to the tab.
|
||||
* @param enabled Controls the enabled state of the tab. When `false`, this tab will not be
|
||||
* clickable and will appear disabled to accessibility services.
|
||||
* @param text The text label content.
|
||||
*/
|
||||
@Composable
|
||||
fun NiaTab(
|
||||
selected: Boolean,
|
||||
onClick: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
enabled: Boolean = true,
|
||||
text: @Composable () -> Unit
|
||||
) {
|
||||
Tab(
|
||||
selected = selected,
|
||||
onClick = onClick,
|
||||
modifier = modifier,
|
||||
enabled = enabled,
|
||||
text = {
|
||||
val style = MaterialTheme.typography.labelLarge.copy(textAlign = TextAlign.Center)
|
||||
ProvideTextStyle(
|
||||
value = style,
|
||||
content = {
|
||||
Box(modifier = Modifier.padding(top = NiaTabDefaults.TabTopPadding)) {
|
||||
text()
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Now in Android tab row. Wraps Material 3 [TabRow].
|
||||
*
|
||||
* @param selectedTabIndex The index of the currently selected tab.
|
||||
* @param modifier Modifier to be applied to the tab row.
|
||||
* @param tabs The tabs inside this tab row. Typically this will be multiple [NiaTab]s. Each element
|
||||
* inside this lambda will be measured and placed evenly across the row, each taking up equal space.
|
||||
*/
|
||||
@Composable
|
||||
fun NiaTabRow(
|
||||
selectedTabIndex: Int,
|
||||
modifier: Modifier = Modifier,
|
||||
tabs: @Composable () -> Unit
|
||||
) {
|
||||
TabRow(
|
||||
selectedTabIndex = selectedTabIndex,
|
||||
modifier = modifier,
|
||||
containerColor = Color.Transparent,
|
||||
contentColor = MaterialTheme.colorScheme.onSurface,
|
||||
indicator = { tabPositions ->
|
||||
TabRowDefaults.Indicator(
|
||||
modifier = Modifier.tabIndicatorOffset(tabPositions[selectedTabIndex]),
|
||||
height = 2.dp,
|
||||
color = MaterialTheme.colorScheme.onSurface
|
||||
)
|
||||
},
|
||||
tabs = tabs
|
||||
)
|
||||
}
|
||||
|
||||
object NiaTabDefaults {
|
||||
val TabTopPadding = 7.dp
|
||||
}
|
@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.google.samples.apps.nowinandroid.core.ui.component
|
||||
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.contentColorFor
|
||||
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.graphics.Color
|
||||
|
||||
@Composable
|
||||
fun NiaTopicTag(
|
||||
followed: Boolean,
|
||||
onFollowClick: () -> Unit,
|
||||
onUnfollowClick: () -> Unit,
|
||||
onBrowseClick: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
enabled: Boolean = true,
|
||||
text: @Composable () -> Unit,
|
||||
followText: @Composable () -> Unit,
|
||||
unFollowText: @Composable () -> Unit,
|
||||
browseText: @Composable () -> Unit
|
||||
) {
|
||||
var expanded by remember { mutableStateOf(false) }
|
||||
Box(modifier = modifier) {
|
||||
val containerColor = if (followed) {
|
||||
MaterialTheme.colorScheme.primaryContainer
|
||||
} else {
|
||||
MaterialTheme.colorScheme.surfaceVariant
|
||||
}
|
||||
NiaTextButton(
|
||||
onClick = { expanded = true },
|
||||
enabled = enabled,
|
||||
small = true,
|
||||
colors = NiaButtonDefaults.textButtonColors(
|
||||
containerColor = containerColor,
|
||||
contentColor = contentColorFor(backgroundColor = containerColor),
|
||||
disabledContainerColor = if (followed) {
|
||||
MaterialTheme.colorScheme.onBackground.copy(
|
||||
alpha = NiaButtonDefaults.DisabledButtonContentAlpha
|
||||
)
|
||||
} else {
|
||||
Color.Transparent
|
||||
}
|
||||
),
|
||||
text = text
|
||||
)
|
||||
NiaDropdownMenu(
|
||||
expanded = expanded,
|
||||
onDismissRequest = { expanded = false },
|
||||
items = if (followed) listOf(UNFOLLOW, BROWSE) else listOf(FOLLOW, BROWSE),
|
||||
onItemClick = { item ->
|
||||
when (item) {
|
||||
FOLLOW -> onFollowClick()
|
||||
UNFOLLOW -> onUnfollowClick()
|
||||
BROWSE -> onBrowseClick()
|
||||
}
|
||||
},
|
||||
itemText = { item ->
|
||||
when (item) {
|
||||
FOLLOW -> followText()
|
||||
UNFOLLOW -> unFollowText()
|
||||
BROWSE -> browseText()
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private const val FOLLOW = 1
|
||||
private const val UNFOLLOW = 2
|
||||
private const val BROWSE = 3
|
@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.google.samples.apps.nowinandroid.core.ui.component
|
||||
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.sizeIn
|
||||
import androidx.compose.foundation.selection.toggleable
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.drawBehind
|
||||
import androidx.compose.ui.platform.LocalDensity
|
||||
import androidx.compose.ui.semantics.Role
|
||||
import androidx.compose.ui.unit.dp
|
||||
|
||||
/**
|
||||
* Now in Android toggle button with icon and checked icon content slots. Wraps Material 3
|
||||
* [IconButton].
|
||||
*
|
||||
* @param checked Whether the toggle button is currently checked.
|
||||
* @param onCheckedChange Called when the user clicks the toggle button and toggles checked.
|
||||
* @param modifier Modifier to be applied to the toggle button.
|
||||
* @param enabled Controls the enabled state of the toggle button. When `false`, this toggle button
|
||||
* will not be clickable and will appear disabled to accessibility services.
|
||||
* @param icon The icon content to show when unchecked.
|
||||
* @param checkedIcon The icon content to show when checked.
|
||||
*/
|
||||
@Composable
|
||||
fun NiaToggleButton(
|
||||
checked: Boolean,
|
||||
onCheckedChange: (Boolean) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
enabled: Boolean = true,
|
||||
icon: @Composable () -> Unit,
|
||||
checkedIcon: @Composable () -> Unit = icon
|
||||
) {
|
||||
val checkedColor = MaterialTheme.colorScheme.primaryContainer
|
||||
val checkedRadius = with(LocalDensity.current) {
|
||||
(NiaToggleButtonDefaults.ToggleButtonSize / 2).toPx()
|
||||
}
|
||||
IconButton(
|
||||
onClick = { onCheckedChange(!checked) },
|
||||
modifier = Modifier
|
||||
.toggleable(value = checked, enabled = enabled, role = Role.Button, onValueChange = {})
|
||||
.drawBehind {
|
||||
if (checked) drawCircle(
|
||||
color = checkedColor,
|
||||
radius = checkedRadius
|
||||
)
|
||||
}
|
||||
.then(modifier),
|
||||
enabled = enabled,
|
||||
content = {
|
||||
Box(
|
||||
modifier = Modifier.sizeIn(
|
||||
maxWidth = NiaToggleButtonDefaults.ToggleButtonIconSize,
|
||||
maxHeight = NiaToggleButtonDefaults.ToggleButtonIconSize
|
||||
)
|
||||
) {
|
||||
if (checked) checkedIcon() else icon()
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Now in Android toggle button default values.
|
||||
*/
|
||||
object NiaToggleButtonDefaults {
|
||||
val ToggleButtonSize = 40.dp
|
||||
val ToggleButtonIconSize = 18.dp
|
||||
}
|
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.google.samples.apps.nowinandroid.core.ui.component
|
||||
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import com.google.samples.apps.nowinandroid.core.ui.icon.NiaIcons
|
||||
|
||||
/**
|
||||
* Now in Android view toggle button with included trailing icon as well as compact and expanded
|
||||
* text label content slots.
|
||||
*
|
||||
* @param expanded Whether the view toggle is currently in expanded mode or compact mode.
|
||||
* @param onExpandedChange Called when the user clicks the button and toggles the mode.
|
||||
* @param modifier Modifier to be applied to the button.
|
||||
* @param enabled Controls the enabled state of the button. When `false`, this button will not be
|
||||
* clickable and will appear disabled to accessibility services.
|
||||
* @param compactText The text label content to show in expanded mode.
|
||||
* @param expandedText The text label content to show in compact mode.
|
||||
*/
|
||||
@Composable
|
||||
fun NiaViewToggleButton(
|
||||
expanded: Boolean,
|
||||
onExpandedChange: (Boolean) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
enabled: Boolean = true,
|
||||
compactText: @Composable () -> Unit,
|
||||
expandedText: @Composable () -> Unit
|
||||
) {
|
||||
NiaTextButton(
|
||||
onClick = { onExpandedChange(!expanded) },
|
||||
modifier = modifier,
|
||||
enabled = enabled,
|
||||
text = if (expanded) expandedText else compactText,
|
||||
trailingIcon = {
|
||||
Icon(
|
||||
imageVector = if (expanded) NiaIcons.ViewDay else NiaIcons.ShortText,
|
||||
contentDescription = null
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.google.samples.apps.nowinandroid.core.ui.icon
|
||||
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.MoreVert
|
||||
import androidx.compose.material.icons.outlined.AccountCircle
|
||||
import androidx.compose.material.icons.rounded.Add
|
||||
import androidx.compose.material.icons.rounded.ArrowBack
|
||||
import androidx.compose.material.icons.rounded.ArrowDropDown
|
||||
import androidx.compose.material.icons.rounded.ArrowDropUp
|
||||
import androidx.compose.material.icons.rounded.Check
|
||||
import androidx.compose.material.icons.rounded.Close
|
||||
import androidx.compose.material.icons.rounded.ExpandLess
|
||||
import androidx.compose.material.icons.rounded.Fullscreen
|
||||
import androidx.compose.material.icons.rounded.PlayArrow
|
||||
import androidx.compose.material.icons.rounded.Search
|
||||
import androidx.compose.material.icons.rounded.ShortText
|
||||
import androidx.compose.material.icons.rounded.Tag
|
||||
import androidx.compose.material.icons.rounded.ViewDay
|
||||
import androidx.compose.material.icons.rounded.VolumeOff
|
||||
import androidx.compose.material.icons.rounded.VolumeUp
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import com.google.samples.apps.nowinandroid.core.ui.R
|
||||
|
||||
/**
|
||||
* Now in Android icons. Material icons are [ImageVector]s, custom icons are drawable resource IDs.
|
||||
*/
|
||||
object NiaIcons {
|
||||
val AccountCircle = Icons.Outlined.AccountCircle
|
||||
val Add = Icons.Rounded.Add
|
||||
val ArrowBack = Icons.Rounded.ArrowBack
|
||||
val ArrowDropDown = Icons.Rounded.ArrowDropDown
|
||||
val ArrowDropUp = Icons.Rounded.ArrowDropUp
|
||||
val Bookmark = R.drawable.ic_bookmark
|
||||
val BookmarkBorder = R.drawable.ic_bookmark_border
|
||||
val Bookmarks = R.drawable.ic_bookmarks
|
||||
val BookmarksBorder = R.drawable.ic_bookmarks_border
|
||||
val Check = Icons.Rounded.Check
|
||||
val Close = Icons.Rounded.Close
|
||||
val ExpandLess = Icons.Rounded.ExpandLess
|
||||
val Fullscreen = Icons.Rounded.Fullscreen
|
||||
val MenuBook = R.drawable.ic_menu_book
|
||||
val MenuBookBorder = R.drawable.ic_menu_book_border
|
||||
val MoreVert = Icons.Default.MoreVert
|
||||
val PlayArrow = Icons.Rounded.PlayArrow
|
||||
val Search = Icons.Rounded.Search
|
||||
val ShortText = Icons.Rounded.ShortText
|
||||
val Tag = Icons.Rounded.Tag
|
||||
val Upcoming = R.drawable.ic_upcoming
|
||||
val UpcomingBorder = R.drawable.ic_upcoming_border
|
||||
val ViewDay = Icons.Rounded.ViewDay
|
||||
val VolumeOff = Icons.Rounded.VolumeOff
|
||||
val VolumeUp = Icons.Rounded.VolumeUp
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
~ Copyright 2022 Google LLC
|
||||
~
|
||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
||||
~ you may not use this file except in compliance with the License.
|
||||
~ You may obtain a copy of the License at
|
||||
~
|
||||
~ https://www.apache.org/licenses/LICENSE-2.0
|
||||
~
|
||||
~ Unless required by applicable law or agreed to in writing, software
|
||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
~ See the License for the specific language governing permissions and
|
||||
~ limitations under the License.
|
||||
-->
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:pathData="M17,3H7C5.9,3 5,3.9 5,5V19.483C5,20.201 5.734,20.685 6.394,20.403L12,18L17.606,20.403C18.266,20.685 19,20.201 19,19.483V5C19,3.9 18.1,3 17,3Z"
|
||||
android:fillColor="#201A1B"/>
|
||||
</vector>
|
@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
~ Copyright 2022 Google LLC
|
||||
~
|
||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
||||
~ you may not use this file except in compliance with the License.
|
||||
~ You may obtain a copy of the License at
|
||||
~
|
||||
~ https://www.apache.org/licenses/LICENSE-2.0
|
||||
~
|
||||
~ Unless required by applicable law or agreed to in writing, software
|
||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
~ See the License for the specific language governing permissions and
|
||||
~ limitations under the License.
|
||||
-->
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:pathData="M17,3H7C5.9,3 5,3.9 5,5V19.483C5,20.201 5.734,20.685 6.394,20.403L12,18L17.606,20.403C18.266,20.685 19,20.201 19,19.483V5C19,3.9 18.1,3 17,3ZM17,18L12.4,15.994C12.145,15.883 11.855,15.883 11.6,15.994L7,18V5H17V18Z"
|
||||
android:fillColor="#201A1B"/>
|
||||
</vector>
|
@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
~ Copyright 2022 Google LLC
|
||||
~
|
||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
||||
~ you may not use this file except in compliance with the License.
|
||||
~ You may obtain a copy of the License at
|
||||
~
|
||||
~ https://www.apache.org/licenses/LICENSE-2.0
|
||||
~
|
||||
~ Unless required by applicable law or agreed to in writing, software
|
||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
~ See the License for the specific language governing permissions and
|
||||
~ limitations under the License.
|
||||
-->
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:pathData="M19,19C19,19.552 19.448,20 20,20C20.552,20 21,19.552 21,19V3C21,1.9 20.1,1 19,1H7C6.448,1 6,1.448 6,2C6,2.552 6.448,3 7,3H19V19Z"
|
||||
android:fillColor="#201A1B"/>
|
||||
<path
|
||||
android:pathData="M15,5H5C3.9,5 3,5.9 3,7V21.483C3,22.201 3.734,22.685 4.394,22.403L10,20L15.606,22.403C16.266,22.685 17,22.201 17,21.483V7C17,5.9 16.1,5 15,5Z"
|
||||
android:fillColor="#201A1B"/>
|
||||
</vector>
|
@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
~ Copyright 2022 Google LLC
|
||||
~
|
||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
||||
~ you may not use this file except in compliance with the License.
|
||||
~ You may obtain a copy of the License at
|
||||
~
|
||||
~ https://www.apache.org/licenses/LICENSE-2.0
|
||||
~
|
||||
~ Unless required by applicable law or agreed to in writing, software
|
||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
~ See the License for the specific language governing permissions and
|
||||
~ limitations under the License.
|
||||
-->
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:pathData="M19,19C19,19.552 19.448,20 20,20C20.552,20 21,19.552 21,19V3C21,1.9 20.1,1 19,1H7C6.448,1 6,1.448 6,2C6,2.552 6.448,3 7,3H19V19Z"
|
||||
android:fillColor="#201A1B"/>
|
||||
<path
|
||||
android:pathData="M5,5H15C16.1,5 17,5.9 17,7V21.483C17,22.201 16.266,22.685 15.606,22.403L10,20L4.394,22.403C3.734,22.685 3,22.201 3,21.483V7C3,5.9 3.9,5 5,5ZM15,19.97V7H5V19.97C6.535,19.31 8.07,18.65 9.605,17.99C9.857,17.882 10.143,17.882 10.395,17.99L15,19.97Z"
|
||||
android:fillColor="#201A1B"
|
||||
android:fillType="evenOdd"/>
|
||||
</vector>
|
@ -0,0 +1,34 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
~ Copyright 2022 Google LLC
|
||||
~
|
||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
||||
~ you may not use this file except in compliance with the License.
|
||||
~ You may obtain a copy of the License at
|
||||
~
|
||||
~ https://www.apache.org/licenses/LICENSE-2.0
|
||||
~
|
||||
~ Unless required by applicable law or agreed to in writing, software
|
||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
~ See the License for the specific language governing permissions and
|
||||
~ limitations under the License.
|
||||
-->
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:pathData="M12.005,5.178C13.455,4.078 15.555,3.678 17.505,3.678C18.955,3.678 20.495,3.898 21.775,4.468C22.505,4.798 22.995,5.508 22.995,6.318V17.598C22.995,18.908 21.775,19.868 20.515,19.538C19.535,19.288 18.495,19.178 17.495,19.178C15.935,19.178 14.275,19.428 12.935,20.098C12.345,20.398 11.665,20.398 11.065,20.098C9.725,19.438 8.065,19.178 6.505,19.178C5.505,19.178 4.465,19.288 3.485,19.538C2.225,19.858 1.005,18.898 1.005,17.598V6.318C1.005,5.508 1.495,4.798 2.225,4.468C3.515,3.898 5.055,3.678 6.505,3.678C8.455,3.678 10.555,4.078 12.005,5.178ZM21,17.5C19.9,17.15 18.7,17 17.5,17C16.16,17 14.37,17.41 13,17.99V6.49C14.37,5.9 16.16,5.5 17.5,5.5C18.7,5.5 19.9,5.65 21,6V17.5Z"
|
||||
android:fillColor="#201A1B"
|
||||
android:fillType="evenOdd"/>
|
||||
<path
|
||||
android:pathData="M17.5,9.5C18.38,9.5 19.23,9.59 20,9.76V8.24C19.21,8.09 18.36,8 17.5,8C16.22,8 15.04,8.16 14,8.47V10.04C14.99,9.69 16.18,9.5 17.5,9.5Z"
|
||||
android:fillColor="#201A1B"/>
|
||||
<path
|
||||
android:pathData="M17.5,12.16C18.38,12.16 19.23,12.25 20,12.42V10.9C19.21,10.75 18.36,10.66 17.5,10.66C16.22,10.66 15.04,10.82 14,11.13V12.7C14.99,12.36 16.18,12.16 17.5,12.16Z"
|
||||
android:fillColor="#201A1B"/>
|
||||
<path
|
||||
android:pathData="M17.5,14.83C18.38,14.83 19.23,14.92 20,15.09V13.57C19.21,13.42 18.36,13.33 17.5,13.33C16.22,13.33 15.04,13.49 14,13.8V15.37C14.99,15.02 16.18,14.83 17.5,14.83Z"
|
||||
android:fillColor="#201A1B"/>
|
||||
</vector>
|
@ -0,0 +1,34 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
~ Copyright 2022 Google LLC
|
||||
~
|
||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
||||
~ you may not use this file except in compliance with the License.
|
||||
~ You may obtain a copy of the License at
|
||||
~
|
||||
~ https://www.apache.org/licenses/LICENSE-2.0
|
||||
~
|
||||
~ Unless required by applicable law or agreed to in writing, software
|
||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
~ See the License for the specific language governing permissions and
|
||||
~ limitations under the License.
|
||||
-->
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:pathData="M12.005,5.178C13.455,4.078 15.555,3.678 17.505,3.678C18.955,3.678 20.495,3.898 21.775,4.468C22.505,4.798 22.995,5.508 22.995,6.318V17.598C22.995,18.908 21.775,19.868 20.515,19.538C19.535,19.288 18.495,19.178 17.495,19.178C15.935,19.178 14.275,19.428 12.935,20.098C12.345,20.398 11.665,20.398 11.065,20.098C9.725,19.438 8.065,19.178 6.505,19.178C5.505,19.178 4.465,19.288 3.485,19.538C2.225,19.858 1.005,18.898 1.005,17.598V6.318C1.005,5.508 1.495,4.798 2.225,4.468C3.515,3.898 5.055,3.678 6.505,3.678C8.455,3.678 10.555,4.078 12.005,5.178ZM6.5,5.5C7.84,5.5 9.63,5.91 11,6.49V17.99C9.63,17.41 7.84,17 6.5,17C5.3,17 4.1,17.15 3,17.5V6C4.1,5.65 5.3,5.5 6.5,5.5ZM21,17.5C19.9,17.15 18.7,17 17.5,17C16.16,17 14.37,17.41 13,17.99V6.49C14.37,5.9 16.16,5.5 17.5,5.5C18.7,5.5 19.9,5.65 21,6V17.5Z"
|
||||
android:fillColor="#201A1B"
|
||||
android:fillType="evenOdd"/>
|
||||
<path
|
||||
android:pathData="M17.5,9.5C18.38,9.5 19.23,9.59 20,9.76V8.24C19.21,8.09 18.36,8 17.5,8C16.22,8 15.04,8.16 14,8.47V10.04C14.99,9.69 16.18,9.5 17.5,9.5Z"
|
||||
android:fillColor="#201A1B"/>
|
||||
<path
|
||||
android:pathData="M17.5,12.16C18.38,12.16 19.23,12.25 20,12.42V10.9C19.21,10.75 18.36,10.66 17.5,10.66C16.22,10.66 15.04,10.82 14,11.13V12.7C14.99,12.36 16.18,12.16 17.5,12.16Z"
|
||||
android:fillColor="#201A1B"/>
|
||||
<path
|
||||
android:pathData="M17.5,14.83C18.38,14.83 19.23,14.92 20,15.09V13.57C19.21,13.42 18.36,13.33 17.5,13.33C16.22,13.33 15.04,13.49 14,13.8V15.37C14.99,15.02 16.18,14.83 17.5,14.83Z"
|
||||
android:fillColor="#201A1B"/>
|
||||
</vector>
|
@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
~ Copyright 2022 Google LLC
|
||||
~
|
||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
||||
~ you may not use this file except in compliance with the License.
|
||||
~ You may obtain a copy of the License at
|
||||
~
|
||||
~ https://www.apache.org/licenses/LICENSE-2.0
|
||||
~
|
||||
~ Unless required by applicable law or agreed to in writing, software
|
||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
~ See the License for the specific language governing permissions and
|
||||
~ limitations under the License.
|
||||
-->
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:pathData="M20.45,6.55C20.07,6.17 19.44,6.17 19.06,6.55L16.89,8.7C16.5,9.08 16.5,9.71 16.89,10.09L16.9,10.1C17.29,10.49 17.91,10.49 18.3,10.1C18.92,9.47 19.82,8.56 20.45,7.93C20.83,7.55 20.83,6.93 20.45,6.55Z"
|
||||
android:fillColor="#201A1B"/>
|
||||
<path
|
||||
android:pathData="M12.02,3H11.99C11.44,3 11,3.44 11,3.98V7.01C11,7.56 11.44,8 11.98,8H12.01C12.56,8 13,7.56 13,7.02V3.98C13,3.44 12.56,3 12.02,3Z"
|
||||
android:fillColor="#201A1B"/>
|
||||
<path
|
||||
android:pathData="M7.1,10.11L7.11,10.1C7.49,9.72 7.49,9.09 7.11,8.71L4.96,6.54C4.58,6.15 3.95,6.15 3.57,6.54L3.55,6.55C3.16,6.94 3.16,7.56 3.55,7.94C4.18,8.56 5.08,9.48 5.7,10.11C6.09,10.49 6.72,10.49 7.1,10.11Z"
|
||||
android:fillColor="#201A1B"/>
|
||||
<path
|
||||
android:pathData="M12,15C10.76,15 9.69,14.25 9.24,13.17C8.92,12.43 8.14,12 7.34,12H4C2.9,12 2,12.9 2,14V19C2,20.1 2.9,21 4,21H20C21.1,21 22,20.1 22,19V14C22,12.9 21.1,12 20,12H16.66C15.86,12 15.08,12.43 14.76,13.17C14.31,14.25 13.24,15 12,15Z"
|
||||
android:fillColor="#201A1B"/>
|
||||
</vector>
|
@ -0,0 +1,34 @@
|
||||
<?xml version="1.0" encoding="utf-8"?><!--
|
||||
~ Copyright 2022 Google LLC
|
||||
~
|
||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
||||
~ you may not use this file except in compliance with the License.
|
||||
~ You may obtain a copy of the License at
|
||||
~
|
||||
~ https://www.apache.org/licenses/LICENSE-2.0
|
||||
~
|
||||
~ Unless required by applicable law or agreed to in writing, software
|
||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
~ See the License for the specific language governing permissions and
|
||||
~ limitations under the License.
|
||||
-->
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:pathData="M20.45,6.55C20.07,6.17 19.44,6.17 19.06,6.55L16.89,8.7C16.5,9.08 16.5,9.71 16.89,10.09L16.9,10.1C17.29,10.49 17.91,10.49 18.3,10.1C18.92,9.47 19.82,8.56 20.45,7.93C20.83,7.55 20.83,6.93 20.45,6.55Z"
|
||||
android:fillColor="#201A1B"/>
|
||||
<path
|
||||
android:pathData="M12.02,3H11.99C11.44,3 11,3.44 11,3.98V7.01C11,7.56 11.44,8 11.98,8H12.01C12.56,8 13,7.56 13,7.02V3.98C13,3.44 12.56,3 12.02,3Z"
|
||||
android:fillColor="#201A1B"/>
|
||||
<path
|
||||
android:pathData="M7.1,10.11L7.11,10.1C7.49,9.72 7.49,9.09 7.11,8.71L4.96,6.54C4.58,6.15 3.95,6.15 3.57,6.54L3.55,6.55C3.16,6.94 3.16,7.56 3.55,7.94C4.18,8.56 5.08,9.48 5.7,10.11C6.09,10.49 6.72,10.49 7.1,10.11Z"
|
||||
android:fillColor="#201A1B"/>
|
||||
<path
|
||||
android:pathData="M9.24,13.17C9.69,14.25 10.76,15 12,15C13.24,15 14.31,14.25 14.76,13.17C15.08,12.43 15.86,12 16.66,12H20C21.1,12 22,12.9 22,14V19C22,20.1 21.1,21 20,21H4C2.9,21 2,20.1 2,19V14C2,12.9 2.9,12 4,12H7.34C8.14,12 8.92,12.43 9.24,13.17ZM20,14H16.58C15.81,15.76 14.04,17 12,17C9.96,17 8.19,15.76 7.42,14H4V19H20V14Z"
|
||||
android:fillColor="#201A1B"
|
||||
android:fillType="evenOdd"/>
|
||||
</vector>
|
Loading…
Reference in new issue