mirror of
https://github.com/Joker-x-dev/AndroidProject-Compose.git
synced 2025-12-27 15:47:11 +00:00
初步实现首页 demo 示例布局
This commit is contained in:
@@ -0,0 +1,53 @@
|
|||||||
|
package com.joker.kit.feature.main.component
|
||||||
|
|
||||||
|
import androidx.compose.material3.ListItem
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.draw.clip
|
||||||
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
|
import com.joker.kit.core.designsystem.theme.AppTheme
|
||||||
|
import com.joker.kit.core.designsystem.theme.ShapeMedium
|
||||||
|
import com.joker.kit.core.ui.component.text.AppText
|
||||||
|
import com.joker.kit.core.ui.component.text.TextSize
|
||||||
|
import com.joker.kit.feature.main.model.DemoCardInfo
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Demo 卡片组件,统一 ListItem 样式
|
||||||
|
*
|
||||||
|
* @param info 卡片数据
|
||||||
|
* @param modifier 修饰符
|
||||||
|
*/
|
||||||
|
@Composable
|
||||||
|
fun DemoCard(
|
||||||
|
info: DemoCardInfo,
|
||||||
|
modifier: Modifier = Modifier
|
||||||
|
) {
|
||||||
|
ListItem(
|
||||||
|
modifier = modifier.clip(ShapeMedium),
|
||||||
|
headlineContent = {
|
||||||
|
AppText(
|
||||||
|
text = info.title,
|
||||||
|
size = TextSize.TITLE_MEDIUM
|
||||||
|
)
|
||||||
|
},
|
||||||
|
supportingContent = {
|
||||||
|
AppText(
|
||||||
|
text = info.description,
|
||||||
|
size = TextSize.BODY_MEDIUM
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Preview(showBackground = true)
|
||||||
|
@Composable
|
||||||
|
private fun DemoCardPreview() {
|
||||||
|
AppTheme {
|
||||||
|
DemoCard(
|
||||||
|
info = DemoCardInfo(
|
||||||
|
title = "示例组件",
|
||||||
|
description = "预览展示 Demo 卡片默认样式。"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
package com.joker.kit.feature.main.data
|
||||||
|
|
||||||
|
import com.joker.kit.feature.main.model.DemoCardInfo
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Demo 卡片静态数据源
|
||||||
|
*/
|
||||||
|
object DemoCardData {
|
||||||
|
|
||||||
|
val coreCards: List<DemoCardInfo> = listOf(
|
||||||
|
DemoCardInfo(
|
||||||
|
title = "Base Network",
|
||||||
|
description = "网络状态切换,包含加载、错误、重试等流程。"
|
||||||
|
),
|
||||||
|
DemoCardInfo(
|
||||||
|
title = "Base Network List",
|
||||||
|
description = "下拉刷新与分页加载的统一列表模板,内置空状态与重试。"
|
||||||
|
),
|
||||||
|
DemoCardInfo(
|
||||||
|
title = "数据库",
|
||||||
|
description = "Room 的增删改查示例,含简单的列表展示与数据观察。"
|
||||||
|
),
|
||||||
|
DemoCardInfo(
|
||||||
|
title = "本地存储",
|
||||||
|
description = "DataStore / MMKV 的写入与清除示例,演示单值增删改查。"
|
||||||
|
),
|
||||||
|
DemoCardInfo(
|
||||||
|
title = "状态管理",
|
||||||
|
description = "全局 UserState 登陆态同步、跨页面数据推送与状态流更新。"
|
||||||
|
),
|
||||||
|
DemoCardInfo(
|
||||||
|
title = "网络请求",
|
||||||
|
description = "结合 ResultHandler 的通用接口请求、加载状态与错误提示。"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
val navigationCards: List<DemoCardInfo> = listOf(
|
||||||
|
DemoCardInfo(
|
||||||
|
title = "带参跳转",
|
||||||
|
description = "类型安全路由参数,包含必填/可选参数与目标页接收方式。"
|
||||||
|
),
|
||||||
|
DemoCardInfo(
|
||||||
|
title = "结果回传",
|
||||||
|
description = "NavigationResultKey 返回数据,包含刷新信号与数据实体回传。"
|
||||||
|
),
|
||||||
|
DemoCardInfo(
|
||||||
|
title = "导航拦截",
|
||||||
|
description = "登录拦截流程:未登录跳登录页,登录成功后才能进入用户详情。"
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package com.joker.kit.feature.main.model
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Demo 卡片信息
|
||||||
|
*
|
||||||
|
* @param title 标题
|
||||||
|
* @param description 描述内容
|
||||||
|
*/
|
||||||
|
data class DemoCardInfo(
|
||||||
|
val title: String,
|
||||||
|
val description: String
|
||||||
|
)
|
||||||
@@ -0,0 +1,81 @@
|
|||||||
|
package com.joker.kit.feature.main.view
|
||||||
|
|
||||||
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
|
import androidx.compose.foundation.layout.PaddingValues
|
||||||
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
|
import androidx.compose.foundation.lazy.items
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.material3.Surface
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.collectAsState
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
|
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
|
||||||
|
import com.joker.kit.core.designsystem.theme.AppTheme
|
||||||
|
import com.joker.kit.core.designsystem.theme.SpacePaddingLarge
|
||||||
|
import com.joker.kit.core.designsystem.theme.SpaceVerticalMedium
|
||||||
|
import com.joker.kit.feature.main.component.DemoCard
|
||||||
|
import com.joker.kit.feature.main.data.DemoCardData
|
||||||
|
import com.joker.kit.feature.main.model.DemoCardInfo
|
||||||
|
import com.joker.kit.feature.main.viewmodel.CoreDemoViewModel
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Core Demo 路由
|
||||||
|
*
|
||||||
|
* @param viewModel Core Demo ViewModel
|
||||||
|
*/
|
||||||
|
@Composable
|
||||||
|
internal fun CoreDemoRoute(
|
||||||
|
viewModel: CoreDemoViewModel = hiltViewModel()
|
||||||
|
) {
|
||||||
|
val cards by viewModel.cards.collectAsState()
|
||||||
|
CoreDemoScreen(cards = cards)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Core Demo 界面
|
||||||
|
*
|
||||||
|
* @param cards Demo 卡片列表
|
||||||
|
*/
|
||||||
|
@Composable
|
||||||
|
internal fun CoreDemoScreen(
|
||||||
|
cards: List<DemoCardInfo> = emptyList()
|
||||||
|
) {
|
||||||
|
LazyColumn(
|
||||||
|
modifier = Modifier.fillMaxSize(),
|
||||||
|
contentPadding = PaddingValues(SpacePaddingLarge),
|
||||||
|
verticalArrangement = Arrangement.spacedBy(SpaceVerticalMedium)
|
||||||
|
) {
|
||||||
|
items(cards) { info ->
|
||||||
|
DemoCard(info = info)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Core Demo 浅色预览
|
||||||
|
*/
|
||||||
|
@Preview(showBackground = true)
|
||||||
|
@Composable
|
||||||
|
private fun CoreDemoPreview() {
|
||||||
|
AppTheme {
|
||||||
|
Surface(color = MaterialTheme.colorScheme.background) {
|
||||||
|
CoreDemoScreen(cards = DemoCardData.coreCards)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Core Demo 深色预览
|
||||||
|
*/
|
||||||
|
@Preview(showBackground = true)
|
||||||
|
@Composable
|
||||||
|
private fun CoreDemoPreviewDark() {
|
||||||
|
AppTheme(darkTheme = true) {
|
||||||
|
Surface(color = MaterialTheme.colorScheme.background) {
|
||||||
|
CoreDemoScreen(cards = DemoCardData.coreCards)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,15 +1,33 @@
|
|||||||
package com.joker.kit.feature.main.view
|
package com.joker.kit.feature.main.view
|
||||||
|
|
||||||
|
import androidx.compose.foundation.ExperimentalFoundationApi
|
||||||
|
import androidx.compose.foundation.background
|
||||||
|
import androidx.compose.foundation.clickable
|
||||||
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
|
import androidx.compose.foundation.layout.Row
|
||||||
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.navigationBarsPadding
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.pager.HorizontalPager
|
||||||
|
import androidx.compose.foundation.pager.rememberPagerState
|
||||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Scaffold
|
import androidx.compose.material3.Scaffold
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
|
import androidx.compose.runtime.collectAsState
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
|
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
|
||||||
import com.joker.kit.core.designsystem.theme.AppTheme
|
import com.joker.kit.core.designsystem.theme.AppTheme
|
||||||
import com.joker.kit.core.ui.component.text.AppText
|
import com.joker.kit.core.ui.component.text.AppText
|
||||||
import com.joker.kit.core.ui.component.text.TextSize
|
import com.joker.kit.core.ui.component.text.TextSize
|
||||||
|
import com.joker.kit.feature.main.viewmodel.MainTab
|
||||||
|
import com.joker.kit.feature.main.viewmodel.MainUiState
|
||||||
import com.joker.kit.feature.main.viewmodel.MainViewModel
|
import com.joker.kit.feature.main.viewmodel.MainViewModel
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -22,40 +40,113 @@ import com.joker.kit.feature.main.viewmodel.MainViewModel
|
|||||||
internal fun MainRoute(
|
internal fun MainRoute(
|
||||||
viewModel: MainViewModel = hiltViewModel()
|
viewModel: MainViewModel = hiltViewModel()
|
||||||
) {
|
) {
|
||||||
MainScreen()
|
val uiState by viewModel.uiState.collectAsState()
|
||||||
|
MainScreen(
|
||||||
|
uiState = uiState,
|
||||||
|
onTabSelected = viewModel::selectTab
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 主页面
|
* 主页面
|
||||||
*
|
*
|
||||||
* @param onBackClick 返回按钮回调
|
* @param uiState UI 状态
|
||||||
|
* @param onTabSelected Tab 切换回调
|
||||||
* @author Joker.X
|
* @author Joker.X
|
||||||
*/
|
*/
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
internal fun MainScreen(
|
internal fun MainScreen(
|
||||||
onBackClick: () -> Unit = {},
|
uiState: MainUiState,
|
||||||
|
onTabSelected: (MainTab) -> Unit,
|
||||||
) {
|
) {
|
||||||
Scaffold { innerPadding ->
|
MainScreenContent(
|
||||||
MainContentView(
|
uiState = uiState,
|
||||||
modifier = Modifier.padding(innerPadding)
|
onTabSelected = onTabSelected
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 主页面内容视图,包含底部导航和横向 Pager
|
||||||
|
*/
|
||||||
|
@OptIn(ExperimentalMaterial3Api::class, ExperimentalFoundationApi::class)
|
||||||
|
@Composable
|
||||||
|
private fun MainScreenContent(
|
||||||
|
uiState: MainUiState,
|
||||||
|
onTabSelected: (MainTab) -> Unit
|
||||||
|
) {
|
||||||
|
val pagerState = rememberPagerState(pageCount = { MainTab.allTabs.size })
|
||||||
|
val currentPage = pagerState.currentPage
|
||||||
|
|
||||||
|
LaunchedEffect(uiState.currentTab) {
|
||||||
|
val targetPage = uiState.currentTab.index
|
||||||
|
if (pagerState.currentPage != targetPage) {
|
||||||
|
pagerState.animateScrollToPage(targetPage)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LaunchedEffect(currentPage) {
|
||||||
|
val tab = MainTab.fromIndex(currentPage)
|
||||||
|
if (tab != uiState.currentTab) {
|
||||||
|
onTabSelected(tab)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Scaffold(
|
||||||
|
bottomBar = {
|
||||||
|
MainBottomBar(
|
||||||
|
tabs = MainTab.allTabs,
|
||||||
|
currentTab = uiState.currentTab,
|
||||||
|
onTabSelected = onTabSelected
|
||||||
|
)
|
||||||
|
}
|
||||||
|
) { innerPadding ->
|
||||||
|
HorizontalPager(
|
||||||
|
state = pagerState,
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
.padding(innerPadding)
|
||||||
|
) { page ->
|
||||||
|
when (MainTab.fromIndex(page)) {
|
||||||
|
MainTab.Core -> CoreDemoRoute()
|
||||||
|
MainTab.Navigation -> NavigationDemoRoute()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 主页面内容视图
|
* 自定义纯文字底部导航栏
|
||||||
*
|
|
||||||
* @param modifier 修饰符
|
|
||||||
* @author Joker.X
|
|
||||||
*/
|
*/
|
||||||
@Composable
|
@Composable
|
||||||
private fun MainContentView(modifier: Modifier = Modifier) {
|
private fun MainBottomBar(
|
||||||
AppText(
|
tabs: List<MainTab>,
|
||||||
text = "主页面",
|
currentTab: MainTab,
|
||||||
size = TextSize.TITLE_MEDIUM,
|
onTabSelected: (MainTab) -> Unit
|
||||||
modifier = modifier
|
) {
|
||||||
)
|
Row(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.background(MaterialTheme.colorScheme.surface)
|
||||||
|
.navigationBarsPadding()
|
||||||
|
.padding(horizontal = 16.dp),
|
||||||
|
horizontalArrangement = Arrangement.spacedBy(12.dp)
|
||||||
|
) {
|
||||||
|
tabs.forEach { tab ->
|
||||||
|
val selected = tab == currentTab
|
||||||
|
AppText(
|
||||||
|
text = tab.title,
|
||||||
|
size = TextSize.BODY_MEDIUM,
|
||||||
|
color = if (selected) MaterialTheme.colorScheme.primary
|
||||||
|
else MaterialTheme.colorScheme.onSurfaceVariant,
|
||||||
|
textAlign = TextAlign.Center,
|
||||||
|
modifier = Modifier
|
||||||
|
.weight(1f)
|
||||||
|
.clickable { onTabSelected(tab) }
|
||||||
|
.padding(vertical = 10.dp)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -67,7 +158,10 @@ private fun MainContentView(modifier: Modifier = Modifier) {
|
|||||||
@Composable
|
@Composable
|
||||||
internal fun MainScreenPreview() {
|
internal fun MainScreenPreview() {
|
||||||
AppTheme {
|
AppTheme {
|
||||||
MainScreen()
|
MainScreen(
|
||||||
|
uiState = MainUiState(),
|
||||||
|
onTabSelected = {}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -80,6 +174,9 @@ internal fun MainScreenPreview() {
|
|||||||
@Composable
|
@Composable
|
||||||
internal fun MainScreenPreviewDark() {
|
internal fun MainScreenPreviewDark() {
|
||||||
AppTheme(darkTheme = true) {
|
AppTheme(darkTheme = true) {
|
||||||
MainScreen()
|
MainScreen(
|
||||||
|
uiState = MainUiState(),
|
||||||
|
onTabSelected = {}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,81 @@
|
|||||||
|
package com.joker.kit.feature.main.view
|
||||||
|
|
||||||
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
|
import androidx.compose.foundation.layout.PaddingValues
|
||||||
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
|
import androidx.compose.foundation.lazy.items
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.material3.Surface
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.collectAsState
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
|
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
|
||||||
|
import com.joker.kit.core.designsystem.theme.AppTheme
|
||||||
|
import com.joker.kit.core.designsystem.theme.SpacePaddingLarge
|
||||||
|
import com.joker.kit.core.designsystem.theme.SpaceVerticalMedium
|
||||||
|
import com.joker.kit.feature.main.component.DemoCard
|
||||||
|
import com.joker.kit.feature.main.data.DemoCardData
|
||||||
|
import com.joker.kit.feature.main.model.DemoCardInfo
|
||||||
|
import com.joker.kit.feature.main.viewmodel.NavigationDemoViewModel
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Navigation Demo 路由
|
||||||
|
*
|
||||||
|
* @param viewModel Navigation Demo ViewModel
|
||||||
|
*/
|
||||||
|
@Composable
|
||||||
|
internal fun NavigationDemoRoute(
|
||||||
|
viewModel: NavigationDemoViewModel = hiltViewModel()
|
||||||
|
) {
|
||||||
|
val cards by viewModel.cards.collectAsState()
|
||||||
|
NavigationDemoScreen(cards = cards)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Navigation Demo 界面
|
||||||
|
*
|
||||||
|
* @param cards Demo 卡片列表
|
||||||
|
*/
|
||||||
|
@Composable
|
||||||
|
internal fun NavigationDemoScreen(
|
||||||
|
cards: List<DemoCardInfo> = emptyList()
|
||||||
|
) {
|
||||||
|
LazyColumn(
|
||||||
|
modifier = Modifier.fillMaxSize(),
|
||||||
|
contentPadding = PaddingValues(SpacePaddingLarge),
|
||||||
|
verticalArrangement = Arrangement.spacedBy(SpaceVerticalMedium)
|
||||||
|
) {
|
||||||
|
items(cards) { info ->
|
||||||
|
DemoCard(info = info)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Navigation Demo 浅色预览
|
||||||
|
*/
|
||||||
|
@Preview(showBackground = true)
|
||||||
|
@Composable
|
||||||
|
private fun NavigationDemoPreview() {
|
||||||
|
AppTheme {
|
||||||
|
Surface(color = MaterialTheme.colorScheme.background) {
|
||||||
|
NavigationDemoScreen(cards = DemoCardData.navigationCards)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Navigation Demo 深色预览
|
||||||
|
*/
|
||||||
|
@Preview(showBackground = true)
|
||||||
|
@Composable
|
||||||
|
private fun NavigationDemoPreviewDark() {
|
||||||
|
AppTheme(darkTheme = true) {
|
||||||
|
Surface(color = MaterialTheme.colorScheme.background) {
|
||||||
|
NavigationDemoScreen(cards = DemoCardData.navigationCards)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
package com.joker.kit.feature.main.viewmodel
|
||||||
|
|
||||||
|
import com.joker.kit.core.base.viewmodel.BaseViewModel
|
||||||
|
import com.joker.kit.core.state.UserState
|
||||||
|
import com.joker.kit.feature.main.data.DemoCardData
|
||||||
|
import com.joker.kit.feature.main.model.DemoCardInfo
|
||||||
|
import com.joker.kit.navigation.AppNavigator
|
||||||
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
|
import kotlinx.coroutines.flow.asStateFlow
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Core Demo ViewModel
|
||||||
|
*/
|
||||||
|
@HiltViewModel
|
||||||
|
class CoreDemoViewModel @Inject constructor(
|
||||||
|
navigator: AppNavigator,
|
||||||
|
userState: UserState,
|
||||||
|
) : BaseViewModel(
|
||||||
|
navigator = navigator,
|
||||||
|
userState = userState
|
||||||
|
) {
|
||||||
|
|
||||||
|
private val _cards = MutableStateFlow(DemoCardData.coreCards)
|
||||||
|
val cards: StateFlow<List<DemoCardInfo>> = _cards.asStateFlow()
|
||||||
|
}
|
||||||
@@ -4,6 +4,9 @@ import com.joker.kit.core.base.viewmodel.BaseViewModel
|
|||||||
import com.joker.kit.core.state.UserState
|
import com.joker.kit.core.state.UserState
|
||||||
import com.joker.kit.navigation.AppNavigator
|
import com.joker.kit.navigation.AppNavigator
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
|
import kotlinx.coroutines.flow.asStateFlow
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -20,4 +23,43 @@ class MainViewModel @Inject constructor(
|
|||||||
) : BaseViewModel(
|
) : BaseViewModel(
|
||||||
navigator = navigator,
|
navigator = navigator,
|
||||||
userState = userState
|
userState = userState
|
||||||
) {}
|
) {
|
||||||
|
|
||||||
|
private val _uiState = MutableStateFlow(MainUiState())
|
||||||
|
val uiState: StateFlow<MainUiState> = _uiState.asStateFlow()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 切换底部导航 tab
|
||||||
|
*/
|
||||||
|
fun selectTab(tab: MainTab) {
|
||||||
|
if (tab == _uiState.value.currentTab) return
|
||||||
|
_uiState.value = _uiState.value.copy(currentTab = tab)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Main 页面 UI 状态
|
||||||
|
*
|
||||||
|
* @param currentTab 当前底部栏 tab
|
||||||
|
*/
|
||||||
|
data class MainUiState(
|
||||||
|
val currentTab: MainTab = MainTab.Core
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Main 页面底部栏 Tab
|
||||||
|
*/
|
||||||
|
enum class MainTab(val title: String) {
|
||||||
|
Core("Core"),
|
||||||
|
Navigation("Navigation");
|
||||||
|
|
||||||
|
val index: Int get() = ordinal
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
val allTabs: List<MainTab> = values().toList()
|
||||||
|
|
||||||
|
fun fromIndex(index: Int): MainTab {
|
||||||
|
return allTabs.getOrElse(index) { Core }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
package com.joker.kit.feature.main.viewmodel
|
||||||
|
|
||||||
|
import com.joker.kit.core.base.viewmodel.BaseViewModel
|
||||||
|
import com.joker.kit.core.state.UserState
|
||||||
|
import com.joker.kit.feature.main.data.DemoCardData
|
||||||
|
import com.joker.kit.feature.main.model.DemoCardInfo
|
||||||
|
import com.joker.kit.navigation.AppNavigator
|
||||||
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
|
import kotlinx.coroutines.flow.asStateFlow
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Navigation Demo ViewModel
|
||||||
|
*/
|
||||||
|
@HiltViewModel
|
||||||
|
class NavigationDemoViewModel @Inject constructor(
|
||||||
|
navigator: AppNavigator,
|
||||||
|
userState: UserState,
|
||||||
|
) : BaseViewModel(
|
||||||
|
navigator = navigator,
|
||||||
|
userState = userState
|
||||||
|
) {
|
||||||
|
|
||||||
|
private val _cards = MutableStateFlow(DemoCardData.navigationCards)
|
||||||
|
val cards: StateFlow<List<DemoCardInfo>> = _cards.asStateFlow()
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user