10.16 合并 #2

Merged
p5gy6sexf merged 3 commits from djm_branch into master 2 years ago

Binary file not shown.

@ -52,6 +52,8 @@ dependencies {
implementation "androidx.appcompat:appcompat:1.6.1"
implementation "androidx.core:core-ktx:1.10.1"
implementation "com.google.android.material:material:1.9.0"
implementation 'androidx.core:core-ktx:+'
implementation 'androidx.core:core-ktx:+'
def composeBom = platform('androidx.compose:compose-bom:2023.08.00')
implementation(composeBom)

@ -14,15 +14,11 @@
tools:targetApi="31">
<!--android:exported=“false”当前Activity是否可以被另一个Application的组件启动true允许被启动false不允许被启动-->
<activity
android:name=".ui.MainActivity"
android:theme="@style/Theme.AppCompat.Light.NoActionBar"
android:exported="true" />
<activity android:name=".ui.LoginActivity"
android:name=".MyActivity"
android:theme="@style/Theme.AppCompat.Light.NoActionBar"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>

@ -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,48 @@
package com.example.fruitandvegetableguide
import android.os.Bundle
import androidx.activity.compose.setContent
import androidx.appcompat.app.AppCompatActivity
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Surface
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
import androidx.navigation.compose.currentBackStackEntryAsState
import androidx.navigation.compose.rememberNavController
import com.example.fruitandvegetableguide.ui.login.LoginScreen
import com.example.fruitandvegetableguide.ui.theme.FruitandVegetableGuideTheme
class MyActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
FruitandVegetableGuideTheme() {
Surface(
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
) {
MyApp()
}
}
}
}
}
@Composable
fun MyApp() {
//使用 rememberNavController() 获取 NavController因为它是整个应用的根可组合项和入口点
val navController = rememberNavController()
// val currentBackStack by navController.currentBackStackEntryAsState()
// val currentDestination = currentBackStack?.destination
Scaffold { innerPadding ->
NavHost(
navController = navController,
modifier = Modifier.padding(innerPadding)
)
}
}

@ -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
)

