创建Screents和ViewModels
在前面的章节中,我们已经分析了OrderNow项目的理论概念和我们将赋予的组织。
在本章中,我们将开始实现初始结构和模板,这将联接每一个应用程序的部分。
首先将添加以下带有各自视图模型的主屏幕:
• 首页
• 产品列表
• 产品详情
• 购物车
添加元素的一个例子如下图所示:
Sreens 和 ViewModels
我们将在应用程序中使用依赖管理器将每个ViewModel绑定到各自的屏幕上。为此,我们必须首先在应用程序中依赖Hilt。
implementation 'com.google.dagger:hilt-android:2.38.1' // Use the latest version kapt 'com.google.dagger:hilt-android-compiler:2.38.1' // Use the latest version
在依赖Hilt的过程后,将要求定义应用类型类,例如在我们的示例项目中,将定义为OrderNowApplication,如下:
@HiltAndroidApp class OrderNowApplication:Application() { }
注意:在androidmanifest .xml中注册OrderNowApplication类
<application
android:name=".main.OrderNowApplication"
android:allowBackup="true"
...>
此外,我们将 Navigation Compose依赖到项目中,这将允许View(Composable)在导航期间获得其各自ViewModel的实例:
dependencies {
implementation 'androidx.hilt:hilt-navigation-compose:1.0.0'
}
一旦在项目中正确地执行了前面的配置,我们就可以像这样将ViewModel注入View:
Home ViewModel:
@HiltViewModel
class HomeViewModel @Inject constructor() : ViewModel() {
...
}
Home Screen:
@Composable
fun HomeScreen(viewModel: HomeViewModel = hiltViewModel()
) {
...
}
每个屏幕都将通过Hilt依赖管理器与其相应的ViewModel相关联。到目前为止,我们已经集成了以下架构组件:Compose、Navigation和ViewModel。
这是Jetpack工具的完美组合,在后面的章节中,我们将看到它在移动开发中的潜力。
UI模式:TopAppBar和BottomAppBar
通过Scaffold组件,我们可以在应用程序中实现两种在Material Design中最常见的UI模式:TopAppBar和BottomAppBar。
Scaffold是一个详细的视图(composable),它将允许我们以以下方式实现这些模式:
Scaffold:
Scaffold(
topBar = {
TopAppBar { /* Top app bar content */ }
},
bottomBar = {
BottomAppBar { /* Bottom app bar content */ }
}
) { contentPadding -> 9 // Screen content
}
在代码片段中,我们定义了topBar,bottomBar,和(还未添加的)屏幕内容。
在Scaffold中,topBar和bottomBar部分是可选的;也就是说,可以省略其中一部分的定义。此外,在Scaffold中,我们可以声明两个更多的组件:
• scaffoldState
• snackbarHost
在下一章,我们将看到每个的用法。现在我们只定义topBar和bottomBar。 现在我们知道如何在我们的应用程序中包含这些UI模式,下一步就是创建代表TopAppBar和BottomAppBar的视图(Composables)。
我们将其组织在一个叫做patterns的目录中,并在其中添加了两个Views,OrderNowTopBar和OrderNowBottomBar,如下所示:
TopAppBar and BottomAppBar Composables:
OrderNowTopBar
OrderNowTopBar的实现很简单。我们最初只需要以以下方式实现它:
@Composable
fun OrderNowTopBar() {
TopAppBar(
title = {
Text(
text = stringResource(id = AppString.app_name),
textAlign = TextAlign.Center,
modifier = Modifier.fillMaxWidth()
)
},
backgroundColor = MaterialTheme.colors.background,
contentColor = contentColorFor(MaterialTheme.colors.background)
)
}
之前的实现还不包含返回选项等元素;然而,在后面的章节中添加“Back”到TopAppBar中,它将包含这样一个使用状态策略的导航选项。
OrderNowBottomBar
OrderNowBottomBar的实现可以更精细一些,因为我们需要包括屏幕之间的导航。但是,我们将把实现细节留到下一章。
现在,我们将包含一个没有导航的静态定义。
@Composable
fun OrderNowBottomBar() {
val selectedIndex = remember { mutableStateOf(0) }
BottomNavigation(
backgroundColor = MaterialTheme.colors.background,
contentColor = contentColorFor(MaterialTheme.colors.background),
elevation = 10.dp
) {
BottomNavigationItem(icon = {
Icon(imageVector = Icons.Default.Home, "")
},
label = { Text(text = "Home") },
selected = (selectedIndex.value == 0),
unselectedContentColor = Color.Gray,
selectedContentColor = orange,
onClick = {
selectedIndex.value = 0
})
BottomNavigationItem(icon = {
Icon(imageVector = Icons.Default.ShoppingCart, "")
},
label = { Text(text = "Cart") },
selected = (selectedIndex.value == 1),
unselectedContentColor = Color.Gray,
selectedContentColor = orange,
onClick = {
selectedIndex.value = 1
})
}
}
在这个阶段,我们已经有了屏幕、视图模型和Scaffold的定义(其中包括OrderNowBottomBar和OrderNowTopBar)。
下一步是将所有的部分组合在一起,我们将在下一部分中做这个。
将所有元素整合在一起
第一项任务是创建一个名为main的目录。这个目录将是横向的,并将包含App的基类或结构。
在该目录中,我们放置Application类,移动MainActivity到那里,以及应用程序的主屏幕,我们将其命名为OrderNowScreen,如下图所示。
Main Components:
现在我们修改MainActivity.kt类,以便它将登录屏幕加载到OrderNowScreen应用程序,如下所示:
@AndroidEntryPoint
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
OrderNowScreen()
}
}
}
然后,在OrderNowScreen视图中,我们像这样定义应用程序的Scaffold:
@Composable
fun OrderNowScreen() {
InitialSkeletonTheme {
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colors.background
) {
Scaffold(
topBar = { OrderNowTopBar() },
bottomBar = { OrderNowBottomBar() }
) { contentPadding ->
println(contentPadding)
}
}
}
}
当您运行应用程序时,结果应该类似于以下图像:
总结
在本章中,我们已经构建了OrderNow项目的初始结构。
这里定义和实现的组件将是下一章继续讨论导航的基础。
随着我们阅读这些章节,我们将改进OrderNow的每个部分的实现,因此.我们的电子贸易将以最佳方式设计和实施。
源码:
class MainActivity4: ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent{
OrderNowScreen()
}
}
}
@Preview
@Composable
fun OrderNowScreen() {
MyTestTheme {
Surface(modifier = Modifier.fillMaxSize(),color=MaterialTheme.colors.background){
Scaffold(
topBar = {OrderNowTopBar()},
bottomBar={ OrderNowBottomBar()}
) {contentPadding ->
println(contentPadding)
}
}
}
}
@Preview
@Composable
fun OrderNowBottomBar(){
val selectedIndex =remember{ mutableStateOf(0)}
BottomNavigation(
backgroundColor = MaterialTheme.colors.background,
contentColor=contentColorFor(MaterialTheme.colors.background),
elevation = 10.dp){
BottomNavigationItem(
icon = { Icon(imageVector = Icons.Default.Home,"") },
label = { Text(text = "首页")},
selected =(selectedIndex.value == 0) ,
unselectedContentColor = Color.Gray,
selectedContentColor = Color.Red,
onClick = { selectedIndex.value = 0 })
BottomNavigationItem(icon={Icon(imageVector = Icons.Default.Favorite,"")},
label = {Text(text="热门")},
selected = (selectedIndex.value== 1),
unselectedContentColor =Color.Gray,
selectedContentColor = Color.Red,
onClick ={selectedIndex.value=1}
)
BottomNavigationItem(
icon = { Icon(imageVector = Icons.Default.ShoppingCart,"") },
label = { Text(text = "购物车")},
selected =(selectedIndex.value == 2) ,
unselectedContentColor = Color.Gray,
selectedContentColor = Color.Red,
onClick = { selectedIndex.value = 2 })
BottomNavigationItem(icon={Icon(imageVector = Icons.Default.Person,"")},
label = {Text(text="我的")},
selected = (selectedIndex.value== 3),
unselectedContentColor =Color.Gray,
selectedContentColor = Color.Red,
onClick ={selectedIndex.value=3}
)
}
}
@Composable
fun OrderNowTopBar() {
TopAppBar(
title = {
Text(
text = stringResource(id = R.string.app_name),
textAlign = TextAlign.Center,
modifier = Modifier.fillMaxWidth()
)
},
backgroundColor = MaterialTheme.colors.background,
contentColor = contentColorFor(MaterialTheme.colors.background)
)
}
@HiltAndroidApp
class OrderNowApplication : Application() {
}