diff --git a/doc/界面设计.docx b/doc/界面设计.docx new file mode 100644 index 0000000..b34cd48 Binary files /dev/null and b/doc/界面设计.docx differ diff --git a/src/FruitandVegetableGuide/app/build.gradle b/src/FruitandVegetableGuide/app/build.gradle index 5376ae4..d300838 100644 --- a/src/FruitandVegetableGuide/app/build.gradle +++ b/src/FruitandVegetableGuide/app/build.gradle @@ -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) diff --git a/src/FruitandVegetableGuide/app/src/main/AndroidManifest.xml b/src/FruitandVegetableGuide/app/src/main/AndroidManifest.xml index b53bc0f..097e5ee 100644 --- a/src/FruitandVegetableGuide/app/src/main/AndroidManifest.xml +++ b/src/FruitandVegetableGuide/app/src/main/AndroidManifest.xml @@ -14,15 +14,11 @@ tools:targetApi="31"> - - diff --git a/src/FruitandVegetableGuide/app/src/main/java/com/example/fruitandvegetableguide/Destinations.kt b/src/FruitandVegetableGuide/app/src/main/java/com/example/fruitandvegetableguide/Destinations.kt new file mode 100644 index 0000000..430408d --- /dev/null +++ b/src/FruitandVegetableGuide/app/src/main/java/com/example/fruitandvegetableguide/Destinations.kt @@ -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) \ No newline at end of file diff --git a/src/FruitandVegetableGuide/app/src/main/java/com/example/fruitandvegetableguide/MyActivity.kt b/src/FruitandVegetableGuide/app/src/main/java/com/example/fruitandvegetableguide/MyActivity.kt new file mode 100644 index 0000000..d973dc9 --- /dev/null +++ b/src/FruitandVegetableGuide/app/src/main/java/com/example/fruitandvegetableguide/MyActivity.kt @@ -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) + ) + } +} + diff --git a/src/FruitandVegetableGuide/app/src/main/java/com/example/fruitandvegetableguide/NavHost.kt b/src/FruitandVegetableGuide/app/src/main/java/com/example/fruitandvegetableguide/NavHost.kt new file mode 100644 index 0000000..9f7a6a9 --- /dev/null +++ b/src/FruitandVegetableGuide/app/src/main/java/com/example/fruitandvegetableguide/NavHost.kt @@ -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 } diff --git a/src/FruitandVegetableGuide/app/src/main/java/com/example/fruitandvegetableguide/data/Account.kt b/src/FruitandVegetableGuide/app/src/main/java/com/example/fruitandvegetableguide/data/Account.kt index 92a8f04..f4bc508 100644 --- a/src/FruitandVegetableGuide/app/src/main/java/com/example/fruitandvegetableguide/data/Account.kt +++ b/src/FruitandVegetableGuide/app/src/main/java/com/example/fruitandvegetableguide/data/Account.kt @@ -1,7 +1,8 @@ package com.example.fruitandvegetableguide.data +//用户数据类 data class Account( - val username: String, val id:Long, + val username: String, val password:String ) diff --git a/src/FruitandVegetableGuide/app/src/main/java/com/example/fruitandvegetableguide/data/Guide.kt b/src/FruitandVegetableGuide/app/src/main/java/com/example/fruitandvegetableguide/data/Guide.kt index 84d7a9a..6b21ffd 100644 --- a/src/FruitandVegetableGuide/app/src/main/java/com/example/fruitandvegetableguide/data/Guide.kt +++ b/src/FruitandVegetableGuide/app/src/main/java/com/example/fruitandvegetableguide/data/Guide.kt @@ -1,5 +1,6 @@ package com.example.fruitandvegetableguide.data +//指南数据类 data class Guide( val id: Long, val imgId: Int, diff --git a/src/FruitandVegetableGuide/app/src/main/java/com/example/fruitandvegetableguide/data/Post.kt b/src/FruitandVegetableGuide/app/src/main/java/com/example/fruitandvegetableguide/data/Post.kt index 2a068dd..d2a4973 100644 --- a/src/FruitandVegetableGuide/app/src/main/java/com/example/fruitandvegetableguide/data/Post.kt +++ b/src/FruitandVegetableGuide/app/src/main/java/com/example/fruitandvegetableguide/data/Post.kt @@ -1,5 +1,6 @@ package com.example.fruitandvegetableguide.data +//帖子数据类 data class Post( val id: Long, val userId: Long, diff --git a/src/FruitandVegetableGuide/app/src/main/java/com/example/fruitandvegetableguide/data/dbutils/DBUtils.kt b/src/FruitandVegetableGuide/app/src/main/java/com/example/fruitandvegetableguide/data/dbutils/DBUtils.kt new file mode 100644 index 0000000..b788ade --- /dev/null +++ b/src/FruitandVegetableGuide/app/src/main/java/com/example/fruitandvegetableguide/data/dbutils/DBUtils.kt @@ -0,0 +1,3 @@ +package com.example.fruitandvegetableguide.data.dbutils + +// TODO 这里放数据库工具方法 \ No newline at end of file diff --git a/src/FruitandVegetableGuide/app/src/main/java/com/example/fruitandvegetableguide/data/local/LocalAccountsDataProvider.kt b/src/FruitandVegetableGuide/app/src/main/java/com/example/fruitandvegetableguide/data/local/LocalAccountsDataProvider.kt index 1141a6a..da3f71d 100644 --- a/src/FruitandVegetableGuide/app/src/main/java/com/example/fruitandvegetableguide/data/local/LocalAccountsDataProvider.kt +++ b/src/FruitandVegetableGuide/app/src/main/java/com/example/fruitandvegetableguide/data/local/LocalAccountsDataProvider.kt @@ -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") ) } \ No newline at end of file diff --git a/src/FruitandVegetableGuide/app/src/main/java/com/example/fruitandvegetableguide/data/local/LocalGuidesDataProvider.kt b/src/FruitandVegetableGuide/app/src/main/java/com/example/fruitandvegetableguide/data/local/LocalGuidesDataProvider.kt index c1f7497..06de5f1 100644 --- a/src/FruitandVegetableGuide/app/src/main/java/com/example/fruitandvegetableguide/data/local/LocalGuidesDataProvider.kt +++ b/src/FruitandVegetableGuide/app/src/main/java/com/example/fruitandvegetableguide/data/local/LocalGuidesDataProvider.kt @@ -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", diff --git a/src/FruitandVegetableGuide/app/src/main/java/com/example/fruitandvegetableguide/data/local/LocalPostsDataProvider.kt b/src/FruitandVegetableGuide/app/src/main/java/com/example/fruitandvegetableguide/data/local/LocalPostsDataProvider.kt index b83fa9f..7e26df7 100644 --- a/src/FruitandVegetableGuide/app/src/main/java/com/example/fruitandvegetableguide/data/local/LocalPostsDataProvider.kt +++ b/src/FruitandVegetableGuide/app/src/main/java/com/example/fruitandvegetableguide/data/local/LocalPostsDataProvider.kt @@ -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, diff --git a/src/FruitandVegetableGuide/app/src/main/java/com/example/fruitandvegetableguide/ui/ImgRecognitionPage.kt b/src/FruitandVegetableGuide/app/src/main/java/com/example/fruitandvegetableguide/ui/ImgRecognitionPage.kt deleted file mode 100644 index 132bbe1..0000000 --- a/src/FruitandVegetableGuide/app/src/main/java/com/example/fruitandvegetableguide/ui/ImgRecognitionPage.kt +++ /dev/null @@ -1,2 +0,0 @@ -package com.example.fruitandvegetableguide.ui - diff --git a/src/FruitandVegetableGuide/app/src/main/java/com/example/fruitandvegetableguide/ui/LoginActivity.kt b/src/FruitandVegetableGuide/app/src/main/java/com/example/fruitandvegetableguide/ui/LoginActivity.kt deleted file mode 100644 index 32212cf..0000000 --- a/src/FruitandVegetableGuide/app/src/main/java/com/example/fruitandvegetableguide/ui/LoginActivity.kt +++ /dev/null @@ -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() -} diff --git a/src/FruitandVegetableGuide/app/src/main/java/com/example/fruitandvegetableguide/ui/MainActivity.kt b/src/FruitandVegetableGuide/app/src/main/java/com/example/fruitandvegetableguide/ui/MainActivity.kt deleted file mode 100644 index d56ae2a..0000000 --- a/src/FruitandVegetableGuide/app/src/main/java/com/example/fruitandvegetableguide/ui/MainActivity.kt +++ /dev/null @@ -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() -} diff --git a/src/FruitandVegetableGuide/app/src/main/java/com/example/fruitandvegetableguide/ui/community/CommunityScreen.kt b/src/FruitandVegetableGuide/app/src/main/java/com/example/fruitandvegetableguide/ui/community/CommunityScreen.kt new file mode 100644 index 0000000..e9c222f --- /dev/null +++ b/src/FruitandVegetableGuide/app/src/main/java/com/example/fruitandvegetableguide/ui/community/CommunityScreen.kt @@ -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 = "帖子编辑页") + } + } +} \ No newline at end of file diff --git a/src/FruitandVegetableGuide/app/src/main/java/com/example/fruitandvegetableguide/ui/community/PostDetailScreen.kt b/src/FruitandVegetableGuide/app/src/main/java/com/example/fruitandvegetableguide/ui/community/PostDetailScreen.kt new file mode 100644 index 0000000..c1ad9de --- /dev/null +++ b/src/FruitandVegetableGuide/app/src/main/java/com/example/fruitandvegetableguide/ui/community/PostDetailScreen.kt @@ -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)) + } +} \ No newline at end of file diff --git a/src/FruitandVegetableGuide/app/src/main/java/com/example/fruitandvegetableguide/ui/community/PostEditScreen.kt b/src/FruitandVegetableGuide/app/src/main/java/com/example/fruitandvegetableguide/ui/community/PostEditScreen.kt new file mode 100644 index 0000000..0bb7eb2 --- /dev/null +++ b/src/FruitandVegetableGuide/app/src/main/java/com/example/fruitandvegetableguide/ui/community/PostEditScreen.kt @@ -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)) + } +} \ No newline at end of file diff --git a/src/FruitandVegetableGuide/app/src/main/java/com/example/fruitandvegetableguide/ui/guide/GuideDetailScreen.kt b/src/FruitandVegetableGuide/app/src/main/java/com/example/fruitandvegetableguide/ui/guide/GuideDetailScreen.kt new file mode 100644 index 0000000..da8fb92 --- /dev/null +++ b/src/FruitandVegetableGuide/app/src/main/java/com/example/fruitandvegetableguide/ui/guide/GuideDetailScreen.kt @@ -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)) + } +} \ No newline at end of file diff --git a/src/FruitandVegetableGuide/app/src/main/java/com/example/fruitandvegetableguide/ui/guide/GuideScreen.kt b/src/FruitandVegetableGuide/app/src/main/java/com/example/fruitandvegetableguide/ui/guide/GuideScreen.kt new file mode 100644 index 0000000..5b9f6ab --- /dev/null +++ b/src/FruitandVegetableGuide/app/src/main/java/com/example/fruitandvegetableguide/ui/guide/GuideScreen.kt @@ -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 = "指南详情页") + } + } +} \ No newline at end of file diff --git a/src/FruitandVegetableGuide/app/src/main/java/com/example/fruitandvegetableguide/ui/imgrecognition/PhotographScreen.kt b/src/FruitandVegetableGuide/app/src/main/java/com/example/fruitandvegetableguide/ui/imgrecognition/PhotographScreen.kt new file mode 100644 index 0000000..b1c93c1 --- /dev/null +++ b/src/FruitandVegetableGuide/app/src/main/java/com/example/fruitandvegetableguide/ui/imgrecognition/PhotographScreen.kt @@ -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 = "识别") + } + } +} \ No newline at end of file diff --git a/src/FruitandVegetableGuide/app/src/main/java/com/example/fruitandvegetableguide/ui/imgrecognition/RecognizeResultScreen.kt b/src/FruitandVegetableGuide/app/src/main/java/com/example/fruitandvegetableguide/ui/imgrecognition/RecognizeResultScreen.kt new file mode 100644 index 0000000..082b3e5 --- /dev/null +++ b/src/FruitandVegetableGuide/app/src/main/java/com/example/fruitandvegetableguide/ui/imgrecognition/RecognizeResultScreen.kt @@ -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)) + } +} \ No newline at end of file diff --git a/src/FruitandVegetableGuide/app/src/main/java/com/example/fruitandvegetableguide/ui/login/LoginScreen.kt b/src/FruitandVegetableGuide/app/src/main/java/com/example/fruitandvegetableguide/ui/login/LoginScreen.kt new file mode 100644 index 0000000..d991df7 --- /dev/null +++ b/src/FruitandVegetableGuide/app/src/main/java/com/example/fruitandvegetableguide/ui/login/LoginScreen.kt @@ -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() +} \ No newline at end of file diff --git a/src/FruitandVegetableGuide/app/src/main/java/com/example/fruitandvegetableguide/ui/main/MainScreen.kt b/src/FruitandVegetableGuide/app/src/main/java/com/example/fruitandvegetableguide/ui/main/MainScreen.kt new file mode 100644 index 0000000..c66eca9 --- /dev/null +++ b/src/FruitandVegetableGuide/app/src/main/java/com/example/fruitandvegetableguide/ui/main/MainScreen.kt @@ -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() +//} diff --git a/src/FruitandVegetableGuide/app/src/main/java/com/example/fruitandvegetableguide/ui/register/RegisterScreen.kt b/src/FruitandVegetableGuide/app/src/main/java/com/example/fruitandvegetableguide/ui/register/RegisterScreen.kt new file mode 100644 index 0000000..2fd24ba --- /dev/null +++ b/src/FruitandVegetableGuide/app/src/main/java/com/example/fruitandvegetableguide/ui/register/RegisterScreen.kt @@ -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)) + } +} \ No newline at end of file diff --git a/src/FruitandVegetableGuide/app/src/main/java/com/example/fruitandvegetableguide/ui/search/SearchScreen.kt b/src/FruitandVegetableGuide/app/src/main/java/com/example/fruitandvegetableguide/ui/search/SearchScreen.kt new file mode 100644 index 0000000..6afbcf5 --- /dev/null +++ b/src/FruitandVegetableGuide/app/src/main/java/com/example/fruitandvegetableguide/ui/search/SearchScreen.kt @@ -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 = "帖子详情页") + } + } +} \ No newline at end of file diff --git a/src/FruitandVegetableGuide/app/src/main/java/com/example/fruitandvegetableguide/ui/user/MyPostScreen.kt b/src/FruitandVegetableGuide/app/src/main/java/com/example/fruitandvegetableguide/ui/user/MyPostScreen.kt new file mode 100644 index 0000000..8539336 --- /dev/null +++ b/src/FruitandVegetableGuide/app/src/main/java/com/example/fruitandvegetableguide/ui/user/MyPostScreen.kt @@ -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) + ) + } +} \ No newline at end of file diff --git a/src/FruitandVegetableGuide/app/src/main/java/com/example/fruitandvegetableguide/ui/user/UserScreen.kt b/src/FruitandVegetableGuide/app/src/main/java/com/example/fruitandvegetableguide/ui/user/UserScreen.kt new file mode 100644 index 0000000..07daf87 --- /dev/null +++ b/src/FruitandVegetableGuide/app/src/main/java/com/example/fruitandvegetableguide/ui/user/UserScreen.kt @@ -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 = { }) + } +} \ No newline at end of file diff --git a/src/FruitandVegetableGuide/app/src/main/java/com/example/fruitandvegetableguide/utils/Utils.kt b/src/FruitandVegetableGuide/app/src/main/java/com/example/fruitandvegetableguide/utils/Utils.kt new file mode 100644 index 0000000..18d2484 --- /dev/null +++ b/src/FruitandVegetableGuide/app/src/main/java/com/example/fruitandvegetableguide/utils/Utils.kt @@ -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 +}