Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Compose components: NavigationBar #239

Merged
merged 5 commits into from
Jul 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions modules/app_ui_kit/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ dependencies {
implementation(project(":ui_icons"))
implementation(project(":ui_kit_lists"))
implementation(project(":ui_kit_topappbar"))
implementation(project(":ui_kit_navigationbar"))
implementation(project(":lib_navigation_api"))
implementation(project(":lib_navigation_compose"))
implementation(project(":lib_elm"))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,21 @@ package kekmech.ru.mpeiapp.demo

import android.os.Bundle
import androidx.activity.compose.setContent
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.Surface
import androidx.compose.runtime.CompositionLocalProvider
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.core.view.WindowCompat
import com.bumble.appyx.core.integration.NodeHost
import com.bumble.appyx.core.integrationpoint.NodeComponentActivity
import kekmech.ru.mpeiapp.demo.di.AppModule
import kekmech.ru.mpeiapp.demo.ui.LocalUiKitThemeController
import kekmech.ru.mpeiapp.demo.ui.UiKitThemeController
import kekmech.ru.ui_theme.theme.MpeixTheme
import org.koin.core.context.startKoin

Expand All @@ -21,14 +29,33 @@ class MainActivity : NodeComponentActivity() {
}
WindowCompat.setDecorFitsSystemWindows(window, false)
setContent {
MpeixTheme {
// A surface container using the 'background' color from the theme
Surface(
modifier = Modifier.fillMaxSize(),
color = MpeixTheme.palette.background,
val isSystemInDarkTheme = isSystemInDarkTheme()
var darkThemeEnabled by remember { mutableStateOf(isSystemInDarkTheme) }
val themeController = remember {
object : UiKitThemeController {

override fun darkThemeEnabled(): Boolean =
darkThemeEnabled

override fun toggleDarkTheme() {
darkThemeEnabled = !darkThemeEnabled
}
}
}
CompositionLocalProvider(
LocalUiKitThemeController provides themeController,
) {
MpeixTheme(
darkTheme = darkThemeEnabled,
) {
NodeHost(integrationPoint = appyxIntegrationPoint) {
BackStackRootNode(buildContext = it)
// A surface container using the 'background' color from the theme
Surface(
modifier = Modifier.fillMaxSize(),
color = MpeixTheme.palette.background,
) {
NodeHost(integrationPoint = appyxIntegrationPoint) {
BackStackRootNode(buildContext = it)
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import com.bumble.appyx.core.node.node
import kekmech.ru.lib_navigation_api.NavTarget
import kekmech.ru.lib_navigation_compose.LocalBackStackNavigator
import kekmech.ru.mpeiapp.demo.screens.components.lists.ListItemScreenNavTarget
import kekmech.ru.mpeiapp.demo.screens.components.navigationbar.NavigationBarScreenNavTarget
import kekmech.ru.mpeiapp.demo.screens.components.topappbar.ComponentsTopAppBarNavTarget
import kekmech.ru.mpeiapp.demo.ui.SectionItem
import kekmech.ru.mpeiapp.demo.ui.UiKitScreen
Expand Down Expand Up @@ -42,6 +43,14 @@ private fun ComponentsScreen() {
name = "ListItem",
)
}
item("Navigation bar") {
SectionItem(
onClick = {
navigator.navigate(NavigationBarScreenNavTarget())
},
name = "Navigation bar",
)
}
item("Top app bar") {
SectionItem(
onClick = {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
package kekmech.ru.mpeiapp.demo.screens.components.navigationbar

import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.WindowInsetsSides
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.only
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.ScaffoldDefaults
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.Alignment
import androidx.compose.ui.Modifier
import com.bumble.appyx.core.modality.BuildContext
import com.bumble.appyx.core.node.Node
import com.bumble.appyx.core.node.node
import kekmech.ru.lib_navigation_api.NavTarget
import kekmech.ru.mpeiapp.demo.ui.UiKitScreen
import kekmech.ru.ui_icons.MpeixIcons
import kekmech.ru.ui_kit_navigationbar.NavigationBar
import kekmech.ru.ui_kit_navigationbar.NavigationBarItem
import kotlinx.parcelize.Parcelize

@Parcelize
internal class NavigationBarScreenNavTarget : NavTarget {

override fun resolve(buildContext: BuildContext): Node =
node(buildContext) { NavigationBarScreen() }
}

@Suppress("LongMethod", "MagicNumber")
@Composable
private fun NavigationBarScreen() {
UiKitScreen(
title = "Navigation bar",
contentWindowInsets = ScaffoldDefaults.contentWindowInsets.only(WindowInsetsSides.Top),
) { innerPadding ->
Box(
modifier = Modifier
.padding(innerPadding)
.fillMaxSize(),
contentAlignment = Alignment.BottomCenter,
) {
var selectedItemIdx by remember { mutableStateOf(0) }
NavigationBar(
modifier = Modifier.fillMaxWidth(),
) {
NavigationBarItem(
selected = selectedItemIdx == 0,
onClick = { selectedItemIdx = 0 },
icon = {
Icon(
painterSelected = MpeixIcons.WhatshotBlack24,
painterUnselected = MpeixIcons.WhatshotOutline24,
)
},
label = "Главная",
)
NavigationBarItem(
selected = selectedItemIdx == 1,
onClick = { selectedItemIdx = 1 },
icon = {
Icon(
painterSelected = MpeixIcons.EventBlack24,
painterUnselected = MpeixIcons.EventOutline24,
)
},
label = "Расписание",
)
NavigationBarItem(
selected = selectedItemIdx == 2,
onClick = { selectedItemIdx = 2 },
icon = {
Icon(
painterSelected = MpeixIcons.ExploreBlack24,
painterUnselected = MpeixIcons.ExploreOutline24,
)
},
label = "Карта",
)
NavigationBarItem(
selected = selectedItemIdx == 3,
onClick = { selectedItemIdx = 3 },
icon = {
Icon(
painterSelected = MpeixIcons.AccountBlack24,
painterUnselected = MpeixIcons.AccountOutline24,
)
},
label = "Профиль",
)
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import kekmech.ru.mpeiapp.demo.screens.components.ComponentsScreenNavTarget
import kekmech.ru.mpeiapp.demo.screens.elmslie.ElmDemoScreenNavTarget
import kekmech.ru.mpeiapp.demo.screens.typography.TypographyScreenNavTarget
import kekmech.ru.mpeiapp.demo.ui.SectionItem
import kekmech.ru.mpeiapp.demo.ui.ToggleThemeActionButton
import kekmech.ru.ui_kit_topappbar.TopAppBar
import kotlinx.parcelize.Parcelize
import kotlin.random.Random
Expand All @@ -32,6 +33,7 @@ internal class MainScreenNavTarget(private val greetings: String = "MpeiX UI-Kit
node(buildContext) { MainScreen(greetings) }
}

@Suppress("LongMethod")
@Composable
private fun MainScreen(greetings: String) {
val navigator = LocalBackStackNavigator.current
Expand All @@ -44,6 +46,9 @@ private fun MainScreen(greetings: String) {
TopAppBar(
title = greetings,
scrollBehavior = scrollBehavior,
actions = {
ToggleThemeActionButton()
}
)
},
) { innerPadding ->
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package kekmech.ru.mpeiapp.demo.ui

import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.runtime.Composable
import androidx.compose.ui.res.painterResource
import kekmech.ru.mpeiapp.demo.R


@Composable
fun ToggleThemeActionButton() {
val themeController = LocalUiKitThemeController.current
IconButton(
onClick = { themeController.toggleDarkTheme() },
) {
Icon(
painter = if (themeController.darkThemeEnabled()) {
painterResource(R.drawable.ic_light_mode_24)
} else {
painterResource(R.drawable.ic_dark_mode_24)
},
contentDescription = null,
)
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package kekmech.ru.mpeiapp.demo.ui

import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.material3.Scaffold
import androidx.compose.material3.ScaffoldDefaults
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
Expand All @@ -12,6 +14,7 @@ import kekmech.ru.ui_kit_topappbar.TopAppBar
@Composable
fun UiKitScreen(
title: String,
contentWindowInsets: WindowInsets = ScaffoldDefaults.contentWindowInsets,
content: @Composable (PaddingValues) -> Unit,
) {
val navigator = LocalBackStackNavigator.current
Expand All @@ -27,9 +30,13 @@ fun UiKitScreen(
BackIconButton {
navigator.back()
}
},
actions = {
ToggleThemeActionButton()
}
)
},
contentWindowInsets = contentWindowInsets,
content = content,
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package kekmech.ru.mpeiapp.demo.ui

import androidx.compose.runtime.Stable
import androidx.compose.runtime.compositionLocalOf

@Stable
interface UiKitThemeController {

fun darkThemeEnabled(): Boolean

fun toggleDarkTheme()
}

val LocalUiKitThemeController = compositionLocalOf<UiKitThemeController> {
error("LocalUiKitThemeController not provided")
}
9 changes: 9 additions & 0 deletions modules/app_ui_kit/src/main/res/drawable/ic_dark_mode_24.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<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,3c-4.97,0 -9,4.03 -9,9s4.03,9 9,9s9,-4.03 9,-9c0,-0.46 -0.04,-0.92 -0.1,-1.36c-0.98,1.37 -2.58,2.26 -4.4,2.26c-2.98,0 -5.4,-2.42 -5.4,-5.4c0,-1.81 0.89,-3.42 2.26,-4.4C12.92,3.04 12.46,3 12,3L12,3z"
android:fillColor="#000000"/>
</vector>
9 changes: 9 additions & 0 deletions modules/app_ui_kit/src/main/res/drawable/ic_light_mode_24.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<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,7c-2.76,0 -5,2.24 -5,5s2.24,5 5,5s5,-2.24 5,-5S14.76,7 12,7L12,7zM2,13l2,0c0.55,0 1,-0.45 1,-1s-0.45,-1 -1,-1l-2,0c-0.55,0 -1,0.45 -1,1S1.45,13 2,13zM20,13l2,0c0.55,0 1,-0.45 1,-1s-0.45,-1 -1,-1l-2,0c-0.55,0 -1,0.45 -1,1S19.45,13 20,13zM11,2v2c0,0.55 0.45,1 1,1s1,-0.45 1,-1V2c0,-0.55 -0.45,-1 -1,-1S11,1.45 11,2zM11,20v2c0,0.55 0.45,1 1,1s1,-0.45 1,-1v-2c0,-0.55 -0.45,-1 -1,-1C11.45,19 11,19.45 11,20zM5.99,4.58c-0.39,-0.39 -1.03,-0.39 -1.41,0c-0.39,0.39 -0.39,1.03 0,1.41l1.06,1.06c0.39,0.39 1.03,0.39 1.41,0s0.39,-1.03 0,-1.41L5.99,4.58zM18.36,16.95c-0.39,-0.39 -1.03,-0.39 -1.41,0c-0.39,0.39 -0.39,1.03 0,1.41l1.06,1.06c0.39,0.39 1.03,0.39 1.41,0c0.39,-0.39 0.39,-1.03 0,-1.41L18.36,16.95zM19.42,5.99c0.39,-0.39 0.39,-1.03 0,-1.41c-0.39,-0.39 -1.03,-0.39 -1.41,0l-1.06,1.06c-0.39,0.39 -0.39,1.03 0,1.41s1.03,0.39 1.41,0L19.42,5.99zM7.05,18.36c0.39,-0.39 0.39,-1.03 0,-1.41c-0.39,-0.39 -1.03,-0.39 -1.41,0l-1.06,1.06c-0.39,0.39 -0.39,1.03 0,1.41s1.03,0.39 1.41,0L7.05,18.36z"
android:fillColor="#000000"/>
</vector>
7 changes: 7 additions & 0 deletions modules/ui/kit/navigationbar/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
plugins {
id("mpeix.android.ui")
}

dependencies {
implementation(project(":ui_theme"))
}
Loading