feat: update demo

This commit is contained in:
2024-01-11 23:12:46 +08:00
parent 5616bb29e2
commit c213f5d507
3 changed files with 327 additions and 35 deletions

View File

@@ -21,18 +21,20 @@
*/ */
@file:OptIn(ExperimentalFoundationApi::class) @file:OptIn(ExperimentalFoundationApi::class)
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.pager.HorizontalPager import androidx.compose.foundation.pager.HorizontalPager
import androidx.compose.foundation.pager.rememberPagerState import androidx.compose.foundation.pager.rememberPagerState
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.Stable import androidx.compose.runtime.Stable
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
@@ -41,34 +43,79 @@ import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalUriHandler
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.em
import com.highcapable.betterandroid.compose.extension.ui.ComponentPadding
import com.highcapable.betterandroid.compose.multiplatform.backpress.BackHandler
import com.highcapable.betterandroid.compose.multiplatform.systembar.PlatformSystemBarStyle
import com.highcapable.betterandroid.compose.multiplatform.systembar.rememberSystemBarsController
import com.highcapable.betterandroid.compose.multiplatform.systembar.setStyle
import com.highcapable.flexiui.FlexiTheme import com.highcapable.flexiui.FlexiTheme
import com.highcapable.flexiui.component.AreaBox import com.highcapable.flexiui.component.AreaBox
import com.highcapable.flexiui.component.AreaColumn import com.highcapable.flexiui.component.AreaColumn
import com.highcapable.flexiui.component.Button
import com.highcapable.flexiui.component.DropdownList
import com.highcapable.flexiui.component.DropdownMenuItem
import com.highcapable.flexiui.component.HorizontalItemBox
import com.highcapable.flexiui.component.Icon import com.highcapable.flexiui.component.Icon
import com.highcapable.flexiui.component.IconDefaults import com.highcapable.flexiui.component.IconDefaults
import com.highcapable.flexiui.component.NavigationBarItem import com.highcapable.flexiui.component.NavigationBarItem
import com.highcapable.flexiui.component.NavigationBarRow import com.highcapable.flexiui.component.NavigationBarRow
import com.highcapable.flexiui.component.PrimaryAppBar import com.highcapable.flexiui.component.PrimaryAppBar
import com.highcapable.flexiui.component.Scaffold import com.highcapable.flexiui.component.Scaffold
import com.highcapable.flexiui.component.SecondaryAppBar
import com.highcapable.flexiui.component.Surface
import com.highcapable.flexiui.component.SwitchItem import com.highcapable.flexiui.component.SwitchItem
import com.highcapable.flexiui.component.Text import com.highcapable.flexiui.component.Text
import com.highcapable.flexiui.resources.FlexiIcons import com.highcapable.flexiui.resources.FlexiIcons
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@Stable private const val PROJECT_URL = "https://github.com/BetterAndroid/FlexiUI"
data class AppPreferences(
var darkMode: MutableState<Boolean> = mutableStateOf(false),
var followSystemDarkMode: MutableState<Boolean> = mutableStateOf(false)
)
@Composable
private fun FlexiDemoTheme(content: @Composable () -> Unit) {
val systemBars = rememberSystemBarsController()
val darkMode by remember { Preferences.darkMode }
val followSystemDarkMode by remember { Preferences.followSystemDarkMode }
val currentDarkMode = if (followSystemDarkMode) isSystemInDarkTheme() else darkMode
val colorScheme by remember { Preferences.colorScheme }
systemBars.setStyle(
if (currentDarkMode)
PlatformSystemBarStyle.DarkTransparent
else PlatformSystemBarStyle.LightTransparent
)
FlexiTheme(
colors = colorScheme.toColors(currentDarkMode),
content = content
)
}
/** Simulate a router. */
@Stable @Stable
private val Preferences = AppPreferences() private var CurrentPage = mutableStateOf(0)
@Composable
private fun rememberCurrentPage() = remember { CurrentPage }
@Composable
private fun Page(page: Int, content: @Composable () -> Unit) {
val currentPage by remember { CurrentPage }
AnimatedVisibility(
visible = currentPage == page,
enter = fadeIn(),
exit = fadeOut()
) { content() }
}
@Composable @Composable
fun App() { fun App() {
FlexiTheme { FlexiDemoTheme {
MainScreen() // Surface will keep the content background color when animation.
Surface(padding = ComponentPadding()) {
Page(0) { MainScreen() }
Page(1) { SecondaryScreen() }
}
} }
} }
@@ -77,13 +124,14 @@ fun MainScreen() {
val pageCount = 2 val pageCount = 2
val state = rememberPagerState(pageCount = { pageCount }) val state = rememberPagerState(pageCount = { pageCount })
val scope = rememberCoroutineScope() val scope = rememberCoroutineScope()
val uriHandler = LocalUriHandler.current
Scaffold( Scaffold(
appBar = { appBar = {
PrimaryAppBar( PrimaryAppBar(
title = { Text("Flexi UI Demo") }, title = { Text("Flexi UI Demo") },
actions = { actions = {
ActionIconButton( ActionIconButton(
onClick = { /* TODO */ } onClick = { uriHandler.openUri(PROJECT_URL) }
) { Icon(FlexiIcons.GitHub) } ) { Icon(FlexiIcons.GitHub) }
} }
) )
@@ -127,24 +175,61 @@ fun MainHomePage() {
} }
PrimarySpacer() PrimarySpacer()
AreaColumn(modifier = Modifier.fillMaxWidth()) { AreaColumn(modifier = Modifier.fillMaxWidth()) {
var colorScheme by remember { Preferences.colorScheme }
var darkMode by remember { Preferences.darkMode } var darkMode by remember { Preferences.darkMode }
var followSystemDarkMode by remember { Preferences.followSystemDarkMode } var followSystemDarkMode by remember { Preferences.followSystemDarkMode }
SecondaryText("Theme Style") SecondaryText("Theme Style")
PrimarySpacer() PrimarySpacer()
SwitchItem( AnimatedVisibility(visible = !followSystemDarkMode) {
checked = darkMode, Column {
onCheckedChange = { darkMode = it } SwitchItem(
) { Text("Enable night mode") } checked = darkMode,
SecondarySpacer() onCheckedChange = { darkMode = it }
SecondaryText("Manually switch the current theme to night mode.") ) { Text("Enable night mode") }
PrimarySpacer() SecondarySpacer()
SecondaryText("Manually switch the current theme to night mode.")
PrimarySpacer()
}
}
SwitchItem( SwitchItem(
checked = followSystemDarkMode, checked = followSystemDarkMode,
onCheckedChange = { followSystemDarkMode = it } onCheckedChange = { followSystemDarkMode = it }
) { Text("Follow system night mode") } ) { Text("Follow system night mode") }
SecondarySpacer() SecondarySpacer()
SecondaryText("Follow the system theme to switch day and night mode.") SecondaryText("Follow the system theme to switch day and night mode.")
PrimarySpacer()
Row(
modifier = Modifier.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically
) {
var expanded by remember { mutableStateOf(false) }
Text("Current Theme")
PrimarySpacer()
DropdownList(
modifier = Modifier.fillMaxWidth(),
expanded = expanded,
onExpandedChange = { expanded = it },
text = { Text(colorScheme.toName()) },
) {
colorSchemes().forEach {
DropdownMenuItem(
actived = colorScheme == it,
onClick = {
expanded = false
colorScheme = it
}
) { Text(it.toName()) }
}
}
}
} }
PrimarySpacer()
var currentPage by rememberCurrentPage()
HorizontalItemBox(
onClick = { currentPage = 1 },
title = { Text("Single Page Demo") },
subtitle = { Text("Open a single page.") }
)
} }
} }
@@ -158,20 +243,32 @@ fun MainComponentPage() {
} }
@Composable @Composable
private fun PrimarySpacer() { fun SecondaryScreen() {
Spacer(modifier = Modifier.height(10.dp)) var currentPage by rememberCurrentPage()
} Scaffold(
appBar = {
@Composable SecondaryAppBar(
private fun SecondarySpacer() { title = { Text("Single Page") },
Spacer(modifier = Modifier.height(5.dp)) navigationIcon = {
} NavigationIconButton(onClick = { currentPage = 0 })
}
@Composable )
private fun SecondaryText(text: String) { }
Text( ) {
text = text, AreaColumn(modifier = Modifier.fillMaxWidth()) {
color = FlexiTheme.colors.textSecondary, Text(
style = FlexiTheme.typography.secondary """
) Now, you open a separate secondary page.
You can click the button below to back to the homepage.
""".trimIndent(),
style = FlexiTheme.typography.primary.copy(lineHeight = 2.em)
)
PrimarySpacer()
Button(
modifier = Modifier.fillMaxWidth(),
onClick = { currentPage = 0 }
) { Text("Take Me Home") }
}
BackHandler { currentPage = 0 }
}
} }

View File

@@ -0,0 +1,50 @@
/*
* Flexi UI - A flexible and useful UI component library.
* Copyright (C) 2019-2024 HighCapable
* https://github.com/BetterAndroid/FlexiUI
*
* Apache License Version 2.0
*
* 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.
*
* This file is created by fankes on 2024/1/11.
*/
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.size
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import com.highcapable.flexiui.FlexiTheme
import com.highcapable.flexiui.component.Text
// TODO: Some components can be include to Flexi UI (To be determined)
@Composable
fun PrimarySpacer() {
Spacer(modifier = Modifier.size(10.dp))
}
@Composable
fun SecondarySpacer() {
Spacer(modifier = Modifier.size(5.dp))
}
@Composable
fun SecondaryText(text: String) {
Text(
text = text,
color = FlexiTheme.colors.textSecondary,
style = FlexiTheme.typography.secondary
)
}

View File

@@ -0,0 +1,145 @@
/*
* Flexi UI - A flexible and useful UI component library.
* Copyright (C) 2019-2024 HighCapable
* https://github.com/BetterAndroid/FlexiUI
*
* Apache License Version 2.0
*
* 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.
*
* This file is created by fankes on 2024/1/11.
*/
import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.Stable
import androidx.compose.runtime.mutableStateOf
import com.highcapable.flexiui.blueColors
import com.highcapable.flexiui.defaultColors
import com.highcapable.flexiui.greenColors
import com.highcapable.flexiui.isSystemColorAvailable
import com.highcapable.flexiui.orangeColors
import com.highcapable.flexiui.pinkColors
import com.highcapable.flexiui.purpleColors
import com.highcapable.flexiui.redColors
import com.highcapable.flexiui.systemColors
import com.highcapable.flexiui.yellowColors
@Stable
data class AppPreferences(
var colorScheme: MutableState<ColorScheme> = mutableStateOf(ColorScheme.Default),
var darkMode: MutableState<Boolean> = mutableStateOf(false),
var followSystemDarkMode: MutableState<Boolean> = mutableStateOf(false)
)
// TODO: Include ColorScheme to Flexi UI's Colors.kt
@Stable
val Preferences = AppPreferences()
@Stable
enum class ColorScheme {
Default,
DefaultBlack,
System,
SystemBlack,
Red,
RedBlack,
Pink,
PinkBlack,
Purple,
PurpleBlack,
Orange,
OrangeBlack,
Yellow,
YellowBlack,
Green,
GreenBlack,
Blue,
BlueBlack
}
@Composable
fun colorSchemes(): Array<ColorScheme> {
val defaultColors = arrayOf(
ColorScheme.Default,
ColorScheme.DefaultBlack
)
val systemColors = arrayOf(
ColorScheme.System,
ColorScheme.SystemBlack
)
val presetColors = arrayOf(
ColorScheme.Red,
ColorScheme.RedBlack,
ColorScheme.Pink,
ColorScheme.PinkBlack,
ColorScheme.Purple,
ColorScheme.PurpleBlack,
ColorScheme.Orange,
ColorScheme.OrangeBlack,
ColorScheme.Yellow,
ColorScheme.YellowBlack,
ColorScheme.Green,
ColorScheme.GreenBlack,
ColorScheme.Blue,
ColorScheme.BlueBlack
)
return if (isSystemColorAvailable())
defaultColors + systemColors + presetColors
else defaultColors + presetColors
}
@Composable
fun ColorScheme.toColors(darkMode: Boolean) = when (this) {
ColorScheme.Default -> defaultColors(darkMode)
ColorScheme.DefaultBlack -> defaultColors(darkMode, blackDarkMode = true)
ColorScheme.System -> systemColors(darkMode)
ColorScheme.SystemBlack -> systemColors(darkMode, blackDarkMode = true)
ColorScheme.Red -> redColors(darkMode)
ColorScheme.RedBlack -> redColors(darkMode, blackDarkMode = true)
ColorScheme.Pink -> pinkColors(darkMode)
ColorScheme.PinkBlack -> pinkColors(darkMode, blackDarkMode = true)
ColorScheme.Purple -> purpleColors(darkMode)
ColorScheme.PurpleBlack -> purpleColors(darkMode, blackDarkMode = true)
ColorScheme.Orange -> orangeColors(darkMode)
ColorScheme.OrangeBlack -> orangeColors(darkMode, blackDarkMode = true)
ColorScheme.Yellow -> yellowColors(darkMode)
ColorScheme.YellowBlack -> yellowColors(darkMode, blackDarkMode = true)
ColorScheme.Green -> greenColors(darkMode)
ColorScheme.GreenBlack -> greenColors(darkMode, blackDarkMode = true)
ColorScheme.Blue -> blueColors(darkMode)
ColorScheme.BlueBlack -> blueColors(darkMode, blackDarkMode = true)
}
@Stable
fun ColorScheme.toName() = when (this) {
ColorScheme.Default -> "Default"
ColorScheme.DefaultBlack -> "Default (Black)"
ColorScheme.System -> "System"
ColorScheme.SystemBlack -> "System (Black)"
ColorScheme.Red -> "Red"
ColorScheme.RedBlack -> "Red (Black)"
ColorScheme.Pink -> "Pink"
ColorScheme.PinkBlack -> "Pink (Black)"
ColorScheme.Purple -> "Purple"
ColorScheme.PurpleBlack -> "Purple (Black)"
ColorScheme.Orange -> "Orange"
ColorScheme.OrangeBlack -> "Orange (Black)"
ColorScheme.Yellow -> "Yellow"
ColorScheme.YellowBlack -> "Yellow (Black)"
ColorScheme.Green -> "Green"
ColorScheme.GreenBlack -> "Green (Black)"
ColorScheme.Blue -> "Blue"
ColorScheme.BlueBlack -> "Blue (Black)"
}