@ -1,5 +1,6 @@
package com.example.fruitandvegetableguide.data
//指南数据类
data class Guide(
val id: Long,
val imgId: Int,

@ -1,5 +1,6 @@
package com.example.fruitandvegetableguide.data
//帖子数据类
data class Post(
val id: Long,
val userId: Long,

@ -0,0 +1,3 @@
package com.example.fruitandvegetableguide.data.dbutils
// TODO 这里放数据库工具方法

@ -2,10 +2,11 @@ package com.example.fruitandvegetableguide.data.local
import com.example.fruitandvegetableguide.data.Account
//本地用户测试数据
object LocalAccountsDataProvider {
val allUserAccounts = mutableListOf(
Account("aaa",1,"123456"),
Account("bbb",2,"123456"),
Account("ccc",3,"123456")
Account(1,"aaa","123456"),
Account(2,"bbb","123456"),
Account(3,"ccc","123456")
)
}

@ -3,6 +3,7 @@ package com.example.fruitandvegetableguide.data.local
import com.example.fruitandvegetableguide.data.Guide
import com.example.fruitandvegetableguide.R
//本地指南测试数据
object LocalGuidesDataProvider {
val allGuides = mutableListOf(
Guide(
@ -12,7 +13,7 @@ object LocalGuidesDataProvider {
"https://ai-public-console.cdn.bcebos.com/portal-pc-static/1694501570778/images/technology/imagerecognition/ingredient/2.jpg",
"一般人皆可食用,尤以[癌症、高血压、夜盲症干眼症、营养不良、皮肤粗糙]者为最。",
"[饮酒过量]者不宜食用",
"热量: 37千卡, 蛋白质: 1克, 碳水化合物: 8.8克, 膳食纤维3.2克, 胡萝卜素: 4130微克",
"热量: 37千卡, 蛋白质: 1克\n碳水化合物: 8.8克, 膳食纤维3.2克\n 胡萝卜素: 4130微克",
"炝腌萝卜"
),
Guide(
@ -66,7 +67,7 @@ object LocalGuidesDataProvider {
"番茄乌冬面"
),
Guide(
1,
7,
R.drawable.carrots,
"胡萝卜",
"https://ai-public-console.cdn.bcebos.com/portal-pc-static/1694501570778/images/technology/imagerecognition/ingredient/2.jpg",
@ -76,7 +77,7 @@ object LocalGuidesDataProvider {
"炝腌萝卜"
),
Guide(
2,
8,
R.drawable.cucumbers,
"黄瓜",
"https://ai-public-console.cdn.bcebos.com/portal-pc-static/1694501570778/images/technology/imagerecognition/ingredient/3.jpg",
@ -86,7 +87,7 @@ object LocalGuidesDataProvider {
"黄瓜玉子烧"
),
Guide(
3,
9,
R.drawable.tomatoes,
"西红柿",
"https://bkimg.cdn.bcebos.com/pic/0823dd54564e9258d109b7bb1bd4c658ccbf6c81e012?x-bce-process=image/watermark,image_d2F0ZXIvYmFpa2U5Mg==,g_7,xp_5,yp_5/format,f_auto",
@ -96,7 +97,7 @@ object LocalGuidesDataProvider {
"番茄乌冬面"
),
Guide(
4,
10,
R.drawable.carrots,
"胡萝卜",
"https://ai-public-console.cdn.bcebos.com/portal-pc-static/1694501570778/images/technology/imagerecognition/ingredient/2.jpg",
@ -106,7 +107,7 @@ object LocalGuidesDataProvider {
"炝腌萝卜"
),
Guide(
5,
11,
R.drawable.cucumbers,
"黄瓜",
"https://ai-public-console.cdn.bcebos.com/portal-pc-static/1694501570778/images/technology/imagerecognition/ingredient/3.jpg",
@ -116,7 +117,7 @@ object LocalGuidesDataProvider {
"黄瓜玉子烧"
),
Guide(
6,
12,
R.drawable.tomatoes,
"西红柿",
"https://bkimg.cdn.bcebos.com/pic/0823dd54564e9258d109b7bb1bd4c658ccbf6c81e012?x-bce-process=image/watermark,image_d2F0ZXIvYmFpa2U5Mg==,g_7,xp_5,yp_5/format,f_auto",

@ -3,6 +3,7 @@ package com.example.fruitandvegetableguide.data.local
import com.example.fruitandvegetableguide.R
import com.example.fruitandvegetableguide.data.Post
//本地帖子测试数据
object LocalPostsDataProvider {
val allPosts = mutableListOf(
Post(
@ -66,7 +67,7 @@ object LocalPostsDataProvider {
"有没有好心人教教如何挑选生姜,大的和小的有什么区别"
),
Post(
1,
7,
1,
"白菜怎么挑选",
R.drawable.cabbage,
@ -76,7 +77,7 @@ object LocalPostsDataProvider {
"黄色菜叶多说明农家肥用得多。一般来说,农家肥种的白菜个头大,菜瓷实,黄色菜叶比较多,吃起来口感也要好一些。颜色发绿的白菜叶片厚实,吃起来口感比较粗,特别耐储存。\n"
),
Post(
2,
8,
2,
"关于西瓜的挑选经验",
R.drawable.watermelon,
@ -88,7 +89,7 @@ object LocalPostsDataProvider {
"5、听声音 将西瓜托在手里,手指轻轻敲,如果发出“咚、咚”的清脆声,并且托瓜的手有震动的感觉就是熟透的瓜,一般瓜味也会比较甜。"
),
Post(
3,
9,
3,
"生姜怎么挑选?",
R.drawable.ginger,
@ -96,7 +97,7 @@ object LocalPostsDataProvider {
"有没有好心人教教如何挑选生姜,大的和小的有什么区别"
),
Post(
4,
10,
1,
"白菜怎么挑选",
R.drawable.cabbage,
@ -106,7 +107,7 @@ object LocalPostsDataProvider {
"黄色菜叶多说明农家肥用得多。一般来说,农家肥种的白菜个头大,菜瓷实,黄色菜叶比较多,吃起来口感也要好一些。颜色发绿的白菜叶片厚实,吃起来口感比较粗,特别耐储存。\n"
),
Post(
5,
11,
2,
"关于西瓜的挑选经验",
R.drawable.watermelon,
@ -118,7 +119,7 @@ object LocalPostsDataProvider {
"5、听声音 将西瓜托在手里,手指轻轻敲,如果发出“咚、咚”的清脆声,并且托瓜的手有震动的感觉就是熟透的瓜,一般瓜味也会比较甜。"
),
Post(
6,
13,
3,
"生姜怎么挑选?",
R.drawable.ginger,
@ -126,7 +127,7 @@ object LocalPostsDataProvider {
"有没有好心人教教如何挑选生姜,大的和小的有什么区别"
),
Post(
1,
14,
1,
"白菜怎么挑选",
R.drawable.cabbage,
@ -136,7 +137,7 @@ object LocalPostsDataProvider {
"黄色菜叶多说明农家肥用得多。一般来说,农家肥种的白菜个头大,菜瓷实,黄色菜叶比较多,吃起来口感也要好一些。颜色发绿的白菜叶片厚实,吃起来口感比较粗,特别耐储存。\n"
),
Post(
2,
15,
2,
"关于西瓜的挑选经验",
R.drawable.watermelon,
@ -148,7 +149,7 @@ object LocalPostsDataProvider {
"5、听声音 将西瓜托在手里,手指轻轻敲,如果发出“咚、咚”的清脆声,并且托瓜的手有震动的感觉就是熟透的瓜,一般瓜味也会比较甜。"
),
Post(
3,
16,
3,
"生姜怎么挑选?",
R.drawable.ginger,
@ -156,7 +157,7 @@ object LocalPostsDataProvider {
"有没有好心人教教如何挑选生姜,大的和小的有什么区别"
),
Post(
4,
17,
1,
"白菜怎么挑选",
R.drawable.cabbage,
@ -166,7 +167,7 @@ object LocalPostsDataProvider {
"黄色菜叶多说明农家肥用得多。一般来说,农家肥种的白菜个头大,菜瓷实,黄色菜叶比较多,吃起来口感也要好一些。颜色发绿的白菜叶片厚实,吃起来口感比较粗,特别耐储存。\n"
),
Post(
5,
18,
2,
"关于西瓜的挑选经验",
R.drawable.watermelon,
@ -178,7 +179,7 @@ object LocalPostsDataProvider {
"5、听声音 将西瓜托在手里,手指轻轻敲,如果发出“咚、咚”的清脆声,并且托瓜的手有震动的感觉就是熟透的瓜,一般瓜味也会比较甜。"
),
Post(
6,
19,
3,
"生姜怎么挑选?",
R.drawable.ginger,

@ -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 = { })
}
}

@ -0,0 +1,21 @@
package com.example.fruitandvegetableguide.utils
// TODO 这里放页面逻辑相关代码
fun loginVerification(username: String, password: String): Int {
// TODO 1.登录验证
// 输入username:用户名, password:密码
// 逻辑查询用户表用户名和密码正确返回id;用户名和密码不匹配返回-1;用户表中没有该用户名返回-1
// 输出id或-1
// 将下面的测试代码清空完成需要的代码之后的TODO同此
return 1
}
fun register(username: String, password: String): Boolean {
// TODO 2.注册
// 输入username:用户名, password:密码
// 逻辑:插入用户表;插入成功返回true;插入失败返回false
// 输出true或false
// 将下面的测试代码清空完成需要的代码之后的TODO同此
return true
}
Loading…
Cancel
Save