Implement Basic Controls(Toggle Switch, Checkbox and Radio Button) (#214)
* Implement Basic Controls(Toggle Switch, Checkbox and Radio Button) * Remove appcompat Dependency from Controls module * Resolving comments
This commit is contained in:
Родитель
18d9e0432b
Коммит
ef6a2db75d
|
@ -34,6 +34,7 @@
|
|||
<activity android:name="com.microsoft.fluentuidemo.demos.AvatarGroupViewActivity" />
|
||||
<activity android:name="com.microsoft.fluentuidemo.demos.BasicInputsActivity" />
|
||||
<activity android:name="com.microsoft.fluentuidemo.demos.V2BasicInputsActivity" />
|
||||
<activity android:name="com.microsoft.fluentuidemo.demos.V2BasicControlsActivity" />
|
||||
<activity android:name="com.microsoft.fluentuidemo.demos.BottomNavigationActivity" />
|
||||
<activity android:name="com.microsoft.fluentuidemo.demos.BottomSheetActivity" />
|
||||
<activity android:name="com.microsoft.fluentuidemo.demos.CalendarViewActivity" />
|
||||
|
|
|
@ -12,9 +12,9 @@ open class MyButtonTokens : ButtonTokens() {
|
|||
@Composable
|
||||
override fun fixedHeight(buttonInfo: ButtonInfo): Dp {
|
||||
return when (buttonInfo.size) {
|
||||
ButtonSize.Small -> 50.dp
|
||||
ButtonSize.Medium -> 60.dp
|
||||
ButtonSize.Large -> 100.dp
|
||||
ButtonSize.Small -> 40.dp
|
||||
ButtonSize.Medium -> 48.dp
|
||||
ButtonSize.Large -> 60.dp
|
||||
}
|
||||
}
|
||||
}
|
|
@ -15,6 +15,7 @@ const val AVATAR_VIEW = "AvatarView"
|
|||
const val AVATAR_GROUP_VIEW = "AvatarGroupView"
|
||||
const val BASIC_INPUTS = "Basic Inputs"
|
||||
const val V2BASIC_INPUTS = "V2 Basic Inputs"
|
||||
const val V2BASIC_CONTROLS = "V2 Basic Controls"
|
||||
const val BOTTOM_NAVIGATION = "BottomNavigation"
|
||||
const val BOTTOM_SHEET = "BottomSheet"
|
||||
const val CALENDAR_VIEW = "CalendarView"
|
||||
|
@ -42,6 +43,7 @@ val DEMOS = arrayListOf(
|
|||
Demo(AVATAR_GROUP_VIEW, AvatarGroupViewActivity::class),
|
||||
Demo(BASIC_INPUTS, BasicInputsActivity::class),
|
||||
Demo(V2BASIC_INPUTS, V2BasicInputsActivity::class),
|
||||
Demo(V2BASIC_CONTROLS, V2BasicControlsActivity::class),
|
||||
Demo(BOTTOM_NAVIGATION, BottomNavigationActivity::class),
|
||||
Demo(BOTTOM_SHEET, BottomSheetActivity::class),
|
||||
Demo(CALENDAR_VIEW, CalendarViewActivity::class),
|
||||
|
|
|
@ -0,0 +1,154 @@
|
|||
package com.microsoft.fluentuidemo.demos
|
||||
|
||||
import android.os.Bundle
|
||||
import android.widget.Toast
|
||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.selection.selectable
|
||||
import androidx.compose.material.Divider
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.ComposeView
|
||||
import androidx.compose.ui.semantics.Role
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.example.theme.token.MyAliasTokens
|
||||
import com.example.theme.token.MyGlobalTokens
|
||||
import com.microsoft.fluentui.theme.AppThemeController
|
||||
import com.microsoft.fluentui.theme.FluentTheme
|
||||
import com.microsoft.fluentui.theme.ThemeMode
|
||||
import com.microsoft.fluentui.theme.token.AliasTokens
|
||||
import com.microsoft.fluentui.theme.token.GlobalTokens
|
||||
import com.microsoft.fluentui.controls.CheckBox
|
||||
import com.microsoft.fluentui.controls.RadioButton
|
||||
import com.microsoft.fluentui.controls.ToggleSwitch
|
||||
import com.microsoft.fluentuidemo.DemoActivity
|
||||
import com.microsoft.fluentuidemo.R
|
||||
|
||||
class V2BasicControlsActivity : DemoActivity() {
|
||||
override val contentLayoutId: Int
|
||||
get() = R.layout.v2_activity_compose
|
||||
override val contentNeedsScrollableContainer: Boolean
|
||||
get() = false
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
val context = this
|
||||
|
||||
val compose_here = findViewById<ComposeView>(R.id.compose_here)
|
||||
compose_here.setContent {
|
||||
val globalTokens: GlobalTokens by AppThemeController.observeGlobalToken(initial = GlobalTokens())
|
||||
val aliasTokens: AliasTokens by AppThemeController.observeAliasToken(initial = AliasTokens())
|
||||
|
||||
FluentTheme(globalTokens = globalTokens, aliasTokens = aliasTokens) {
|
||||
Column(verticalArrangement = Arrangement.spacedBy(10.dp),
|
||||
modifier = Modifier.padding(16.dp)) {
|
||||
|
||||
var checked by remember { mutableStateOf(globalTokens !is MyGlobalTokens) }
|
||||
var enabled by remember { mutableStateOf(false) }
|
||||
val themes = listOf("Theme 1", "Theme 2")
|
||||
val selectedOption = remember { mutableStateOf(themes[0]) }
|
||||
|
||||
Row(horizontalArrangement = Arrangement.spacedBy(30.dp),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
modifier = Modifier.fillMaxWidth()) {
|
||||
Text(text = "Toggle Switch enable",
|
||||
fontWeight = FontWeight.Bold,
|
||||
modifier = Modifier.weight(1F),
|
||||
color = aliasTokens.neutralForegroundColor[AliasTokens.NeutralForegroundColorTokens.Foreground1].value(themeMode = ThemeMode.Auto))
|
||||
ToggleSwitch(true, enabled, {
|
||||
enabled = it
|
||||
Toast.makeText(context, "Switch 1 Toggled", Toast.LENGTH_SHORT).show()
|
||||
})
|
||||
}
|
||||
|
||||
Divider()
|
||||
|
||||
Row(horizontalArrangement = Arrangement.spacedBy(30.dp),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
modifier = Modifier.fillMaxWidth()) {
|
||||
Text(text = "Toggle Global/Alias Theme",
|
||||
fontWeight = FontWeight.Bold,
|
||||
modifier = Modifier.weight(1F),
|
||||
color = aliasTokens.neutralForegroundColor[AliasTokens.NeutralForegroundColorTokens.Foreground1].value(themeMode = ThemeMode.Auto))
|
||||
ToggleSwitch(enabled, checked, {
|
||||
checked = it
|
||||
if (checked) {
|
||||
AppThemeController.updateGlobalTokens(GlobalTokens())
|
||||
AppThemeController.updateAliasTokens(AliasTokens())
|
||||
selectedOption.value = themes[0]
|
||||
} else {
|
||||
AppThemeController.updateGlobalTokens(MyGlobalTokens())
|
||||
AppThemeController.updateAliasTokens(MyAliasTokens(MyGlobalTokens()))
|
||||
selectedOption.value = themes[1]
|
||||
}
|
||||
Toast.makeText(context, "Switch 2 Toggled", Toast.LENGTH_SHORT).show()
|
||||
})
|
||||
}
|
||||
|
||||
Row(horizontalArrangement = Arrangement.spacedBy(30.dp),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
modifier = Modifier.fillMaxWidth()) {
|
||||
Text(text = "Toggle Global/Alias Theme",
|
||||
fontWeight = FontWeight.Bold,
|
||||
modifier = Modifier.weight(1F),
|
||||
color = AppThemeController.aliasTokens.value!!.neutralForegroundColor[AliasTokens.NeutralForegroundColorTokens.Foreground1].value(themeMode = ThemeMode.Auto))
|
||||
CheckBox(enabled = enabled, checked = !checked, onCheckedChanged = {
|
||||
checked = !it
|
||||
if (checked) {
|
||||
AppThemeController.updateAliasTokens(AliasTokens())
|
||||
AppThemeController.updateGlobalTokens(GlobalTokens())
|
||||
selectedOption.value = themes[0]
|
||||
} else {
|
||||
AppThemeController.updateAliasTokens(MyAliasTokens(MyGlobalTokens()))
|
||||
AppThemeController.updateGlobalTokens(MyGlobalTokens())
|
||||
selectedOption.value = themes[1]
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
themes.forEach { theme ->
|
||||
Row(horizontalArrangement = Arrangement.spacedBy(30.dp),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.selectable(
|
||||
selected = (theme == selectedOption.value),
|
||||
onClick = { },
|
||||
role = Role.RadioButton,
|
||||
interactionSource = MutableInteractionSource(),
|
||||
indication = null
|
||||
)) {
|
||||
Text(text = theme,
|
||||
fontWeight = FontWeight.Bold,
|
||||
modifier = Modifier.weight(1F),
|
||||
color = AppThemeController.aliasTokens.value!!.neutralForegroundColor[AliasTokens.NeutralForegroundColorTokens.Foreground1].value(themeMode = ThemeMode.Auto))
|
||||
RadioButton(enabled = enabled,
|
||||
selected = (selectedOption.value == theme),
|
||||
onClick = {
|
||||
selectedOption.value = theme
|
||||
if (theme == "Theme 1") {
|
||||
AppThemeController.updateAliasTokens(AliasTokens())
|
||||
AppThemeController.updateGlobalTokens(GlobalTokens())
|
||||
checked = true
|
||||
} else {
|
||||
AppThemeController.updateAliasTokens(MyAliasTokens(MyGlobalTokens()))
|
||||
AppThemeController.updateGlobalTokens(MyGlobalTokens())
|
||||
checked = false
|
||||
}
|
||||
Toast.makeText(context, "Radio Button: ${theme} selected", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -24,10 +24,11 @@ import androidx.compose.ui.unit.dp
|
|||
import com.example.theme.token.MyAliasTokens
|
||||
import com.example.theme.token.MyButtonTokens
|
||||
import com.example.theme.token.MyGlobalTokens
|
||||
import com.microsoft.fluentui.button.Button
|
||||
import com.microsoft.fluentui.button.FloatingActionButton
|
||||
import com.microsoft.fluentui.controls.Button
|
||||
import com.microsoft.fluentui.controls.FloatingActionButton
|
||||
import com.microsoft.fluentui.theme.AppThemeController
|
||||
import com.microsoft.fluentui.theme.FluentTheme
|
||||
import com.microsoft.fluentui.theme.FluentTheme.themeMode
|
||||
import com.microsoft.fluentui.theme.ThemeMode
|
||||
import com.microsoft.fluentui.theme.token.AliasTokens
|
||||
import com.microsoft.fluentui.theme.token.ControlTokens
|
||||
|
@ -61,7 +62,8 @@ class V2BasicInputsActivity : DemoActivity() {
|
|||
) {
|
||||
FluentTheme(globalTokens = globalTokens, aliasTokens = aliasTokens, controlTokens = controlTokens) {
|
||||
Column(horizontalAlignment = Alignment.CenterHorizontally) {
|
||||
Text("Button to update Theme via Global & Alias token")
|
||||
Text("Button to update Theme via Global & Alias token",
|
||||
color = aliasTokens.neutralForegroundColor[AliasTokens.NeutralForegroundColorTokens.Foreground1].value(themeMode))
|
||||
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.spacedBy(5.dp, Alignment.CenterHorizontally),
|
||||
|
@ -71,9 +73,9 @@ class V2BasicInputsActivity : DemoActivity() {
|
|||
style = ButtonStyle.OutlinedButton,
|
||||
size = ButtonSize.Medium,
|
||||
onClick = {
|
||||
AppThemeController.onGlobalChanged(GlobalTokens())
|
||||
AppThemeController.onAliasChanged(AliasTokens())
|
||||
AppThemeController.onControlChanged(ControlTokens().updateTokens(ControlTokens.ControlType.Button, ButtonTokens()))
|
||||
AppThemeController.updateGlobalTokens(GlobalTokens())
|
||||
AppThemeController.updateAliasTokens(AliasTokens())
|
||||
AppThemeController.updateControlTokens(ControlTokens().updateTokens(ControlTokens.ControlType.Button, ButtonTokens()))
|
||||
},
|
||||
text = "Set Default Theme"
|
||||
)
|
||||
|
@ -82,9 +84,9 @@ class V2BasicInputsActivity : DemoActivity() {
|
|||
style = ButtonStyle.OutlinedButton,
|
||||
size = ButtonSize.Medium,
|
||||
onClick = {
|
||||
AppThemeController.onGlobalChanged(MyGlobalTokens())
|
||||
AppThemeController.onAliasChanged(MyAliasTokens(MyGlobalTokens()))
|
||||
AppThemeController.onControlChanged(ControlTokens().updateTokens(ControlTokens.ControlType.Button, MyButtonTokens()))
|
||||
AppThemeController.updateGlobalTokens(MyGlobalTokens())
|
||||
AppThemeController.updateAliasTokens(MyAliasTokens(MyGlobalTokens()))
|
||||
AppThemeController.updateControlTokens(ControlTokens().updateTokens(ControlTokens.ControlType.Button, MyButtonTokens()))
|
||||
},
|
||||
text = "Set New Theme"
|
||||
)
|
||||
|
@ -96,14 +98,16 @@ class V2BasicInputsActivity : DemoActivity() {
|
|||
|
||||
LazyColumn(verticalArrangement = Arrangement.spacedBy(10.dp)) {
|
||||
item {
|
||||
Text("Default Button from provided base token & Auto theme")
|
||||
Text("Default Button from provided base token & Auto theme",
|
||||
color = aliasTokens.neutralForegroundColor[AliasTokens.NeutralForegroundColorTokens.Foreground1].value(themeMode))
|
||||
FluentTheme {
|
||||
CreateButtons()
|
||||
}
|
||||
}
|
||||
|
||||
item {
|
||||
Text("Button with Selected Theme and Colorful mode")
|
||||
Text("Button with Selected Theme and Colorful mode",
|
||||
color = aliasTokens.neutralForegroundColor[AliasTokens.NeutralForegroundColorTokens.Foreground1].value(themeMode))
|
||||
FluentTheme(
|
||||
globalTokens = globalTokens,
|
||||
aliasTokens = aliasTokens,
|
||||
|
@ -124,11 +128,13 @@ class V2BasicInputsActivity : DemoActivity() {
|
|||
}
|
||||
}
|
||||
item {
|
||||
FluentTheme(globalTokens = globalTokens, aliasTokens = aliasTokens, controlTokens = controlTokens) {
|
||||
Text("Button with selected theme, auto mode and default control token")
|
||||
FluentTheme(globalTokens = globalTokens, aliasTokens = aliasTokens) {
|
||||
Text("Button with selected theme, auto mode and default control token",
|
||||
color = aliasTokens.neutralForegroundColor[AliasTokens.NeutralForegroundColorTokens.Foreground1].value(themeMode))
|
||||
CreateButtons()
|
||||
|
||||
Text("Button with selected theme, auto mode and overridden control token")
|
||||
Text("Button with selected theme, auto mode and overridden control token",
|
||||
color = aliasTokens.neutralForegroundColor[AliasTokens.NeutralForegroundColorTokens.Foreground1].value(themeMode))
|
||||
CreateButtons(MyButtonTokens())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,6 +31,7 @@ dependencies {
|
|||
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
||||
api project(':fluentui_calendar')
|
||||
api project(':fluentui_ccb')
|
||||
api project(':fluentui_controls')
|
||||
api project(':fluentui_core')
|
||||
api project(':fluentui_drawer')
|
||||
api project(':fluentui_listitem')
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
* fluentui_drawer and FluentUI should increment their respective version ids
|
||||
*/
|
||||
project.ext.fluentui_calendar_versionid='0.0.23'
|
||||
project.ext.fluentui_controls_versionid='0.1.0'
|
||||
project.ext.fluentui_core_versionid='0.1.0'
|
||||
project.ext.fluentui_listitem_versionid='0.0.23'
|
||||
project.ext.fluentui_tablayout_versionid='0.0.23'
|
||||
|
@ -26,6 +27,7 @@ project.ext.fluentui_persona_versionid='0.0.23'
|
|||
project.ext.fluentui_progress_versionid='0.0.23'
|
||||
project.ext.FluentUI_versionid='0.1.0'
|
||||
project.ext.fluentui_calendar_version_code=23
|
||||
project.ext.fluentui_controls_version_code=1
|
||||
project.ext.fluentui_core_version_code=23
|
||||
project.ext.fluentui_listitem_version_code=23
|
||||
project.ext.fluentui_tablayout_version_code=23
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
/build
|
|
@ -0,0 +1,71 @@
|
|||
apply plugin: 'com.android.library'
|
||||
apply plugin: 'kotlin-android'
|
||||
|
||||
apply from: '../config.gradle'
|
||||
apply from: '../publish.gradle'
|
||||
|
||||
android {
|
||||
compileSdkVersion constants.compileSdkVersion
|
||||
defaultConfig {
|
||||
minSdkVersion constants.minSdkVersion
|
||||
targetSdkVersion constants.targetSdkVersion
|
||||
versionCode project.ext.fluentui_controls_version_code
|
||||
versionName project.ext.fluentui_controls_versionid
|
||||
testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
|
||||
}
|
||||
lintOptions {
|
||||
abortOnError false
|
||||
}
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
testOptions {
|
||||
unitTests {
|
||||
includeAndroidResources = true
|
||||
}
|
||||
}
|
||||
productFlavors {
|
||||
}
|
||||
kotlinOptions {
|
||||
jvmTarget = '1.8'
|
||||
useIR = true
|
||||
}
|
||||
buildFeatures {
|
||||
compose true
|
||||
}
|
||||
composeOptions {
|
||||
kotlinCompilerExtensionVersion composeVersion
|
||||
}
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation fileTree(include: ['*.jar'], dir: 'libs')
|
||||
implementation project(':fluentui_core')
|
||||
|
||||
implementation 'androidx.core:core-ktx:1.7.0'
|
||||
|
||||
implementation("androidx.compose.foundation:foundation:$composeVersion")
|
||||
implementation("androidx.compose.material:material:$composeVersion")
|
||||
implementation("androidx.compose.runtime:runtime:$composeVersion")
|
||||
implementation("androidx.compose.ui:ui:$composeVersion")
|
||||
|
||||
testImplementation 'junit:junit:4.13.2'
|
||||
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
|
||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
|
||||
}
|
||||
|
||||
task sourceJar(type: Jar) {
|
||||
from android.sourceSets.main.java.srcDirs
|
||||
classifier "sources"
|
||||
}
|
||||
|
||||
project.afterEvaluate {
|
||||
project.ext.publishingFunc('fluentui_others')
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
# Add project specific ProGuard rules here.
|
||||
# You can control the set of applied configuration files using the
|
||||
# proguardFiles setting in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
|
||||
# Uncomment this to preserve the line number information for
|
||||
# debugging stack traces.
|
||||
#-keepattributes SourceFile,LineNumberTable
|
||||
|
||||
# If you keep the line number information, uncomment this to
|
||||
# hide the original source file name.
|
||||
#-renamesourcefileattribute SourceFile
|
|
@ -0,0 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
~ Licensed under the MIT License.
|
||||
-->
|
||||
|
||||
<manifest
|
||||
package="com.microsoft.fluentui.controls" />
|
|
@ -1,4 +1,4 @@
|
|||
package com.microsoft.fluentui.button
|
||||
package com.microsoft.fluentui.controls
|
||||
|
||||
import androidx.compose.foundation.*
|
||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
|
@ -0,0 +1,117 @@
|
|||
package com.microsoft.fluentui.controls
|
||||
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.animation.fadeIn
|
||||
import androidx.compose.animation.fadeOut
|
||||
import androidx.compose.foundation.BorderStroke
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.border
|
||||
import androidx.compose.foundation.indication
|
||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.selection.triStateToggleable
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.Icon
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Done
|
||||
import androidx.compose.material.ripple.rememberRipple
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.CompositionLocalProvider
|
||||
import androidx.compose.runtime.compositionLocalOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.Shape
|
||||
import androidx.compose.ui.semantics.Role
|
||||
import androidx.compose.ui.state.ToggleableState
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.microsoft.fluentui.controls.backgroundColor
|
||||
import com.microsoft.fluentui.controls.borderStroke
|
||||
import com.microsoft.fluentui.controls.iconColor
|
||||
import com.microsoft.fluentui.theme.FluentTheme
|
||||
import com.microsoft.fluentui.theme.token.ControlTokens.ControlType
|
||||
import com.microsoft.fluentui.theme.token.controlTokens.CheckBoxInfo
|
||||
import com.microsoft.fluentui.theme.token.controlTokens.CheckBoxTokens
|
||||
|
||||
val LocalCheckBoxTokens = compositionLocalOf { CheckBoxTokens() }
|
||||
val LocalCheckBoxInfo = compositionLocalOf { CheckBoxInfo() }
|
||||
|
||||
@Composable
|
||||
fun CheckBox(enabled: Boolean = true,
|
||||
checked: Boolean = false,
|
||||
onCheckedChanged: (Boolean) -> Unit?,
|
||||
modifier: Modifier = Modifier,
|
||||
checkBoxToken: CheckBoxTokens? = null,
|
||||
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }) {
|
||||
|
||||
val token = checkBoxToken
|
||||
?: FluentTheme.controlTokens.tokens[ControlType.CheckBox] as CheckBoxTokens
|
||||
|
||||
CompositionLocalProvider(
|
||||
LocalCheckBoxTokens provides token,
|
||||
LocalCheckBoxInfo provides CheckBoxInfo(checked)
|
||||
) {
|
||||
val toggleModifier =
|
||||
if (onCheckedChanged != null) {
|
||||
Modifier.triStateToggleable(
|
||||
state = ToggleableState(checked),
|
||||
enabled = enabled,
|
||||
onClick = { onCheckedChanged(!checked) },
|
||||
role = Role.Checkbox,
|
||||
interactionSource = interactionSource,
|
||||
indication = rememberRipple(
|
||||
bounded = false,
|
||||
radius = 24.dp
|
||||
)
|
||||
)
|
||||
} else {
|
||||
Modifier
|
||||
}
|
||||
|
||||
val backgroundColor: Color = backgroundColor(getCheckBoxToken(), getCheckBoxInfo(),
|
||||
enabled, interactionSource)
|
||||
val iconColor: Color = iconColor(getCheckBoxToken(), getCheckBoxInfo(),
|
||||
enabled, interactionSource)
|
||||
val shape: Shape = RoundedCornerShape(getCheckBoxToken().fixedBorderRadius)
|
||||
|
||||
val borders: List<BorderStroke> =
|
||||
borderStroke(getCheckBoxToken(), getCheckBoxInfo(), enabled, interactionSource)
|
||||
var borderModifier: Modifier = Modifier
|
||||
var borderWidth = 0.dp
|
||||
for (border in borders) {
|
||||
borderWidth += border.width
|
||||
borderModifier = borderModifier.border(borderWidth, border.brush, shape)
|
||||
}
|
||||
|
||||
Box(modifier = Modifier.indication(interactionSource, null),
|
||||
contentAlignment = Alignment.Center) {
|
||||
Spacer(modifier = Modifier
|
||||
.size(getCheckBoxToken().fixedSize)
|
||||
.clip(shape)
|
||||
.background(backgroundColor)
|
||||
.then(borderModifier)
|
||||
.then(toggleModifier))
|
||||
AnimatedVisibility(checked, enter = fadeIn(), exit = fadeOut()) {
|
||||
Icon(Icons.Filled.Done,
|
||||
"Done",
|
||||
modifier = Modifier.size(getCheckBoxToken().fixedIconSize),
|
||||
tint = iconColor)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun getCheckBoxToken(): CheckBoxTokens {
|
||||
return LocalCheckBoxTokens.current
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun getCheckBoxInfo(): CheckBoxInfo {
|
||||
return LocalCheckBoxInfo.current
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package com.microsoft.fluentui.button
|
||||
package com.microsoft.fluentui.controls
|
||||
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.foundation.*
|
|
@ -0,0 +1,94 @@
|
|||
package com.microsoft.fluentui.controls
|
||||
|
||||
import androidx.compose.animation.core.animateDpAsState
|
||||
import androidx.compose.animation.core.tween
|
||||
import androidx.compose.foundation.Canvas
|
||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.wrapContentSize
|
||||
import androidx.compose.foundation.selection.selectable
|
||||
import androidx.compose.material.ripple.rememberRipple
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.CompositionLocalProvider
|
||||
import androidx.compose.runtime.compositionLocalOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.drawscope.Fill
|
||||
import androidx.compose.ui.graphics.drawscope.Stroke
|
||||
import androidx.compose.ui.semantics.Role
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.microsoft.fluentui.theme.FluentTheme
|
||||
import com.microsoft.fluentui.theme.token.ControlTokens
|
||||
import com.microsoft.fluentui.theme.token.controlTokens.RadioButtonInfo
|
||||
import com.microsoft.fluentui.theme.token.controlTokens.RadioButtonTokens
|
||||
|
||||
val LocalRadioButtonTokens = compositionLocalOf { RadioButtonTokens() }
|
||||
val LocalRadioButtonInfo = compositionLocalOf { RadioButtonInfo() }
|
||||
|
||||
@Composable
|
||||
fun RadioButton(enabled: Boolean = true,
|
||||
selected: Boolean = false,
|
||||
onClick: (() -> Unit)?,
|
||||
modifier: Modifier = Modifier,
|
||||
radioButtonToken: RadioButtonTokens? = null,
|
||||
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }
|
||||
) {
|
||||
val token = radioButtonToken
|
||||
?: FluentTheme.controlTokens.tokens[ControlTokens.ControlType.RadioButton] as RadioButtonTokens
|
||||
|
||||
CompositionLocalProvider(
|
||||
LocalRadioButtonTokens provides token,
|
||||
LocalRadioButtonInfo provides RadioButtonInfo(selected)
|
||||
) {
|
||||
val dotRadius = animateDpAsState(
|
||||
targetValue = if (selected) getRadioButtonTokens().innerCircleRadius else 0.dp,
|
||||
animationSpec = tween(durationMillis = 100)
|
||||
)
|
||||
|
||||
val selectableModifier = if (onClick != null) {
|
||||
modifier.selectable(selected = selected,
|
||||
enabled = enabled,
|
||||
onClick = onClick,
|
||||
role = Role.RadioButton,
|
||||
interactionSource = interactionSource,
|
||||
indication = rememberRipple(
|
||||
bounded = false,
|
||||
radius = 24.dp
|
||||
)
|
||||
)
|
||||
} else {
|
||||
modifier
|
||||
}
|
||||
|
||||
val outerStrokeColor = backgroundColor(getRadioButtonTokens(), getRadioButtonInfo(),
|
||||
enabled, interactionSource)
|
||||
val innerColor = iconColor(getRadioButtonTokens(), getRadioButtonInfo(),
|
||||
enabled, interactionSource)
|
||||
|
||||
val outerRadius = getRadioButtonTokens().outerCircleRadius
|
||||
val strokeWidth = getRadioButtonTokens().strokeWidthInwards
|
||||
|
||||
Canvas(modifier = Modifier
|
||||
.then(selectableModifier)
|
||||
.size(24.dp)
|
||||
.wrapContentSize(Alignment.Center)) {
|
||||
drawCircle(outerStrokeColor, (outerRadius - (strokeWidth / 2)).toPx(), style = Stroke(1.5.dp.toPx()))
|
||||
|
||||
if (dotRadius.value > 0.dp) {
|
||||
drawCircle(innerColor, (dotRadius.value).toPx(), style = Fill)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Composable
|
||||
fun getRadioButtonTokens(): RadioButtonTokens {
|
||||
return LocalRadioButtonTokens.current
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun getRadioButtonInfo(): RadioButtonInfo {
|
||||
return LocalRadioButtonInfo.current
|
||||
}
|
|
@ -0,0 +1,137 @@
|
|||
package com.microsoft.fluentui.controls
|
||||
|
||||
import androidx.compose.animation.core.TweenSpec
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.gestures.Orientation
|
||||
import androidx.compose.foundation.indication
|
||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.selection.toggleable
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.material.ExperimentalMaterialApi
|
||||
import androidx.compose.material.FractionalThreshold
|
||||
import androidx.compose.material.rememberSwipeableState
|
||||
import androidx.compose.material.ripple.rememberRipple
|
||||
import androidx.compose.material.swipeable
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.platform.LocalDensity
|
||||
import androidx.compose.ui.platform.LocalLayoutDirection
|
||||
import androidx.compose.ui.semantics.Role
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.IntOffset
|
||||
import androidx.compose.ui.unit.LayoutDirection
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.microsoft.fluentui.controls.backgroundColor
|
||||
import com.microsoft.fluentui.controls.iconColor
|
||||
import com.microsoft.fluentui.theme.FluentTheme
|
||||
import com.microsoft.fluentui.theme.token.ControlTokens.ControlType
|
||||
import com.microsoft.fluentui.theme.token.controlTokens.ToggleSwitchInfo
|
||||
import com.microsoft.fluentui.theme.token.controlTokens.ToggleSwitchTokens
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
val LocalToggleSwitchTokens = compositionLocalOf { ToggleSwitchTokens() }
|
||||
val LocalToggleSwitchInfo = compositionLocalOf { ToggleSwitchInfo() }
|
||||
|
||||
@OptIn(ExperimentalMaterialApi::class)
|
||||
@Composable
|
||||
fun ToggleSwitch(enabledSwitch: Boolean = true,
|
||||
checkedState: Boolean = false,
|
||||
onValueChange: ((Boolean) -> Unit)? = null,
|
||||
switchTokens: ToggleSwitchTokens? = null,
|
||||
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }
|
||||
) {
|
||||
|
||||
val token = switchTokens
|
||||
?: FluentTheme.controlTokens.tokens[ControlType.ToggleSwitch] as ToggleSwitchTokens
|
||||
|
||||
CompositionLocalProvider(
|
||||
LocalToggleSwitchTokens provides token,
|
||||
LocalToggleSwitchInfo provides ToggleSwitchInfo(checkedState)
|
||||
) {
|
||||
|
||||
val backgroundColor: Color = backgroundColor(getToggleSwitchToken(), getToggleSwitchInfo(),
|
||||
enabledSwitch, interactionSource)
|
||||
val foregroundColor: Color = iconColor(getToggleSwitchToken(), getToggleSwitchInfo(),
|
||||
enabledSwitch, interactionSource)
|
||||
val padding: Dp = getToggleSwitchToken().paddingTrack
|
||||
|
||||
|
||||
// Swipe Logic
|
||||
val knobMovementWidth = 23.dp
|
||||
val minBound = with(LocalDensity.current) { padding.toPx() }
|
||||
val maxBound = with(LocalDensity.current) { knobMovementWidth.toPx() }
|
||||
val AnimationSpec = TweenSpec<Float>(durationMillis = 100)
|
||||
val swipeState = rememberSwipeableState(checkedState, AnimationSpec, confirmStateChange = { true })
|
||||
val isRtl = LocalLayoutDirection.current == LayoutDirection.Rtl
|
||||
|
||||
val forceAnimationCheck = remember { mutableStateOf(false) }
|
||||
LaunchedEffect(checkedState, forceAnimationCheck.value) {
|
||||
if (checkedState != swipeState.currentValue) {
|
||||
swipeState.animateTo(checkedState)
|
||||
}
|
||||
}
|
||||
DisposableEffect(swipeState.currentValue) {
|
||||
if (checkedState != swipeState.currentValue) {
|
||||
onValueChange?.invoke(swipeState.currentValue)
|
||||
forceAnimationCheck.value = !forceAnimationCheck.value
|
||||
}
|
||||
onDispose { }
|
||||
}
|
||||
|
||||
// Toggle Logic
|
||||
val toggleModifier =
|
||||
if (onValueChange != null) {
|
||||
Modifier.toggleable(value = getToggleSwitchInfo().checked,
|
||||
enabled = enabledSwitch,
|
||||
role = Role.Switch,
|
||||
onValueChange = onValueChange,
|
||||
interactionSource = interactionSource,
|
||||
indication = null)
|
||||
} else
|
||||
Modifier
|
||||
|
||||
// UI Implementation
|
||||
Box(modifier = Modifier
|
||||
.then(toggleModifier)
|
||||
.swipeable(
|
||||
state = swipeState,
|
||||
anchors = mapOf(minBound to false, maxBound to true),
|
||||
thresholds = { _, _ -> FractionalThreshold(0.5f) },
|
||||
orientation = Orientation.Horizontal,
|
||||
enabled = enabledSwitch && onValueChange != null,
|
||||
reverseDirection = isRtl,
|
||||
interactionSource = interactionSource,
|
||||
resistance = null
|
||||
), contentAlignment = Alignment.CenterStart) {
|
||||
Box(modifier = Modifier
|
||||
.width(getToggleSwitchToken().fixedTrackWidth)
|
||||
.height(getToggleSwitchToken().fixedTrackHeight)
|
||||
.clip(CircleShape)
|
||||
.background(backgroundColor))
|
||||
Spacer(modifier = Modifier
|
||||
.offset { IntOffset(swipeState.offset.value.roundToInt(), 0) }
|
||||
.indication(
|
||||
interactionSource = interactionSource,
|
||||
indication = rememberRipple(false,
|
||||
getToggleSwitchToken().knobRippleRadius)
|
||||
)
|
||||
.size(getToggleSwitchToken().fixedKnobDiameter)
|
||||
.clip(CircleShape)
|
||||
.background(foregroundColor))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun getToggleSwitchToken(): ToggleSwitchTokens {
|
||||
return LocalToggleSwitchTokens.current
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun getToggleSwitchInfo(): ToggleSwitchInfo {
|
||||
return LocalToggleSwitchInfo.current
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package com.microsoft.fluentui.button
|
||||
package com.microsoft.fluentui.controls
|
||||
|
||||
import androidx.compose.foundation.BorderStroke
|
||||
import androidx.compose.foundation.interaction.InteractionSource
|
||||
|
@ -12,10 +12,7 @@ import com.microsoft.fluentui.theme.token.ControlInfo
|
|||
import com.microsoft.fluentui.theme.token.ControlToken
|
||||
import com.microsoft.fluentui.theme.token.StateBorderStroke
|
||||
import com.microsoft.fluentui.theme.token.StateColor
|
||||
import com.microsoft.fluentui.theme.token.controlTokens.ButtonInfo
|
||||
import com.microsoft.fluentui.theme.token.controlTokens.ButtonTokens
|
||||
import com.microsoft.fluentui.theme.token.controlTokens.FABInfo
|
||||
import com.microsoft.fluentui.theme.token.controlTokens.FABTokens
|
||||
import com.microsoft.fluentui.theme.token.controlTokens.*
|
||||
import java.security.InvalidParameterException
|
||||
|
||||
@Composable
|
||||
|
@ -53,6 +50,9 @@ fun backgroundColor(
|
|||
when (tokens) {
|
||||
is ButtonTokens -> tokens.backgroundColor(info as ButtonInfo)
|
||||
is FABTokens -> tokens.backgroundColor(info as FABInfo)
|
||||
is ToggleSwitchTokens -> tokens.TrackColor(info as ToggleSwitchInfo)
|
||||
is CheckBoxTokens -> tokens.backgroundColor(info as CheckBoxInfo)
|
||||
is RadioButtonTokens -> tokens.backgroundColor(info as RadioButtonInfo)
|
||||
else -> throw InvalidParameterException()
|
||||
}
|
||||
|
||||
|
@ -70,6 +70,9 @@ fun iconColor(
|
|||
when (tokens) {
|
||||
is ButtonTokens -> tokens.iconColor(info as ButtonInfo)
|
||||
is FABTokens -> tokens.iconColor(info as FABInfo)
|
||||
is ToggleSwitchTokens -> tokens.KnobColor(info as ToggleSwitchInfo)
|
||||
is CheckBoxTokens -> tokens.iconColor(info as CheckBoxInfo)
|
||||
is RadioButtonTokens -> tokens.iconColor(info as RadioButtonInfo)
|
||||
else -> throw InvalidParameterException()
|
||||
}
|
||||
|
||||
|
@ -104,6 +107,7 @@ fun borderStroke(
|
|||
when (tokens) {
|
||||
is ButtonTokens -> tokens.borderStroke(info as ButtonInfo)
|
||||
is FABTokens -> tokens.borderStroke(info as FABInfo)
|
||||
is CheckBoxTokens -> tokens.borderStroke(info as CheckBoxInfo)
|
||||
else -> throw InvalidParameterException()
|
||||
}
|
||||
|
|
@ -63,15 +63,15 @@ object AppThemeController : ViewModel() {
|
|||
var aliasTokens: MutableLiveData<AliasTokens> = MutableLiveData(AliasTokens())
|
||||
var controlTokens: MutableLiveData<ControlTokens> = MutableLiveData(ControlTokens())
|
||||
|
||||
fun onGlobalChanged(overrideGlobalTokens: GlobalTokens) {
|
||||
fun updateGlobalTokens(overrideGlobalTokens: GlobalTokens) {
|
||||
globalTokens.value = overrideGlobalTokens
|
||||
}
|
||||
|
||||
fun onAliasChanged(overrideAliasTokens: AliasTokens) {
|
||||
fun updateAliasTokens(overrideAliasTokens: AliasTokens) {
|
||||
aliasTokens.value = overrideAliasTokens
|
||||
}
|
||||
|
||||
fun onControlChanged(overrideControlTokens: ControlTokens) {
|
||||
fun updateControlTokens(overrideControlTokens: ControlTokens) {
|
||||
controlTokens.value = overrideControlTokens
|
||||
}
|
||||
|
||||
|
|
|
@ -6,8 +6,7 @@
|
|||
package com.microsoft.fluentui.theme.token
|
||||
|
||||
import androidx.compose.runtime.compositionLocalOf
|
||||
import com.microsoft.fluentui.theme.token.controlTokens.ButtonTokens
|
||||
import com.microsoft.fluentui.theme.token.controlTokens.FABTokens
|
||||
import com.microsoft.fluentui.theme.token.controlTokens.*
|
||||
|
||||
interface ControlInfo
|
||||
|
||||
|
@ -18,6 +17,9 @@ class ControlTokens {
|
|||
enum class ControlType {
|
||||
Button,
|
||||
FloatingActionButton,
|
||||
ToggleSwitch,
|
||||
CheckBox,
|
||||
RadioButton
|
||||
}
|
||||
|
||||
val tokens: TokenSet<ControlType, ControlToken> by lazy {
|
||||
|
@ -25,6 +27,9 @@ class ControlTokens {
|
|||
when (token) {
|
||||
ControlType.Button -> ButtonTokens()
|
||||
ControlType.FloatingActionButton -> FABTokens()
|
||||
ControlType.ToggleSwitch -> ToggleSwitchTokens()
|
||||
ControlType.CheckBox -> CheckBoxTokens()
|
||||
ControlType.RadioButton -> RadioButtonTokens()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,95 @@
|
|||
package com.microsoft.fluentui.theme.token.controlTokens
|
||||
|
||||
import android.os.Parcelable
|
||||
import androidx.compose.foundation.BorderStroke
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.microsoft.fluentui.theme.FluentTheme
|
||||
import com.microsoft.fluentui.theme.token.*
|
||||
import kotlinx.parcelize.Parcelize
|
||||
|
||||
data class CheckBoxInfo(
|
||||
val checked: Boolean = false,
|
||||
) : ControlInfo
|
||||
|
||||
@Parcelize
|
||||
open class CheckBoxTokens : ControlToken, Parcelable {
|
||||
|
||||
companion object {
|
||||
const val Type: String = "Checkbox"
|
||||
}
|
||||
|
||||
val fixedSize: Dp = 20.dp
|
||||
val fixedIconSize: Dp = 12.dp
|
||||
val fixedBorderRadius: Dp = 4.dp
|
||||
|
||||
@Composable
|
||||
open fun backgroundColor(checkBoxInfo: CheckBoxInfo): StateColor {
|
||||
return when (checkBoxInfo.checked) {
|
||||
true -> StateColor(
|
||||
rest = FluentTheme.aliasToken.brandBackgroundColor[AliasTokens.BrandBackgroundColorTokens.BrandBackground1].value(
|
||||
themeMode = FluentTheme.themeMode
|
||||
),
|
||||
pressed = FluentTheme.aliasToken.brandBackgroundColor[AliasTokens.BrandBackgroundColorTokens.BrandBackground1].value(
|
||||
themeMode = FluentTheme.themeMode
|
||||
),
|
||||
disabled = FluentTheme.aliasToken.brandBackgroundColor[AliasTokens.BrandBackgroundColorTokens.BrandBackgroundDisabled].value(
|
||||
themeMode = FluentTheme.themeMode
|
||||
)
|
||||
)
|
||||
false -> StateColor()
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
open fun iconColor(checkBoxInfo: CheckBoxInfo): StateColor {
|
||||
return when (checkBoxInfo.checked) {
|
||||
true -> StateColor(
|
||||
rest = FluentTheme.aliasToken.neutralForegroundColor[AliasTokens.NeutralForegroundColorTokens.ForegroundOnColor].value(
|
||||
themeMode = FluentTheme.themeMode
|
||||
),
|
||||
pressed = FluentTheme.aliasToken.neutralForegroundColor[AliasTokens.NeutralForegroundColorTokens.ForegroundOnColor].value(
|
||||
themeMode = FluentTheme.themeMode
|
||||
),
|
||||
disabled = FluentTheme.aliasToken.brandBackgroundColor[AliasTokens.BrandBackgroundColorTokens.BrandBackgroundInvertedDisabled].value(
|
||||
themeMode = FluentTheme.themeMode
|
||||
)
|
||||
)
|
||||
false -> StateColor()
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
open fun borderStroke(checkBoxInfo: CheckBoxInfo): StateBorderStroke {
|
||||
return when (checkBoxInfo.checked) {
|
||||
true -> StateBorderStroke()
|
||||
false -> StateBorderStroke(
|
||||
rest = listOf(
|
||||
BorderStroke(
|
||||
1.5.dp,
|
||||
FluentTheme.aliasToken.neutralStrokeColor[AliasTokens.NeutralStrokeColorTokens.StrokeAccessible].value(
|
||||
themeMode = FluentTheme.themeMode
|
||||
)
|
||||
)
|
||||
),
|
||||
pressed = listOf(
|
||||
BorderStroke(
|
||||
1.5.dp,
|
||||
FluentTheme.aliasToken.neutralStrokeColor[AliasTokens.NeutralStrokeColorTokens.StrokeAccessible].value(
|
||||
themeMode = FluentTheme.themeMode
|
||||
)
|
||||
)
|
||||
),
|
||||
disabled = listOf(
|
||||
BorderStroke(
|
||||
1.5.dp,
|
||||
FluentTheme.aliasToken.neutralStrokeColor[AliasTokens.NeutralStrokeColorTokens.StrokeDisabled].value(
|
||||
themeMode = FluentTheme.themeMode
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
package com.microsoft.fluentui.theme.token.controlTokens
|
||||
|
||||
import android.os.Parcelable
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.microsoft.fluentui.theme.FluentTheme
|
||||
import com.microsoft.fluentui.theme.token.AliasTokens
|
||||
import com.microsoft.fluentui.theme.token.ControlInfo
|
||||
import com.microsoft.fluentui.theme.token.ControlToken
|
||||
import com.microsoft.fluentui.theme.token.StateColor
|
||||
import kotlinx.parcelize.Parcelize
|
||||
|
||||
data class RadioButtonInfo(
|
||||
val selected: Boolean = false,
|
||||
) : ControlInfo
|
||||
|
||||
@Parcelize
|
||||
open class RadioButtonTokens : ControlToken, Parcelable {
|
||||
|
||||
companion object {
|
||||
const val Type: String = "Checkbox"
|
||||
}
|
||||
|
||||
open var innerCircleRadius = 5.dp
|
||||
open var outerCircleRadius = 10.dp
|
||||
open var strokeWidthInwards = 1.5.dp
|
||||
|
||||
@Composable
|
||||
open fun backgroundColor(radioButtonInfo: RadioButtonInfo): StateColor {
|
||||
return when (radioButtonInfo.selected) {
|
||||
true -> StateColor(
|
||||
rest = FluentTheme.aliasToken.brandBackgroundColor[AliasTokens.BrandBackgroundColorTokens.BrandBackground1].value(
|
||||
themeMode = FluentTheme.themeMode
|
||||
),
|
||||
pressed = FluentTheme.aliasToken.brandBackgroundColor[AliasTokens.BrandBackgroundColorTokens.BrandBackground1].value(
|
||||
themeMode = FluentTheme.themeMode
|
||||
),
|
||||
disabled = FluentTheme.aliasToken.brandBackgroundColor[AliasTokens.BrandBackgroundColorTokens.BrandBackgroundDisabled].value(
|
||||
themeMode = FluentTheme.themeMode
|
||||
)
|
||||
)
|
||||
false -> StateColor(
|
||||
rest = FluentTheme.aliasToken.neutralStrokeColor[AliasTokens.NeutralStrokeColorTokens.StrokeAccessible].value(
|
||||
themeMode = FluentTheme.themeMode
|
||||
),
|
||||
disabled = FluentTheme.aliasToken.neutralStrokeColor[AliasTokens.NeutralStrokeColorTokens.StrokeDisabled].value(
|
||||
themeMode = FluentTheme.themeMode
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
open fun iconColor(radioButtonInfo: RadioButtonInfo): StateColor {
|
||||
return when (radioButtonInfo.selected) {
|
||||
true -> StateColor(
|
||||
rest = FluentTheme.aliasToken.brandForegroundColor[AliasTokens.BrandForegroundColorTokens.BrandForeground1].value(
|
||||
themeMode = FluentTheme.themeMode
|
||||
),
|
||||
disabled = FluentTheme.aliasToken.brandBackgroundColor[AliasTokens.BrandBackgroundColorTokens.BrandBackgroundDisabled].value(
|
||||
themeMode = FluentTheme.themeMode
|
||||
)
|
||||
)
|
||||
false -> StateColor()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,86 @@
|
|||
package com.microsoft.fluentui.theme.token.controlTokens
|
||||
|
||||
import android.os.Parcelable
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.microsoft.fluentui.theme.FluentTheme.aliasToken
|
||||
import com.microsoft.fluentui.theme.FluentTheme.themeMode
|
||||
import com.microsoft.fluentui.theme.token.AliasTokens
|
||||
import com.microsoft.fluentui.theme.token.ControlInfo
|
||||
import com.microsoft.fluentui.theme.token.ControlToken
|
||||
import com.microsoft.fluentui.theme.token.StateColor
|
||||
import kotlinx.parcelize.Parcelize
|
||||
|
||||
data class ToggleSwitchInfo(
|
||||
val checked: Boolean = true,
|
||||
) : ControlInfo
|
||||
|
||||
@Parcelize
|
||||
open class ToggleSwitchTokens : ControlToken, Parcelable {
|
||||
|
||||
companion object {
|
||||
const val Type: String = "ToggleSwitch"
|
||||
}
|
||||
|
||||
@Composable
|
||||
open fun TrackColor(switchInfo: ToggleSwitchInfo): StateColor {
|
||||
return when (switchInfo.checked) {
|
||||
true -> StateColor(
|
||||
rest = aliasToken.brandBackgroundColor[AliasTokens.BrandBackgroundColorTokens.BrandBackground1].value(
|
||||
themeMode = themeMode
|
||||
),
|
||||
pressed = aliasToken.brandBackgroundColor[AliasTokens.BrandBackgroundColorTokens.BrandBackground1].value(
|
||||
themeMode = themeMode
|
||||
),
|
||||
disabled = aliasToken.brandBackgroundColor[AliasTokens.BrandBackgroundColorTokens.BrandBackgroundDisabled].value(
|
||||
themeMode = themeMode
|
||||
)
|
||||
)
|
||||
false -> StateColor(
|
||||
rest = aliasToken.neutralBackgroundColor[AliasTokens.NeutralBackgroundColorTokens.Background5].value(
|
||||
themeMode = themeMode
|
||||
),
|
||||
pressed = aliasToken.neutralBackgroundColor[AliasTokens.NeutralBackgroundColorTokens.Background5].value(
|
||||
themeMode = themeMode
|
||||
),
|
||||
disabled = aliasToken.neutralBackgroundColor[AliasTokens.NeutralBackgroundColorTokens.Background5].value(
|
||||
themeMode = themeMode
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
open fun KnobColor(switchInfo: ToggleSwitchInfo): StateColor {
|
||||
return when (switchInfo.checked) {
|
||||
true -> StateColor(
|
||||
rest = aliasToken.brandBackgroundColor[AliasTokens.BrandBackgroundColorTokens.BrandBackgroundInverted].value(
|
||||
themeMode = themeMode
|
||||
),
|
||||
pressed = aliasToken.brandBackgroundColor[AliasTokens.BrandBackgroundColorTokens.BrandBackgroundInverted].value(
|
||||
themeMode = themeMode
|
||||
),
|
||||
disabled = aliasToken.brandBackgroundColor[AliasTokens.BrandBackgroundColorTokens.BrandBackgroundInvertedDisabled].value(
|
||||
themeMode = themeMode
|
||||
)
|
||||
)
|
||||
false -> StateColor(
|
||||
rest = aliasToken.brandBackgroundColor[AliasTokens.BrandBackgroundColorTokens.BrandBackgroundInverted].value(
|
||||
themeMode = themeMode
|
||||
),
|
||||
pressed = aliasToken.brandBackgroundColor[AliasTokens.BrandBackgroundColorTokens.BrandBackgroundInverted].value(
|
||||
themeMode = themeMode
|
||||
),
|
||||
disabled = aliasToken.brandBackgroundColor[AliasTokens.BrandBackgroundColorTokens.BrandBackgroundInvertedDisabled].value(
|
||||
themeMode = themeMode
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
open val fixedTrackHeight = 32.dp
|
||||
open val fixedTrackWidth = 52.dp
|
||||
open val fixedKnobDiameter = 26.dp
|
||||
open val knobRippleRadius = 24.dp
|
||||
open val paddingTrack = 3.dp
|
||||
}
|
|
@ -34,20 +34,6 @@ android {
|
|||
}
|
||||
productFlavors {
|
||||
}
|
||||
kotlinOptions {
|
||||
jvmTarget = '1.8'
|
||||
useIR = true
|
||||
}
|
||||
buildFeatures {
|
||||
compose true
|
||||
}
|
||||
composeOptions {
|
||||
kotlinCompilerExtensionVersion composeVersion
|
||||
}
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
}
|
||||
|
||||
gradle.taskGraph.whenReady { taskGraph ->
|
||||
|
@ -71,11 +57,6 @@ dependencies {
|
|||
implementation "com.splitwise:tokenautocomplete:$tokenautocompleteVersion"
|
||||
implementation "com.microsoft.device:dualscreen-layout:$duoVersion"
|
||||
|
||||
implementation("androidx.compose.foundation:foundation:$composeVersion")
|
||||
implementation("androidx.compose.material:material:$composeVersion")
|
||||
implementation("androidx.compose.runtime:runtime:$composeVersion")
|
||||
implementation("androidx.compose.ui:ui:$composeVersion")
|
||||
|
||||
testImplementation "junit:junit:$junitVersion"
|
||||
androidTestImplementation "androidx.test.ext:junit:$extJunitVersion"
|
||||
androidTestImplementation "androidx.test.espresso:espresso-core:$espressoVersion"
|
||||
|
|
|
@ -13,3 +13,4 @@ include ':fluentui_tablayout'
|
|||
include ':fluentui_others'
|
||||
include ':FluentUI'
|
||||
include ':fluentui_ccb'
|
||||
include ':fluentui_controls'
|
||||
|
|
Загрузка…
Ссылка в новой задаче