Binary file not shown.
@ -0,0 +1,62 @@
|
||||
package com.example.fruitandvegetableguide
|
||||
|
||||
|
||||
// 每个界面路由接口
|
||||
interface Destinations {
|
||||
val route: String
|
||||
}
|
||||
|
||||
//接口实现
|
||||
object Login : Destinations {
|
||||
override val route: String = "login"
|
||||
}
|
||||
|
||||
object Register : Destinations {
|
||||
override val route: String = "register"
|
||||
}
|
||||
|
||||
object Main : Destinations {
|
||||
override val route: String = "main"
|
||||
}
|
||||
|
||||
object Search : Destinations {
|
||||
override val route: String = "search"
|
||||
}
|
||||
|
||||
object PostDetail : Destinations {
|
||||
override val route: String = "postDetail"
|
||||
}
|
||||
|
||||
object GuideDetail : Destinations {
|
||||
override val route: String = "guideDetail"
|
||||
}
|
||||
|
||||
object User : Destinations {
|
||||
override val route: String = "user"
|
||||
}
|
||||
|
||||
object MyPost : Destinations {
|
||||
override val route: String = "myPost"
|
||||
}
|
||||
|
||||
object Photograph : Destinations {
|
||||
override val route: String = "photograph"
|
||||
}
|
||||
|
||||
object RecognizeResult : Destinations {
|
||||
override val route: String = "recognizeResult"
|
||||
}
|
||||
|
||||
object Guide : Destinations {
|
||||
override val route: String = "guide"
|
||||
}
|
||||
|
||||
object Community : Destinations {
|
||||
override val route: String = "community"
|
||||
}
|
||||
|
||||
object PostEdit : Destinations {
|
||||
override val route: String = "postEdit"
|
||||
}
|
||||
|
||||
//val Screens = listOf(Login, Register, Main)
|
||||
@ -0,0 +1,137 @@
|
||||
package com.example.fruitandvegetableguide
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.navigation.NavHostController
|
||||
import androidx.navigation.NavType
|
||||
import androidx.navigation.compose.NavHost
|
||||
import androidx.navigation.compose.composable
|
||||
import androidx.navigation.navArgument
|
||||
import com.example.fruitandvegetableguide.ui.community.CommunityScreen
|
||||
import com.example.fruitandvegetableguide.ui.community.PostDetailScreen
|
||||
import com.example.fruitandvegetableguide.ui.community.PostEditScreen
|
||||
import com.example.fruitandvegetableguide.ui.guide.GuideDetailScreen
|
||||
import com.example.fruitandvegetableguide.ui.guide.GuideScreen
|
||||
import com.example.fruitandvegetableguide.ui.imgrecognition.PhotographScreen
|
||||
import com.example.fruitandvegetableguide.ui.imgrecognition.RecognizeResultScreen
|
||||
import com.example.fruitandvegetableguide.ui.login.LoginScreen
|
||||
import com.example.fruitandvegetableguide.ui.main.MainScreen
|
||||
import com.example.fruitandvegetableguide.ui.register.RegisterScreen
|
||||
import com.example.fruitandvegetableguide.ui.search.SearchScreen
|
||||
import com.example.fruitandvegetableguide.ui.user.MyPostScreen
|
||||
import com.example.fruitandvegetableguide.ui.user.UserScreen
|
||||
|
||||
@Composable
|
||||
fun NavHost(
|
||||
navController: NavHostController,
|
||||
modifier: Modifier = Modifier
|
||||
) {
|
||||
NavHost(
|
||||
navController = navController,
|
||||
startDestination = Login.route,
|
||||
modifier = modifier
|
||||
) {
|
||||
//登录页路由
|
||||
composable(route = Login.route) {
|
||||
LoginScreen(
|
||||
onClickToRegister = { navController.navigateSingleTopTo(Register.route) },
|
||||
onClickToMain = { userid -> navController.navigateSingleTopTo("${Main.route}/${userid}") }//传出userid
|
||||
)
|
||||
}
|
||||
//注册页路由
|
||||
composable(route = Register.route) {
|
||||
RegisterScreen(
|
||||
onClickBack = { navController.popBackStack() }
|
||||
)
|
||||
}
|
||||
//首页路由
|
||||
composable(
|
||||
route = "${Main.route}/{userid}",
|
||||
arguments = listOf(
|
||||
navArgument("userid") {
|
||||
type = NavType.IntType
|
||||
nullable = false
|
||||
}
|
||||
)
|
||||
) {
|
||||
val userid = it.arguments?.getInt("userid")//接收userid
|
||||
MainScreen(
|
||||
userid = userid,
|
||||
onClickToSearch = { navController.navigateSingleTopTo(Search.route) },
|
||||
onClickToUser = { navController.navigateSingleTopTo(User.route) },
|
||||
onClickToPhotograph = { navController.navigateSingleTopTo(Photograph.route) },
|
||||
onClickToGuide = { navController.navigateSingleTopTo(Guide.route) },
|
||||
onClickToCommunity = { navController.navigateSingleTopTo(Community.route) },
|
||||
onClickToGuideDetail = { navController.navigateSingleTopTo(GuideDetail.route) },
|
||||
onClickToPostDetail = { navController.navigateSingleTopTo(PostDetail.route) }
|
||||
)
|
||||
}
|
||||
//搜索页路由
|
||||
composable(route = Search.route) {
|
||||
SearchScreen(
|
||||
onClickBack = { navController.popBackStack() },
|
||||
onClickToGuideDetail = { navController.navigateSingleTopTo(GuideDetail.route) },
|
||||
onClickToPostDetail = { navController.navigateSingleTopTo(PostDetail.route) },
|
||||
)
|
||||
}
|
||||
//指南详情页路由
|
||||
composable(route = GuideDetail.route) {
|
||||
GuideDetailScreen(onClickBack = { navController.popBackStack() })
|
||||
}
|
||||
//帖子详情页路由
|
||||
composable(route = PostDetail.route) {
|
||||
PostDetailScreen(onClickBack = { navController.popBackStack() })
|
||||
}
|
||||
//用户页路由
|
||||
composable(route = User.route) {
|
||||
UserScreen(
|
||||
onClickToMain = { navController.popBackStack() },
|
||||
onClickToMyPost = { navController.navigateSingleTopTo(MyPost.route) },
|
||||
onClickToPhotograph = { navController.navigateSingleTopTo(Photograph.route) }
|
||||
)
|
||||
}
|
||||
//我的帖子页面路由
|
||||
composable(route = MyPost.route) {
|
||||
MyPostScreen(onClickBack = { navController.popBackStack() })
|
||||
}
|
||||
//拍照页路由
|
||||
composable(route = Photograph.route) {
|
||||
PhotographScreen(onClickToRecognizeResult = {
|
||||
navController.navigateSingleTopTo(
|
||||
RecognizeResult.route
|
||||
)
|
||||
})
|
||||
}
|
||||
//识别结果页路由
|
||||
composable(route = RecognizeResult.route) {
|
||||
RecognizeResultScreen(onClickBack = { navController.popBackStack() })
|
||||
}
|
||||
//指南页路由
|
||||
composable(route = Guide.route) {
|
||||
GuideScreen(
|
||||
onClickToSearch = { navController.navigateSingleTopTo(Search.route) },
|
||||
onClickToGuideDetail = { navController.navigateSingleTopTo(GuideDetail.route) },
|
||||
onClickBack = { navController.popBackStack() }
|
||||
)
|
||||
}
|
||||
//社区页路由
|
||||
composable(route = Community.route) {
|
||||
CommunityScreen(
|
||||
onClickToSearch = { navController.navigateSingleTopTo(Search.route) },
|
||||
onClickToPostDetail = { navController.navigateSingleTopTo(PostDetail.route) },
|
||||
onClickToPostEdit = { navController.navigateSingleTopTo(PostEdit.route) },
|
||||
onClickBack = { navController.popBackStack() }
|
||||
)
|
||||
}
|
||||
//帖子编辑页路由
|
||||
composable(route = PostEdit.route) {
|
||||
PostEditScreen(
|
||||
onClickBack = { navController.popBackStack() }
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//如果栈中已经包含了指定要跳转的界面,那么只会保留一个
|
||||
fun NavHostController.navigateSingleTopTo(route: String) =
|
||||
this.navigate(route) { launchSingleTop = true }
|
||||
@ -1,7 +1,8 @@
|
||||
package com.example.fruitandvegetableguide.data
|
||||
|
||||
//用户数据类
|
||||
data class Account(
|
||||
val username: String,
|
||||
val id:Long,
|
||||
val username: String,
|
||||
val password:String
|
||||
)
|
||||
|
||||
@ -0,0 +1,3 @@
|
||||
package com.example.fruitandvegetableguide.data.dbutils
|
||||
|
||||
// TODO 这里放数据库工具方法
|
||||
@ -1,2 +0,0 @@
|
||||
package com.example.fruitandvegetableguide.ui
|
||||
|
||||
@ -1,397 +0,0 @@
|
||||
@file:OptIn(ExperimentalMaterial3Api::class)
|
||||
|
||||
package com.example.fruitandvegetableguide.ui
|
||||
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.widget.Toast
|
||||
import androidx.activity.compose.setContent
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.AccountBox
|
||||
import androidx.compose.material.icons.filled.Lock
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.ButtonDefaults
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TextField
|
||||
import androidx.compose.material3.TextFieldDefaults
|
||||
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 androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.input.PasswordVisualTransformation
|
||||
import androidx.compose.ui.text.input.VisualTransformation
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import com.example.fruitandvegetableguide.R
|
||||
import com.example.fruitandvegetableguide.data.local.LocalAccountsDataProvider
|
||||
import com.example.fruitandvegetableguide.ui.theme.FruitandVegetableGuideTheme
|
||||
|
||||
class LoginActivity : AppCompatActivity() {
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContent {
|
||||
FruitandVegetableGuideTheme() {
|
||||
Surface(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
color = MaterialTheme.colorScheme.background
|
||||
) {
|
||||
var username by remember { mutableStateOf("") }
|
||||
var password by remember { mutableStateOf("") }
|
||||
val pwdVisualTransformation = PasswordVisualTransformation()
|
||||
var showPwd by remember { mutableStateOf(true) }
|
||||
|
||||
val transformation =
|
||||
if (showPwd) pwdVisualTransformation else VisualTransformation.None
|
||||
Box(modifier = Modifier.fillMaxSize()) {
|
||||
Text(
|
||||
text = "注册",
|
||||
fontSize = 20.sp,
|
||||
textAlign = TextAlign.End,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(20.dp)
|
||||
)
|
||||
Column() {
|
||||
Spacer(modifier = Modifier.weight(1f))
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.weight(3f)
|
||||
.background(Color.White)
|
||||
.padding(40.dp)
|
||||
.fillMaxWidth(),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
verticalArrangement = Arrangement.Center
|
||||
) {
|
||||
Column {
|
||||
TextField(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
value = username,
|
||||
onValueChange = { str -> username = str },
|
||||
placeholder = {
|
||||
Text("账号")
|
||||
},
|
||||
colors = TextFieldDefaults.colors(focusedTextColor = Color.Black),
|
||||
leadingIcon = {
|
||||
Icon(
|
||||
imageVector = Icons.Default.AccountBox,
|
||||
contentDescription = null
|
||||
)
|
||||
}
|
||||
)
|
||||
TextField(
|
||||
value = password,
|
||||
onValueChange = { str -> password = str },
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
placeholder = {
|
||||
Text("密码")
|
||||
},
|
||||
visualTransformation = transformation,
|
||||
colors = TextFieldDefaults.colors(focusedTextColor = Color.Black),
|
||||
leadingIcon = {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Lock,
|
||||
contentDescription = null
|
||||
)
|
||||
},
|
||||
trailingIcon = {
|
||||
if (showPwd) {
|
||||
IconButton(onClick = { showPwd = !showPwd }) {
|
||||
Icon(
|
||||
painter = painterResource(id = R.drawable.sleep),
|
||||
contentDescription = null,
|
||||
Modifier.size(30.dp)
|
||||
)
|
||||
}
|
||||
} else {
|
||||
IconButton(onClick = { showPwd = !showPwd }) {
|
||||
Icon(
|
||||
painter = painterResource(id = R.drawable.eye),
|
||||
contentDescription = null,
|
||||
Modifier.size(30.dp)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
Spacer(modifier = Modifier.height(20.dp))
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.SpaceBetween,
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
) {
|
||||
Text(text = "快捷登录", fontSize = 16.sp, color = Color.Gray)
|
||||
Text(text = "忘记密码", fontSize = 16.sp, color = Color.Gray)
|
||||
}
|
||||
Spacer(modifier = Modifier.height(20.dp))
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.Center,
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
Button(
|
||||
onClick = {
|
||||
// TODO 2.此处由验证结果实现页面跳转
|
||||
if (loginVerification(username, password)) {
|
||||
Toast.makeText(
|
||||
this@LoginActivity,
|
||||
"登陆成功",
|
||||
Toast.LENGTH_SHORT
|
||||
).show()
|
||||
val intent = Intent(
|
||||
this@LoginActivity,
|
||||
MainActivity::class.java
|
||||
)
|
||||
startActivity(intent)
|
||||
}
|
||||
else{
|
||||
Toast.makeText(
|
||||
this@LoginActivity,
|
||||
"登陆失败",
|
||||
Toast.LENGTH_SHORT
|
||||
).show()
|
||||
}
|
||||
},
|
||||
colors = ButtonDefaults.buttonColors(
|
||||
containerColor = Color(
|
||||
0xff5c59fe
|
||||
)
|
||||
),
|
||||
contentPadding = PaddingValues(12.dp, 16.dp)
|
||||
) {
|
||||
Text("登录", color = Color.White, fontSize = 18.sp)
|
||||
}
|
||||
}
|
||||
Spacer(modifier = Modifier.height(100.dp))
|
||||
Column(
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
verticalArrangement = Arrangement.Center
|
||||
) {
|
||||
Row(
|
||||
Modifier
|
||||
.background(Color(0xFFCFC5C5))
|
||||
.padding(end = 10.dp)
|
||||
) {}
|
||||
Spacer(modifier = Modifier.height(20.dp))
|
||||
Text(text = "第三方登录", fontSize = 16.sp, color = Color.Gray)
|
||||
Row(
|
||||
Modifier
|
||||
.fillMaxWidth()
|
||||
.weight(1f),
|
||||
horizontalArrangement = Arrangement.Center,
|
||||
verticalAlignment = Alignment.Top
|
||||
) {
|
||||
repeat(3) {
|
||||
Column(
|
||||
Modifier.weight(1f),
|
||||
verticalArrangement = Arrangement.Center,
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
Image(
|
||||
modifier = Modifier.size(50.dp),
|
||||
painter = painterResource(id = R.drawable.qq),
|
||||
contentDescription = null
|
||||
)
|
||||
Text(
|
||||
"QQ",
|
||||
color = Color(0xffcdcdcd),
|
||||
fontSize = 16.sp,
|
||||
fontWeight = FontWeight.Bold
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun loginVerification(username: String, password: String): Boolean {
|
||||
// TODO 1.此处需要完成登录验证的相关代码
|
||||
return username == LocalAccountsDataProvider.allUserAccounts[0].username && password == LocalAccountsDataProvider.allUserAccounts[0].password
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun LoginForm() {
|
||||
var username by remember { mutableStateOf("") }
|
||||
var password by remember { mutableStateOf("") }
|
||||
val pwdVisualTransformation = PasswordVisualTransformation()
|
||||
var showPwd by remember { mutableStateOf(true) }
|
||||
|
||||
val transformation = if (showPwd) pwdVisualTransformation else VisualTransformation.None
|
||||
|
||||
Box(modifier = Modifier.fillMaxSize()) {
|
||||
Text(
|
||||
text = "注册",
|
||||
fontSize = 20.sp,
|
||||
textAlign = TextAlign.End,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(20.dp)
|
||||
)
|
||||
Column() {
|
||||
Spacer(modifier = Modifier.weight(1f))
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.weight(3f)
|
||||
.background(Color.White)
|
||||
.padding(40.dp)
|
||||
.fillMaxWidth(),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
verticalArrangement = Arrangement.Center
|
||||
) {
|
||||
Column {
|
||||
TextField(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
value = username,
|
||||
onValueChange = { str -> username = str },
|
||||
placeholder = {
|
||||
Text("账号")
|
||||
},
|
||||
colors = TextFieldDefaults.colors(focusedTextColor = Color.Transparent),
|
||||
leadingIcon = {
|
||||
Icon(
|
||||
imageVector = Icons.Default.AccountBox,
|
||||
contentDescription = null
|
||||
)
|
||||
}
|
||||
)
|
||||
TextField(
|
||||
value = password,
|
||||
onValueChange = { str -> password = str },
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
placeholder = {
|
||||
Text("密码")
|
||||
},
|
||||
visualTransformation = transformation,
|
||||
colors = TextFieldDefaults.colors(focusedTextColor = Color.Transparent),
|
||||
leadingIcon = {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Lock,
|
||||
contentDescription = null
|
||||
)
|
||||
},
|
||||
trailingIcon = {
|
||||
if (showPwd) {
|
||||
IconButton(onClick = { showPwd = !showPwd }) {
|
||||
Icon(
|
||||
painter = painterResource(id = R.drawable.sleep),
|
||||
contentDescription = null,
|
||||
Modifier.size(30.dp)
|
||||
)
|
||||
}
|
||||
} else {
|
||||
IconButton(onClick = { showPwd = !showPwd }) {
|
||||
Icon(
|
||||
painter = painterResource(id = R.drawable.eye),
|
||||
contentDescription = null,
|
||||
Modifier.size(30.dp)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
Spacer(modifier = Modifier.height(20.dp))
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.SpaceBetween,
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
) {
|
||||
Text(text = "快捷登录", fontSize = 16.sp, color = Color.Gray)
|
||||
Text(text = "忘记密码", fontSize = 16.sp, color = Color.Gray)
|
||||
}
|
||||
Spacer(modifier = Modifier.height(20.dp))
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.Center,
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
Button(
|
||||
onClick = {
|
||||
// TODO 2.此处由验证结果实现页面跳转
|
||||
},
|
||||
colors = ButtonDefaults.buttonColors(containerColor = Color(0xff5c59fe)),
|
||||
contentPadding = PaddingValues(12.dp, 16.dp)
|
||||
) {
|
||||
Text("登录", color = Color.White, fontSize = 18.sp)
|
||||
}
|
||||
}
|
||||
Spacer(modifier = Modifier.height(100.dp))
|
||||
Column(
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
verticalArrangement = Arrangement.Center
|
||||
) {
|
||||
Row(
|
||||
Modifier
|
||||
.background(Color(0xFFCFC5C5))
|
||||
.padding(end = 10.dp)
|
||||
) {}
|
||||
Spacer(modifier = Modifier.height(20.dp))
|
||||
Text(text = "第三方登录", fontSize = 16.sp, color = Color.Gray)
|
||||
Row(
|
||||
Modifier
|
||||
.fillMaxWidth()
|
||||
.weight(1f),
|
||||
horizontalArrangement = Arrangement.Center,
|
||||
verticalAlignment = Alignment.Top
|
||||
) {
|
||||
repeat(3) {
|
||||
Column(
|
||||
Modifier.weight(1f),
|
||||
verticalArrangement = Arrangement.Center,
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
Image(
|
||||
modifier = Modifier.size(50.dp),
|
||||
painter = painterResource(id = R.drawable.qq),
|
||||
contentDescription = null
|
||||
)
|
||||
Text(
|
||||
"QQ",
|
||||
color = Color(0xffcdcdcd),
|
||||
fontSize = 16.sp,
|
||||
fontWeight = FontWeight.Bold
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun Login() {
|
||||
LoginForm()
|
||||
}
|
||||
@ -1,250 +0,0 @@
|
||||
package com.example.fruitandvegetableguide.ui
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.activity.compose.setContent
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.heightIn
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.paddingFromBaseline
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.lazy.grid.GridCells
|
||||
import androidx.compose.foundation.lazy.grid.LazyHorizontalGrid
|
||||
import androidx.compose.foundation.lazy.grid.items
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.AccountCircle
|
||||
import androidx.compose.material.icons.filled.Camera
|
||||
import androidx.compose.material.icons.filled.Search
|
||||
import androidx.compose.material.icons.filled.Spa
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.NavigationBar
|
||||
import androidx.compose.material3.NavigationBarItem
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TextField
|
||||
import androidx.compose.material3.TextFieldDefaults
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.layout.ContentScale
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.example.fruitandvegetableguide.data.local.LocalGuidesDataProvider.allGuides
|
||||
import com.example.fruitandvegetableguide.data.local.LocalPostsDataProvider.allPosts
|
||||
import com.example.fruitandvegetableguide.ui.theme.FruitandVegetableGuideTheme
|
||||
|
||||
class MainActivity : AppCompatActivity() {
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContent {
|
||||
FruitandVegetableGuideTheme() {
|
||||
Surface(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
color = MaterialTheme.colorScheme.background
|
||||
) {
|
||||
MainPage()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//主页
|
||||
@Composable
|
||||
fun MainPage() {
|
||||
FruitandVegetableGuideTheme() {
|
||||
Scaffold(bottomBar = { MyBottomNavigation() }) { padding ->
|
||||
HomeScreen(modifier = Modifier.padding(padding))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//主屏幕
|
||||
@Composable
|
||||
fun HomeScreen(modifier: Modifier = Modifier) {
|
||||
Column(modifier.verticalScroll(rememberScrollState())) {
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
SearchBar(Modifier.padding(horizontal = 16.dp))
|
||||
HomeSection(title = "指南") {
|
||||
GuideRow()
|
||||
}
|
||||
HomeSection(title = "社区") {
|
||||
PostGrid()
|
||||
}
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
}
|
||||
}
|
||||
|
||||
//搜索框
|
||||
@Composable
|
||||
fun SearchBar(modifier: Modifier = Modifier) {
|
||||
TextField(
|
||||
value = "", onValueChange = {},
|
||||
leadingIcon = { Icon(imageVector = Icons.Default.Search, contentDescription = null) },
|
||||
colors = TextFieldDefaults.colors(
|
||||
unfocusedContainerColor = MaterialTheme.colorScheme.surface,
|
||||
focusedContainerColor = MaterialTheme.colorScheme.surface
|
||||
),
|
||||
placeholder = { Text(text = "搜索") },
|
||||
modifier = modifier
|
||||
.fillMaxWidth()
|
||||
.heightIn(56.dp)
|
||||
)
|
||||
}
|
||||
|
||||
//指南元素
|
||||
@Composable
|
||||
fun GuideElement(
|
||||
modifier: Modifier = Modifier,
|
||||
@DrawableRes drawable: Int,
|
||||
kind: String
|
||||
) {
|
||||
Column(
|
||||
modifier = modifier,
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
) {
|
||||
Image(
|
||||
painter = painterResource(id = drawable),
|
||||
contentDescription = null,
|
||||
contentScale = ContentScale.Crop,
|
||||
modifier = Modifier
|
||||
.size(88.dp)
|
||||
.clip(CircleShape)
|
||||
)
|
||||
Text(
|
||||
text = kind,
|
||||
modifier = Modifier.paddingFromBaseline(top = 24.dp, bottom = 8.dp),
|
||||
style = MaterialTheme.typography.bodyMedium
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
//帖子元素
|
||||
@Composable
|
||||
fun PostCard(
|
||||
modifier: Modifier = Modifier,
|
||||
@DrawableRes drawable: Int,
|
||||
title: String
|
||||
) {
|
||||
Surface(
|
||||
shape = MaterialTheme.shapes.medium,
|
||||
modifier = modifier,
|
||||
color = MaterialTheme.colorScheme.surfaceVariant,
|
||||
) {
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
modifier = Modifier.width(255.dp)
|
||||
) {
|
||||
Image(
|
||||
painter = painterResource(id = drawable), contentDescription = null,
|
||||
contentScale = ContentScale.Crop,
|
||||
modifier = Modifier.size(80.dp)
|
||||
)
|
||||
Text(
|
||||
text = title,
|
||||
style = MaterialTheme.typography.titleMedium,
|
||||
modifier = Modifier.padding(horizontal = 16.dp)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//指南的网格显示
|
||||
@Composable
|
||||
fun GuideRow(modifier: Modifier = Modifier) {
|
||||
LazyHorizontalGrid(
|
||||
rows = GridCells.Fixed(2),
|
||||
contentPadding = PaddingValues(horizontal = 16.dp),
|
||||
horizontalArrangement = Arrangement.spacedBy(8.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(16.dp),
|
||||
modifier = modifier.height(240.dp)
|
||||
) {
|
||||
items(allGuides) { item -> GuideElement(drawable = item.imgId, kind = item.kind) }
|
||||
}
|
||||
}
|
||||
|
||||
//帖子的网格显示
|
||||
@Composable
|
||||
fun PostGrid(modifier: Modifier = Modifier) {
|
||||
LazyHorizontalGrid(
|
||||
rows = GridCells.Fixed(4),
|
||||
contentPadding = PaddingValues(horizontal = 16.dp),
|
||||
horizontalArrangement = Arrangement.spacedBy(16.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(16.dp),
|
||||
modifier = modifier.height(288.dp)
|
||||
) {
|
||||
items(allPosts) { item -> PostCard(drawable = item.imgId, title = item.title) }
|
||||
}
|
||||
}
|
||||
|
||||
//小组件加上标题
|
||||
@Composable
|
||||
fun HomeSection(title: String, modifier: Modifier = Modifier, content: @Composable () -> Unit) {
|
||||
Column(modifier) {
|
||||
Text(
|
||||
text = title,
|
||||
style = MaterialTheme.typography.titleMedium,
|
||||
modifier = Modifier
|
||||
.paddingFromBaseline(top = 40.dp, bottom = 16.dp)
|
||||
.padding(horizontal = 16.dp)
|
||||
)
|
||||
content()
|
||||
}
|
||||
}
|
||||
|
||||
//底部导航栏
|
||||
@Composable
|
||||
fun MyBottomNavigation(modifier: Modifier = Modifier) {
|
||||
NavigationBar(containerColor = MaterialTheme.colorScheme.surfaceVariant, modifier = modifier) {
|
||||
NavigationBarItem(icon = {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Spa,
|
||||
contentDescription = null
|
||||
)
|
||||
},
|
||||
label = { Text(text = "首页") },
|
||||
selected = true,
|
||||
onClick = { /*TODO*/ })
|
||||
NavigationBarItem(icon = {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Camera,
|
||||
contentDescription = null
|
||||
)
|
||||
},
|
||||
label = { Text(text = "识别")},
|
||||
selected = false,
|
||||
onClick = { /*TODO*/ })
|
||||
NavigationBarItem(icon = {
|
||||
Icon(
|
||||
imageVector = Icons.Default.AccountCircle,
|
||||
contentDescription = null
|
||||
)
|
||||
}, label = { Text(text = "用户") },
|
||||
selected = false,
|
||||
onClick = { /*TODO*/ })
|
||||
}
|
||||
}
|
||||
|
||||
//预览
|
||||
@Preview(showBackground = true, backgroundColor = 0xFFF5F0EE)
|
||||
@Composable
|
||||
fun PostPrev() {
|
||||
MainPage()
|
||||
}
|
||||
@ -0,0 +1,76 @@
|
||||
@file:OptIn(ExperimentalMaterial3Api::class)
|
||||
|
||||
package com.example.fruitandvegetableguide.ui.community
|
||||
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.requiredHeight
|
||||
import androidx.compose.foundation.layout.wrapContentSize
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.ArrowBack
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TopAppBar
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
|
||||
@Composable
|
||||
fun CommunityScreen(
|
||||
onClickToSearch: () -> Unit = {},
|
||||
onClickToPostDetail: () -> Unit = {},
|
||||
onClickToPostEdit: () -> Unit = {},
|
||||
onClickBack: () -> Unit = {},
|
||||
) {
|
||||
Column(modifier = Modifier.fillMaxSize()) {
|
||||
TopAppBar(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
title = {
|
||||
Text(
|
||||
text = "社区",
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.wrapContentSize(Alignment.Center)
|
||||
)
|
||||
},
|
||||
navigationIcon = {
|
||||
IconButton(onClick = onClickBack) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.ArrowBack,
|
||||
contentDescription = null
|
||||
)
|
||||
}
|
||||
})
|
||||
Spacer(modifier = Modifier.requiredHeight(10.dp))
|
||||
Text(text = "社区页", modifier = Modifier.align(alignment = Alignment.CenterHorizontally))
|
||||
Spacer(modifier = Modifier.requiredHeight(10.dp))
|
||||
Button(
|
||||
onClick = onClickToSearch,
|
||||
modifier = Modifier.align(alignment = Alignment.CenterHorizontally)
|
||||
) {
|
||||
Text(text = "搜索页")
|
||||
}
|
||||
Spacer(modifier = Modifier.requiredHeight(10.dp))
|
||||
Button(
|
||||
onClick = onClickToPostDetail,
|
||||
modifier = Modifier.align(alignment = Alignment.CenterHorizontally)
|
||||
) {
|
||||
Text(text = "帖子详情页")
|
||||
}
|
||||
Spacer(modifier = Modifier.requiredHeight(10.dp))
|
||||
Button(
|
||||
onClick = onClickToPostEdit,
|
||||
modifier = Modifier.align(alignment = Alignment.CenterHorizontally)
|
||||
) {
|
||||
Text(text = "帖子编辑页")
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,48 @@
|
||||
@file:OptIn(ExperimentalMaterial3Api::class)
|
||||
|
||||
package com.example.fruitandvegetableguide.ui.community
|
||||
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.requiredHeight
|
||||
import androidx.compose.foundation.layout.wrapContentSize
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.ArrowBack
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TopAppBar
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
|
||||
@Composable
|
||||
fun PostDetailScreen(onClickBack: () -> Unit) {
|
||||
Column(modifier = Modifier.fillMaxSize()) {
|
||||
TopAppBar(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
title = {
|
||||
Text(
|
||||
text = "PostTitle",
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.wrapContentSize(Alignment.Center)
|
||||
)
|
||||
},
|
||||
navigationIcon = {
|
||||
IconButton(onClick = onClickBack) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.ArrowBack,
|
||||
contentDescription = null
|
||||
)
|
||||
}
|
||||
})
|
||||
Spacer(modifier = Modifier.requiredHeight(10.dp))
|
||||
Text(text = "帖子详情页", modifier = Modifier.align(alignment = Alignment.CenterHorizontally))
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,51 @@
|
||||
@file:OptIn(ExperimentalMaterial3Api::class)
|
||||
|
||||
package com.example.fruitandvegetableguide.ui.community
|
||||
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.requiredHeight
|
||||
import androidx.compose.foundation.layout.wrapContentSize
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.ArrowBack
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TopAppBar
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
|
||||
@Preview(showBackground = true, backgroundColor = 0xFFF5F0EE)
|
||||
@Composable
|
||||
fun PostEditScreen(
|
||||
onClickBack: () -> Unit = {},
|
||||
) {
|
||||
Column(modifier = Modifier.fillMaxSize()) {
|
||||
TopAppBar(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
title = {
|
||||
Text(
|
||||
text = "编辑",
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.wrapContentSize(Alignment.Center)
|
||||
)
|
||||
},
|
||||
navigationIcon = {
|
||||
IconButton(onClick = onClickBack) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.ArrowBack,
|
||||
contentDescription = null
|
||||
)
|
||||
}
|
||||
})
|
||||
Spacer(modifier = Modifier.requiredHeight(10.dp))
|
||||
Text(text = "帖子编辑页", modifier = Modifier.align(alignment = Alignment.CenterHorizontally))
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,48 @@
|
||||
@file:OptIn(ExperimentalMaterial3Api::class)
|
||||
|
||||
package com.example.fruitandvegetableguide.ui.guide
|
||||
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.requiredHeight
|
||||
import androidx.compose.foundation.layout.wrapContentSize
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.ArrowBack
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TopAppBar
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
|
||||
@Composable
|
||||
fun GuideDetailScreen(onClickBack: () -> Unit) {
|
||||
Column(modifier = Modifier.fillMaxSize()) {
|
||||
TopAppBar(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
title = {
|
||||
Text(
|
||||
text = "GuideTitle",
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.wrapContentSize(Alignment.Center)
|
||||
)
|
||||
},
|
||||
navigationIcon = {
|
||||
IconButton(onClick = onClickBack) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.ArrowBack,
|
||||
contentDescription = null
|
||||
)
|
||||
}
|
||||
})
|
||||
Spacer(modifier = Modifier.requiredHeight(10.dp))
|
||||
Text(text = "指南详情页", modifier = Modifier.align(alignment = Alignment.CenterHorizontally))
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,68 @@
|
||||
@file:OptIn(ExperimentalMaterial3Api::class)
|
||||
|
||||
package com.example.fruitandvegetableguide.ui.guide
|
||||
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.requiredHeight
|
||||
import androidx.compose.foundation.layout.wrapContentSize
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.ArrowBack
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TopAppBar
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
|
||||
@Preview(showBackground = true, backgroundColor = 0xFFF5F0EE)
|
||||
@Composable
|
||||
fun GuideScreen(
|
||||
onClickToSearch: () -> Unit = {},
|
||||
onClickToGuideDetail: () -> Unit = {},
|
||||
onClickBack: () -> Unit = {},
|
||||
) {
|
||||
Column(modifier = Modifier.fillMaxSize()) {
|
||||
TopAppBar(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
title = {
|
||||
Text(
|
||||
text = "指南",
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.wrapContentSize(Alignment.Center)
|
||||
)
|
||||
},
|
||||
navigationIcon = {
|
||||
IconButton(onClick = onClickBack) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.ArrowBack,
|
||||
contentDescription = null
|
||||
)
|
||||
}
|
||||
})
|
||||
Spacer(modifier = Modifier.requiredHeight(10.dp))
|
||||
Text(text = "指南页", modifier = Modifier.align(alignment = Alignment.CenterHorizontally))
|
||||
Spacer(modifier = Modifier.requiredHeight(10.dp))
|
||||
Button(
|
||||
onClick = onClickToSearch,
|
||||
modifier = Modifier.align(alignment = Alignment.CenterHorizontally)
|
||||
) {
|
||||
Text(text = "搜索页")
|
||||
}
|
||||
Spacer(modifier = Modifier.requiredHeight(10.dp))
|
||||
Button(
|
||||
onClick = onClickToGuideDetail,
|
||||
modifier = Modifier.align(alignment = Alignment.CenterHorizontally)
|
||||
) {
|
||||
Text(text = "指南详情页")
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,46 @@
|
||||
@file:OptIn(ExperimentalMaterial3Api::class)
|
||||
|
||||
package com.example.fruitandvegetableguide.ui.imgrecognition
|
||||
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.requiredHeight
|
||||
import androidx.compose.foundation.layout.wrapContentSize
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.ArrowBack
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TopAppBar
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
|
||||
@Preview(showBackground = true, backgroundColor = 0xFFF5F0EE)
|
||||
@Composable
|
||||
fun PhotographScreen(onClickToRecognizeResult: () -> Unit = {}) {
|
||||
Column(modifier = Modifier.fillMaxSize()) {
|
||||
TopAppBar(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
title = {
|
||||
Text(
|
||||
text = "拍照",
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.wrapContentSize(Alignment.Center)
|
||||
)
|
||||
})
|
||||
Spacer(modifier = Modifier.requiredHeight(10.dp))
|
||||
Text(text = "拍照页", modifier = Modifier.align(alignment = Alignment.CenterHorizontally))
|
||||
Spacer(modifier = Modifier.requiredHeight(10.dp))
|
||||
Button(onClick = onClickToRecognizeResult,modifier = Modifier.align(alignment = Alignment.CenterHorizontally)) {
|
||||
Text(text = "识别")
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,48 @@
|
||||
@file:OptIn(ExperimentalMaterial3Api::class)
|
||||
|
||||
package com.example.fruitandvegetableguide.ui.imgrecognition
|
||||
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.requiredHeight
|
||||
import androidx.compose.foundation.layout.wrapContentSize
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.ArrowBack
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TopAppBar
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
|
||||
@Composable
|
||||
fun RecognizeResultScreen(onClickBack: () -> Unit = {}) {
|
||||
Column(modifier = Modifier.fillMaxSize()) {
|
||||
TopAppBar(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
title = {
|
||||
Text(
|
||||
text = "结果",
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.wrapContentSize(Alignment.Center)
|
||||
)
|
||||
},
|
||||
navigationIcon = {
|
||||
IconButton(onClick = onClickBack) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.ArrowBack,
|
||||
contentDescription = null
|
||||
)
|
||||
}
|
||||
})
|
||||
Spacer(modifier = Modifier.requiredHeight(10.dp))
|
||||
Text(text = "识别结果页", modifier = Modifier.align(alignment = Alignment.CenterHorizontally))
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,218 @@
|
||||
package com.example.fruitandvegetableguide.ui.login
|
||||
|
||||
import android.widget.Toast
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.AccountBox
|
||||
import androidx.compose.material.icons.filled.Lock
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.ButtonDefaults
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TextButton
|
||||
import androidx.compose.material3.TextField
|
||||
import androidx.compose.material3.TextFieldDefaults
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableIntStateOf
|
||||
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.graphics.Color
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.input.PasswordVisualTransformation
|
||||
import androidx.compose.ui.text.input.VisualTransformation
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import com.example.fruitandvegetableguide.R
|
||||
import com.example.fruitandvegetableguide.utils.loginVerification
|
||||
|
||||
@Composable
|
||||
fun LoginScreen(
|
||||
onClickToRegister: () -> Unit = {},
|
||||
onClickToMain: (Int) -> Unit = {}
|
||||
) {
|
||||
var userid by remember { mutableIntStateOf(-1) }
|
||||
var username by remember { mutableStateOf("") }
|
||||
var password by remember { mutableStateOf("") }
|
||||
val pwdVisualTransformation = PasswordVisualTransformation()
|
||||
var showPwd by remember { mutableStateOf(true) }
|
||||
val transformation = if (showPwd) pwdVisualTransformation else VisualTransformation.None
|
||||
val context = LocalContext.current
|
||||
|
||||
Box(modifier = Modifier.fillMaxSize()) {
|
||||
TextButton(onClick = onClickToRegister) {
|
||||
Text(
|
||||
text = "注册",
|
||||
fontSize = 20.sp,
|
||||
textAlign = TextAlign.End,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(20.dp)
|
||||
)
|
||||
}
|
||||
Column {
|
||||
Spacer(modifier = Modifier.weight(1f))
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.weight(3f)
|
||||
.background(Color.White)
|
||||
.padding(40.dp)
|
||||
.fillMaxWidth(),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
verticalArrangement = Arrangement.Center
|
||||
) {
|
||||
Column {
|
||||
TextField(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
value = username,
|
||||
onValueChange = { str -> username = str },
|
||||
placeholder = {
|
||||
Text("账号")
|
||||
},
|
||||
colors = TextFieldDefaults.colors(focusedTextColor = Color.Black),
|
||||
leadingIcon = {
|
||||
Icon(
|
||||
imageVector = Icons.Default.AccountBox,
|
||||
contentDescription = null
|
||||
)
|
||||
}
|
||||
)
|
||||
TextField(
|
||||
value = password,
|
||||
onValueChange = { str -> password = str },
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
placeholder = {
|
||||
Text("密码")
|
||||
},
|
||||
visualTransformation = transformation,
|
||||
colors = TextFieldDefaults.colors(focusedTextColor = Color.Black),
|
||||
leadingIcon = {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Lock,
|
||||
contentDescription = null
|
||||
)
|
||||
},
|
||||
trailingIcon = {
|
||||
if (showPwd) {
|
||||
IconButton(onClick = { showPwd = !showPwd }) {
|
||||
Icon(
|
||||
painter = painterResource(id = R.drawable.sleep),
|
||||
contentDescription = null,
|
||||
Modifier.size(30.dp)
|
||||
)
|
||||
}
|
||||
} else {
|
||||
IconButton(onClick = { showPwd = !showPwd }) {
|
||||
Icon(
|
||||
painter = painterResource(id = R.drawable.eye),
|
||||
contentDescription = null,
|
||||
Modifier.size(30.dp)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
Spacer(modifier = Modifier.height(20.dp))
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.SpaceBetween,
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
) {
|
||||
Text(text = "快捷登录", fontSize = 16.sp, color = Color.Gray)
|
||||
Text(text = "忘记密码", fontSize = 16.sp, color = Color.Gray)
|
||||
}
|
||||
Spacer(modifier = Modifier.height(20.dp))
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.Center,
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
Button(
|
||||
onClick = {
|
||||
userid = loginVerification(username, password)
|
||||
if (username != "" && password != "" && userid != -1) {
|
||||
Toast.makeText(context, "登陆成功", Toast.LENGTH_SHORT).show()
|
||||
onClickToMain(userid)
|
||||
} else {
|
||||
Toast.makeText(context, "登陆失败", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
},
|
||||
colors = ButtonDefaults.buttonColors(
|
||||
containerColor = Color(
|
||||
0xff5c59fe
|
||||
)
|
||||
),
|
||||
contentPadding = PaddingValues(12.dp, 16.dp)
|
||||
) {
|
||||
Text("登录", color = Color.White, fontSize = 18.sp)
|
||||
}
|
||||
}
|
||||
Spacer(modifier = Modifier.height(100.dp))
|
||||
Column(
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
verticalArrangement = Arrangement.Center
|
||||
) {
|
||||
Row(
|
||||
Modifier
|
||||
.background(Color(0xFFCFC5C5))
|
||||
.padding(end = 10.dp)
|
||||
) {}
|
||||
Spacer(modifier = Modifier.height(20.dp))
|
||||
Text(text = "第三方登录", fontSize = 16.sp, color = Color.Gray)
|
||||
Row(
|
||||
Modifier
|
||||
.fillMaxWidth()
|
||||
.weight(1f),
|
||||
horizontalArrangement = Arrangement.Center,
|
||||
verticalAlignment = Alignment.Top
|
||||
) {
|
||||
repeat(3) {
|
||||
Column(
|
||||
Modifier.weight(1f),
|
||||
verticalArrangement = Arrangement.Center,
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
Image(
|
||||
modifier = Modifier.size(50.dp),
|
||||
painter = painterResource(id = R.drawable.qq),
|
||||
contentDescription = null
|
||||
)
|
||||
Text(
|
||||
"QQ",
|
||||
color = Color(0xffcdcdcd),
|
||||
fontSize = 16.sp,
|
||||
fontWeight = FontWeight.Bold
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Preview(showBackground = true, backgroundColor = 0xFFF5F0EE)
|
||||
@Composable
|
||||
fun Login() {
|
||||
LoginScreen()
|
||||
}
|
||||
@ -0,0 +1,346 @@
|
||||
package com.example.fruitandvegetableguide.ui.main
|
||||
|
||||
import android.widget.ImageButton
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.heightIn
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.paddingFromBaseline
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.lazy.grid.GridCells
|
||||
import androidx.compose.foundation.lazy.grid.LazyHorizontalGrid
|
||||
import androidx.compose.foundation.lazy.grid.items
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.AccountCircle
|
||||
import androidx.compose.material.icons.filled.Camera
|
||||
import androidx.compose.material.icons.filled.Search
|
||||
import androidx.compose.material.icons.filled.Spa
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.ButtonDefaults
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.NavigationBar
|
||||
import androidx.compose.material3.NavigationBarItem
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TextButton
|
||||
import androidx.compose.material3.TextField
|
||||
import androidx.compose.material3.TextFieldDefaults
|
||||
import androidx.compose.runtime.Composable
|
||||
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.layout.ContentScale
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.example.fruitandvegetableguide.data.local.LocalGuidesDataProvider.allGuides
|
||||
import com.example.fruitandvegetableguide.data.local.LocalPostsDataProvider.allPosts
|
||||
import com.example.fruitandvegetableguide.ui.theme.FruitandVegetableGuideTheme
|
||||
|
||||
//主页
|
||||
@Composable
|
||||
fun MainScreen(
|
||||
userid: Int?,
|
||||
onClickToSearch: () -> Unit = {},
|
||||
onClickToUser: () -> Unit = {},
|
||||
onClickToPhotograph: () -> Unit = {},
|
||||
onClickToGuide: () -> Unit = {},
|
||||
onClickToCommunity: () -> Unit = {},
|
||||
onClickToGuideDetail: () -> Unit = {},
|
||||
onClickToPostDetail: () -> Unit = {},
|
||||
) {
|
||||
FruitandVegetableGuideTheme() {
|
||||
Scaffold(bottomBar = {
|
||||
MyBottomNavigation(
|
||||
onClickToUser = onClickToUser,
|
||||
onClickToPhotograph = onClickToPhotograph
|
||||
)
|
||||
}) { padding ->
|
||||
HomeScreen(
|
||||
modifier = Modifier.padding(padding),
|
||||
onClickToSearch = onClickToSearch,
|
||||
onClickToGuide = onClickToGuide,
|
||||
onClickToCommunity = onClickToCommunity,
|
||||
onClickToGuideDetail = onClickToGuideDetail,
|
||||
onClickToPostDetail = onClickToPostDetail
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//主屏幕
|
||||
@Composable
|
||||
fun HomeScreen(
|
||||
modifier: Modifier = Modifier,
|
||||
onClickToSearch: () -> Unit,
|
||||
onClickToGuide: () -> Unit = {},
|
||||
onClickToCommunity: () -> Unit = {},
|
||||
onClickToGuideDetail: () -> Unit = {},
|
||||
onClickToPostDetail: () -> Unit = {},
|
||||
) {
|
||||
Column(modifier.verticalScroll(rememberScrollState())) {
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
SearchBar(
|
||||
Modifier.padding(horizontal = 16.dp),
|
||||
onClickToSearch = onClickToSearch
|
||||
)
|
||||
Column {
|
||||
TextButton(onClick = onClickToGuide) {
|
||||
Text(
|
||||
text = "指南",
|
||||
style = MaterialTheme.typography.titleMedium,
|
||||
modifier = Modifier
|
||||
.paddingFromBaseline(top = 40.dp, bottom = 16.dp)
|
||||
.padding(horizontal = 16.dp)
|
||||
)
|
||||
}
|
||||
GuideGrid(onClickToGuideDetail = onClickToGuideDetail)
|
||||
}
|
||||
// HomeSection(title = "指南") {
|
||||
// GuideGrid()
|
||||
// }
|
||||
Column {
|
||||
TextButton(onClick = onClickToCommunity) {
|
||||
Text(
|
||||
text = "社区",
|
||||
style = MaterialTheme.typography.titleMedium,
|
||||
modifier = Modifier
|
||||
.paddingFromBaseline(top = 40.dp, bottom = 16.dp)
|
||||
.padding(horizontal = 16.dp)
|
||||
)
|
||||
}
|
||||
PostGrid(onClickToPostDetail = onClickToPostDetail)
|
||||
}
|
||||
// HomeSection(title = "社区") {
|
||||
// PostGrid()
|
||||
// }
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
}
|
||||
}
|
||||
|
||||
//搜索框
|
||||
@Composable
|
||||
fun SearchBar(
|
||||
modifier: Modifier = Modifier,
|
||||
onClickToSearch: () -> Unit
|
||||
) {
|
||||
TextField(
|
||||
value = "", onValueChange = {},
|
||||
leadingIcon = {
|
||||
IconButton(onClick = onClickToSearch) {
|
||||
Icon(imageVector = Icons.Default.Search, contentDescription = null)
|
||||
}
|
||||
},
|
||||
colors = TextFieldDefaults.colors(
|
||||
unfocusedContainerColor = MaterialTheme.colorScheme.surface,
|
||||
focusedContainerColor = MaterialTheme.colorScheme.surface
|
||||
),
|
||||
placeholder = { Text(text = "搜索") },
|
||||
modifier = modifier
|
||||
.fillMaxWidth()
|
||||
.heightIn(56.dp)
|
||||
)
|
||||
}
|
||||
|
||||
//指南元素
|
||||
@Composable
|
||||
fun GuideElement(
|
||||
modifier: Modifier = Modifier,
|
||||
@DrawableRes drawable: Int,
|
||||
kind: String,
|
||||
onClickToGuideDetail: () -> Unit = {},
|
||||
) {
|
||||
Button(
|
||||
onClick = onClickToGuideDetail,
|
||||
colors = ButtonDefaults.buttonColors(
|
||||
containerColor = Color.White,
|
||||
// contentColor = Color.Black
|
||||
),
|
||||
contentPadding = PaddingValues(1.dp)
|
||||
) {
|
||||
Column(
|
||||
modifier = modifier,
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
) {
|
||||
Image(
|
||||
painter = painterResource(id = drawable),
|
||||
contentDescription = null,
|
||||
contentScale = ContentScale.Crop,
|
||||
modifier = Modifier
|
||||
.size(88.dp)
|
||||
.clip(CircleShape)
|
||||
)
|
||||
Text(
|
||||
text = kind,
|
||||
modifier = Modifier.paddingFromBaseline(top = 24.dp, bottom = 8.dp),
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
color = Color.Black
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
//帖子元素
|
||||
@Composable
|
||||
fun PostCard(
|
||||
modifier: Modifier = Modifier,
|
||||
@DrawableRes drawable: Int,
|
||||
title: String,
|
||||
onClickToPostDetail: () -> Unit = {},
|
||||
) {
|
||||
Surface(
|
||||
shape = MaterialTheme.shapes.medium,
|
||||
modifier = modifier,
|
||||
color = MaterialTheme.colorScheme.surfaceVariant,
|
||||
) {
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
modifier = Modifier.width(255.dp)
|
||||
) {
|
||||
Button(
|
||||
onClick = onClickToPostDetail,
|
||||
colors = ButtonDefaults.buttonColors(
|
||||
containerColor = Color.LightGray,
|
||||
)
|
||||
) {
|
||||
Image(
|
||||
painter = painterResource(id = drawable), contentDescription = null,
|
||||
contentScale = ContentScale.Crop,
|
||||
modifier = Modifier.size(80.dp)
|
||||
)
|
||||
Text(
|
||||
text = title,
|
||||
style = MaterialTheme.typography.titleMedium,
|
||||
modifier = Modifier.padding(horizontal = 16.dp)
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//指南的网格显示
|
||||
@Preview
|
||||
@Composable
|
||||
fun GuideGrid(
|
||||
modifier: Modifier = Modifier,
|
||||
onClickToGuideDetail: () -> Unit = {},
|
||||
) {
|
||||
LazyHorizontalGrid(
|
||||
rows = GridCells.Fixed(2),
|
||||
contentPadding = PaddingValues(horizontal = 8.dp),
|
||||
horizontalArrangement = Arrangement.spacedBy(8.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(2.dp),
|
||||
modifier = modifier.height(300.dp)
|
||||
) {
|
||||
items(allGuides) { item ->
|
||||
GuideElement(
|
||||
drawable = item.imgId,
|
||||
kind = item.kind,
|
||||
onClickToGuideDetail = onClickToGuideDetail
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//帖子的网格显示
|
||||
@Composable
|
||||
fun PostGrid(
|
||||
modifier: Modifier = Modifier,
|
||||
onClickToPostDetail: () -> Unit = {},
|
||||
) {
|
||||
LazyHorizontalGrid(
|
||||
rows = GridCells.Fixed(4),
|
||||
contentPadding = PaddingValues(horizontal = 16.dp),
|
||||
horizontalArrangement = Arrangement.spacedBy(16.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(16.dp),
|
||||
modifier = modifier.height(300.dp)
|
||||
) {
|
||||
items(allPosts) { item ->
|
||||
PostCard(
|
||||
drawable = item.imgId,
|
||||
title = item.title,
|
||||
onClickToPostDetail = onClickToPostDetail
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//小组件加上标题
|
||||
//@Composable
|
||||
//fun HomeSection(title: String, modifier: Modifier = Modifier, content: @Composable () -> Unit) {
|
||||
// Column(modifier) {
|
||||
// Text(
|
||||
// text = title,
|
||||
// style = MaterialTheme.typography.titleMedium,
|
||||
// modifier = Modifier
|
||||
// .paddingFromBaseline(top = 40.dp, bottom = 16.dp)
|
||||
// .padding(horizontal = 16.dp)
|
||||
// )
|
||||
// content()
|
||||
// }
|
||||
//}
|
||||
|
||||
//底部导航栏
|
||||
@Composable
|
||||
fun MyBottomNavigation(
|
||||
modifier: Modifier = Modifier,
|
||||
onClickToUser: () -> Unit = {},
|
||||
onClickToPhotograph: () -> Unit = {},
|
||||
) {
|
||||
NavigationBar(containerColor = MaterialTheme.colorScheme.surfaceVariant, modifier = modifier) {
|
||||
NavigationBarItem(icon = {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Spa,
|
||||
contentDescription = null
|
||||
)
|
||||
},
|
||||
label = { Text(text = "首页") },
|
||||
selected = true,
|
||||
onClick = { })
|
||||
NavigationBarItem(
|
||||
icon = {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Camera,
|
||||
contentDescription = null
|
||||
)
|
||||
},
|
||||
label = { Text(text = "识别") },
|
||||
selected = false,
|
||||
onClick = onClickToPhotograph
|
||||
)
|
||||
NavigationBarItem(icon = {
|
||||
Icon(
|
||||
imageVector = Icons.Default.AccountCircle,
|
||||
contentDescription = null
|
||||
)
|
||||
}, label = { Text(text = "用户") },
|
||||
selected = false,
|
||||
onClick = onClickToUser
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
//预览
|
||||
//@Preview(showBackground = true, backgroundColor = 0xFFF5F0EE)
|
||||
//@Composable
|
||||
//fun PostPrev() {
|
||||
// MainScreen()
|
||||
//}
|
||||
@ -0,0 +1,205 @@
|
||||
@file:OptIn(ExperimentalMaterial3Api::class)
|
||||
|
||||
package com.example.fruitandvegetableguide.ui.register
|
||||
|
||||
import android.widget.Toast
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.wrapContentSize
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.AccountBox
|
||||
import androidx.compose.material.icons.filled.ArrowBack
|
||||
import androidx.compose.material.icons.filled.Lock
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.ButtonDefaults
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TextField
|
||||
import androidx.compose.material3.TextFieldDefaults
|
||||
import androidx.compose.material3.TopAppBar
|
||||
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 androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.text.input.PasswordVisualTransformation
|
||||
import androidx.compose.ui.text.input.VisualTransformation
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import com.example.fruitandvegetableguide.R
|
||||
import com.example.fruitandvegetableguide.utils.register
|
||||
|
||||
@Preview(showBackground = true, backgroundColor = 0xFFF5F0EE)
|
||||
@Composable
|
||||
fun RegisterScreen(onClickBack: () -> Unit = {}) {
|
||||
var username by remember { mutableStateOf("") }
|
||||
var password by remember { mutableStateOf("") }
|
||||
var rePassword by remember { mutableStateOf("") }
|
||||
val pwdVisualTransformation = PasswordVisualTransformation()
|
||||
var showPwd by remember { mutableStateOf(true) }
|
||||
val transformation = if (showPwd) pwdVisualTransformation else VisualTransformation.None
|
||||
val context = LocalContext.current
|
||||
TopAppBar(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
title = {
|
||||
Text(
|
||||
text = "注册",
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.wrapContentSize(Alignment.Center)
|
||||
)
|
||||
},
|
||||
navigationIcon = {
|
||||
IconButton(onClick = onClickBack) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.ArrowBack,
|
||||
contentDescription = null
|
||||
)
|
||||
}
|
||||
})
|
||||
Column() {
|
||||
Spacer(modifier = Modifier.weight(1f))
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.weight(3f)
|
||||
.background(Color.White)
|
||||
.padding(40.dp)
|
||||
.fillMaxWidth(),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
verticalArrangement = Arrangement.Center
|
||||
) {
|
||||
Column {
|
||||
TextField(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
value = username,
|
||||
onValueChange = { str -> username = str },
|
||||
placeholder = {
|
||||
Text("账号")
|
||||
},
|
||||
colors = TextFieldDefaults.colors(focusedTextColor = Color.Black),
|
||||
leadingIcon = {
|
||||
Icon(
|
||||
imageVector = Icons.Default.AccountBox,
|
||||
contentDescription = null
|
||||
)
|
||||
}
|
||||
)
|
||||
TextField(
|
||||
value = password,
|
||||
onValueChange = { str -> password = str },
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
placeholder = {
|
||||
Text("密码")
|
||||
},
|
||||
visualTransformation = transformation,
|
||||
colors = TextFieldDefaults.colors(focusedTextColor = Color.Black),
|
||||
leadingIcon = {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Lock,
|
||||
contentDescription = null
|
||||
)
|
||||
},
|
||||
trailingIcon = {
|
||||
if (showPwd) {
|
||||
IconButton(onClick = { showPwd = !showPwd }) {
|
||||
Icon(
|
||||
painter = painterResource(id = R.drawable.sleep),
|
||||
contentDescription = null,
|
||||
Modifier.size(30.dp)
|
||||
)
|
||||
}
|
||||
} else {
|
||||
IconButton(onClick = { showPwd = !showPwd }) {
|
||||
Icon(
|
||||
painter = painterResource(id = R.drawable.eye),
|
||||
contentDescription = null,
|
||||
Modifier.size(30.dp)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
TextField(
|
||||
value = rePassword,
|
||||
onValueChange = { str -> rePassword = str },
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
placeholder = {
|
||||
Text("再次输入密码")
|
||||
},
|
||||
visualTransformation = transformation,
|
||||
colors = TextFieldDefaults.colors(focusedTextColor = Color.Black),
|
||||
leadingIcon = {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Lock,
|
||||
contentDescription = null
|
||||
)
|
||||
},
|
||||
trailingIcon = {
|
||||
if (showPwd) {
|
||||
IconButton(onClick = { showPwd = !showPwd }) {
|
||||
Icon(
|
||||
painter = painterResource(id = R.drawable.sleep),
|
||||
contentDescription = null,
|
||||
Modifier.size(30.dp)
|
||||
)
|
||||
}
|
||||
} else {
|
||||
IconButton(onClick = { showPwd = !showPwd }) {
|
||||
Icon(
|
||||
painter = painterResource(id = R.drawable.eye),
|
||||
contentDescription = null,
|
||||
Modifier.size(30.dp)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
Spacer(modifier = Modifier.height(20.dp))
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.Center,
|
||||
verticalAlignment = Alignment.CenterVertically
|
||||
) {
|
||||
Button(
|
||||
onClick = {
|
||||
if (username != "" && password != "" && password == rePassword && register(
|
||||
username,
|
||||
password
|
||||
)
|
||||
) {
|
||||
Toast.makeText(context, "注册成功", Toast.LENGTH_SHORT).show()
|
||||
onClickBack()
|
||||
} else {
|
||||
Toast.makeText(context, "注册失败", Toast.LENGTH_SHORT).show()
|
||||
}
|
||||
},
|
||||
colors = ButtonDefaults.buttonColors(
|
||||
containerColor = Color(
|
||||
0xff5c59fe
|
||||
)
|
||||
),
|
||||
contentPadding = PaddingValues(12.dp, 16.dp)
|
||||
) {
|
||||
Text("注册", color = Color.White, fontSize = 18.sp)
|
||||
}
|
||||
}
|
||||
}
|
||||
Spacer(modifier = Modifier.height(120.dp))
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,71 @@
|
||||
@file:OptIn(ExperimentalMaterial3Api::class)
|
||||
|
||||
package com.example.fruitandvegetableguide.ui.search
|
||||
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.requiredHeight
|
||||
import androidx.compose.foundation.layout.wrapContentSize
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.ArrowBack
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TopAppBar
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
|
||||
@Preview(showBackground = true, backgroundColor = 0xFFF5F0EE)
|
||||
@Composable
|
||||
fun SearchScreen(
|
||||
onClickBack: () -> Unit = {},
|
||||
onClickToGuideDetail: () -> Unit = {},
|
||||
onClickToPostDetail: () -> Unit = {}
|
||||
) {
|
||||
Column(modifier = Modifier.fillMaxSize()) {
|
||||
TopAppBar(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
title = {
|
||||
Text(
|
||||
text = "搜索",
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.wrapContentSize(Alignment.Center)
|
||||
)
|
||||
},
|
||||
navigationIcon = {
|
||||
IconButton(onClick = onClickBack) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.ArrowBack,
|
||||
contentDescription = null
|
||||
)
|
||||
}
|
||||
})
|
||||
Spacer(modifier = Modifier.requiredHeight(10.dp))
|
||||
Text(
|
||||
text = "搜索结果页",
|
||||
modifier = Modifier.align(alignment = Alignment.CenterHorizontally)
|
||||
)
|
||||
Spacer(modifier = Modifier.requiredHeight(10.dp))
|
||||
Button(
|
||||
onClick = onClickToGuideDetail,
|
||||
modifier = Modifier.align(alignment = Alignment.CenterHorizontally)
|
||||
) {
|
||||
Text(text = "指南详情页")
|
||||
}
|
||||
Spacer(modifier = Modifier.requiredHeight(10.dp))
|
||||
Button(
|
||||
onClick = onClickToPostDetail,
|
||||
modifier = Modifier.align(alignment = Alignment.CenterHorizontally)
|
||||
) {
|
||||
Text(text = "帖子详情页")
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,52 @@
|
||||
@file:OptIn(ExperimentalMaterial3Api::class)
|
||||
|
||||
package com.example.fruitandvegetableguide.ui.user
|
||||
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.requiredHeight
|
||||
import androidx.compose.foundation.layout.wrapContentSize
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.ArrowBack
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TopAppBar
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
|
||||
@Composable
|
||||
fun MyPostScreen(onClickBack: () -> Unit = {}) {
|
||||
Column(modifier = Modifier.fillMaxSize()) {
|
||||
TopAppBar(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
title = {
|
||||
Text(
|
||||
text = "MyPost",
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.wrapContentSize(Alignment.Center)
|
||||
)
|
||||
},
|
||||
navigationIcon = {
|
||||
IconButton(onClick = onClickBack) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.ArrowBack,
|
||||
contentDescription = null
|
||||
)
|
||||
}
|
||||
})
|
||||
Spacer(modifier = Modifier.requiredHeight(10.dp))
|
||||
Text(
|
||||
text = "我的帖子页",
|
||||
modifier = Modifier.align(alignment = Alignment.CenterHorizontally)
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,115 @@
|
||||
@file:OptIn(ExperimentalMaterial3Api::class)
|
||||
|
||||
package com.example.fruitandvegetableguide.ui.user
|
||||
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.requiredHeight
|
||||
import androidx.compose.foundation.layout.wrapContentSize
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.AccountCircle
|
||||
import androidx.compose.material.icons.filled.ArrowBack
|
||||
import androidx.compose.material.icons.filled.Camera
|
||||
import androidx.compose.material.icons.filled.Spa
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.NavigationBar
|
||||
import androidx.compose.material3.NavigationBarItem
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TopAppBar
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
|
||||
@Composable
|
||||
fun UserScreen(
|
||||
onClickToMain: () -> Unit = {},
|
||||
onClickToMyPost: () -> Unit = {},
|
||||
onClickToPhotograph: () -> Unit = {},
|
||||
) {
|
||||
Scaffold(bottomBar = {
|
||||
MyBottomNavigation(
|
||||
onClickToMain = onClickToMain,
|
||||
onClickToPhotograph = onClickToPhotograph
|
||||
)
|
||||
}) { padding ->
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.padding(padding)
|
||||
) {
|
||||
TopAppBar(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
title = {
|
||||
Text(
|
||||
text = "用户",
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.wrapContentSize(Alignment.Center)
|
||||
)
|
||||
})
|
||||
Spacer(modifier = Modifier.requiredHeight(10.dp))
|
||||
Text(
|
||||
text = "用户页",
|
||||
modifier = Modifier.align(alignment = Alignment.CenterHorizontally)
|
||||
)
|
||||
Spacer(modifier = Modifier.requiredHeight(10.dp))
|
||||
Button(
|
||||
onClick = onClickToMyPost,
|
||||
modifier = Modifier.align(alignment = Alignment.CenterHorizontally)
|
||||
) {
|
||||
Text(text = "我的帖子")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//Unable to match the desired swap behavior.
|
||||
//底部导航栏
|
||||
@Composable
|
||||
fun MyBottomNavigation(
|
||||
modifier: Modifier = Modifier,
|
||||
onClickToMain: () -> Unit = {},
|
||||
onClickToPhotograph: () -> Unit = {},
|
||||
) {
|
||||
NavigationBar(containerColor = MaterialTheme.colorScheme.surfaceVariant, modifier = modifier) {
|
||||
NavigationBarItem(
|
||||
icon = {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Spa,
|
||||
contentDescription = null
|
||||
)
|
||||
},
|
||||
label = { Text(text = "首页") },
|
||||
selected = false,
|
||||
onClick = onClickToMain
|
||||
)
|
||||
NavigationBarItem(
|
||||
icon = {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Camera,
|
||||
contentDescription = null
|
||||
)
|
||||
},
|
||||
label = { Text(text = "识别") },
|
||||
selected = false,
|
||||
onClick = onClickToPhotograph
|
||||
)
|
||||
NavigationBarItem(icon = {
|
||||
Icon(
|
||||
imageVector = Icons.Default.AccountCircle,
|
||||
contentDescription = null
|
||||
)
|
||||
}, label = { Text(text = "用户") },
|
||||
selected = true,
|
||||
onClick = { })
|
||||
}
|
||||
}
|
||||
Loading…
Reference in new issue