diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 0ceb916..436d7b4 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -129,6 +129,8 @@ dependencies { kapt("androidx.room:room-compiler:${rootProject.extra["room_version"]}") // optional - Kotlin Extensions and Coroutines support for Room implementation("androidx.room:room-ktx:${rootProject.extra["room_version"]}") + // + implementation("androidx.constraintlayout:constraintlayout-compose:1.0.0-alpha03") // optional - Test helpers testImplementation("androidx.room:room-testing:${rootProject.extra["room_version"]}") //测试 diff --git a/app/src/androidTest/java/com/gyf/csams/TestPreview.kt b/app/src/androidTest/java/com/gyf/csams/TestPreview.kt new file mode 100644 index 0000000..ca25fb6 --- /dev/null +++ b/app/src/androidTest/java/com/gyf/csams/TestPreview.kt @@ -0,0 +1,156 @@ +package com.gyf.csams + +import androidx.compose.foundation.Canvas +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.* +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.rotate +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.drawscope.rotate +import androidx.compose.ui.text.SpanStyle +import androidx.compose.ui.text.buildAnnotatedString +import androidx.compose.ui.text.withStyle +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp + + +@Composable +fun BoxSetSize(degrees:Float=0F,content: @Composable BoxScope.() -> Unit){ + Box(modifier = Modifier + .height(300.dp) + .fillMaxWidth() + .background(Color.Gray) + .rotate(degrees = degrees),contentAlignment = Alignment.Center){ + Canvas(modifier = Modifier.size(200.dp)) { + rotate(45f){ + drawRect(color = Color.Cyan) + } + } + content() + } +} + +@Composable +fun BoxFillSize(degrees:Float=0F, content: @Composable BoxScope.() -> Unit){ + Box(modifier = Modifier + .fillMaxSize() + .background(Color.LightGray) + .rotate(degrees = degrees),contentAlignment = Alignment.Center){ + Canvas(modifier = Modifier.size(100.dp)) { + rotate(80f){ + drawRect(color = Color.Cyan) + } + } + content() + } +} + +@Preview +@Composable +fun TestPreview(){ + Column(modifier = Modifier.fillMaxSize()){ + BoxSetSize { + Text(buildAnnotatedString { + withStyle(style = SpanStyle(fontSize = 30.sp)){ + append("前置子布局固定尺寸") + } + }) + } + + BoxFillSize { + Text(buildAnnotatedString { + withStyle(style = SpanStyle(fontSize = 30.sp)){ + append("后置子布局使用") + } + withStyle(style = SpanStyle(color= Color.Red,fontSize = 30.sp)){ + append("fillMaxSize修饰符") + } + withStyle(style = SpanStyle(fontSize = 30.sp)){ + append("填充父项允许的所有可用空间") + } + }) + } + } +} + +@Preview +@Composable +fun TestPreview2(){ + Column(modifier = Modifier.fillMaxSize()){ + Text(buildAnnotatedString { + withStyle(style = SpanStyle(fontSize = 30.sp)){ + append("如果使用示例1方法是") + } + withStyle(style = SpanStyle(color= Color.Red,fontSize = 30.sp)){ + append("无法实现前置子布局填充父项所有可用空间,后置子布局固定尺寸") + } + withStyle(style = SpanStyle(fontSize = 30.sp)){ + append("因为前置布局已经填充父项允许的所有可用空间,后置子布局没有剩余空间可用") + } + + }) + + BoxFillSize { + Text(buildAnnotatedString { + withStyle(style = SpanStyle(fontSize = 30.sp)){ + append("前置子布局填充父项允许的所有可用空间") + } + }) + } + + BoxSetSize { + Text(buildAnnotatedString { + withStyle(style = SpanStyle(fontSize = 30.sp)){ + append("后置子布局固定尺寸") + } + }) + } + } +} + +@Preview +@Composable +fun TestPreview3(){ + Column(modifier = Modifier + .fillMaxSize()) { + Text(buildAnnotatedString { + withStyle(style = SpanStyle(fontSize = 30.sp)){ + append("折衷方案是通过父项旋转180°实现,子项分别旋转180°复位可") + } + withStyle(style = SpanStyle(color= Color.Red,fontSize = 30.sp)){ + append("实现前置子布局填充父项所有可用空间,后置子布局固定尺寸") + } + withStyle(style = SpanStyle(fontSize = 30.sp)){ + append(",除了旋转,应该有更好的实现方式?") + } + }) + Column(modifier = Modifier.rotate(180F)){ + BoxSetSize(degrees = 180F) { + Text(buildAnnotatedString { + withStyle(style = SpanStyle(fontSize = 30.sp)){ + append("前置子布局固定尺寸,通过旋转和后置子布局对调位置") + } + }) + } + BoxFillSize(degrees = 180F) { + Text(buildAnnotatedString { + + withStyle(style = SpanStyle(fontSize = 30.sp)){ + append("后置子布局使用") + } + withStyle(style = SpanStyle(color= Color.Red,fontSize = 30.sp)){ + append("fillMaxSize修饰符") + } + withStyle(style = SpanStyle(fontSize = 30.sp)){ + append("填充父项允许的所有可用空间,通过旋转和前置子布局对调位置") + } + }) + } + } + } + +} diff --git a/app/src/main/java/com/gyf/csams/ui/Base.kt b/app/src/main/java/com/gyf/csams/ui/Base.kt index 007e902..869cc18 100644 --- a/app/src/main/java/com/gyf/csams/ui/Base.kt +++ b/app/src/main/java/com/gyf/csams/ui/Base.kt @@ -1,13 +1,22 @@ package com.gyf.csams.ui +import androidx.annotation.DrawableRes import androidx.compose.animation.animateColor import androidx.compose.animation.core.* -import androidx.compose.material.MaterialTheme -import androidx.compose.material.Text +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.material.* import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue +import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color +import androidx.compose.ui.res.painterResource import androidx.compose.ui.tooling.preview.Preview +import androidx.navigation.NavController +import androidx.navigation.compose.navigate +import androidx.navigation.compose.rememberNavController +import com.gyf.csams.R /** * 淡入淡出并且颜色变化文本 @@ -33,9 +42,61 @@ fun AnimationText(text:String){ ) } +/** + * 主菜单 + * + */ +enum class MainMenu(@DrawableRes val selectedIcon:Int, + @DrawableRes val unSelectedIcon:Int){ + //主页 + Main(R.drawable.ic_home_fill,R.drawable.ic_home), + //社团列表 + List(R.drawable.ic_all_fill,R.drawable.ic_all), + //个人中心 + Center(R.drawable.ic_account_fill,R.drawable.ic_account) +} + +@Composable +fun MenuIconButton(_menu: MainMenu,menu: MainMenu,modifier: Modifier,onClick: () -> Unit){ + Row(modifier = modifier + ,horizontalArrangement = Arrangement.Center) { + IconButton(onClick = onClick) { + Icon( + painter = painterResource(id = if (_menu == menu) menu.selectedIcon else menu.unSelectedIcon), + contentDescription = null + ) + } + } +} + +@Composable +fun MyBottomAppBar(menu:MainMenu,nav: NavController,modifier: Modifier=Modifier){ + BottomAppBar(backgroundColor = Color.Transparent,modifier=modifier) { + //图标宽度平等分 + + val weight=1/(MainMenu.values().size*1.0f) + + Row(Modifier.fillMaxWidth()) { + MenuIconButton(_menu = menu,menu = MainMenu.Main,Modifier.weight(weight), + onClick = { nav.navigate(MainMenu.Main.name)}) + MenuIconButton(_menu = menu,menu = MainMenu.List,Modifier.weight(weight), + onClick = { nav.navigate(MainMenu.List.name)}) + MenuIconButton(_menu = menu,menu = MainMenu.Center,Modifier.weight(weight), + onClick = { nav.navigate(MainMenu.Center.name)}) + } + } + +} @Preview @Composable fun AnimationTextPreview(){ AnimationText(text = "6666") +} + +@Preview +@Composable +fun MyBottomAppBarPreview(){ + val nav= rememberNavController() + MyBottomAppBar(menu = MainMenu.Main,nav=nav) } \ No newline at end of file diff --git a/app/src/main/java/com/gyf/csams/ui/MainActivity.kt b/app/src/main/java/com/gyf/csams/ui/MainActivity.kt index aed0362..72b8608 100644 --- a/app/src/main/java/com/gyf/csams/ui/MainActivity.kt +++ b/app/src/main/java/com/gyf/csams/ui/MainActivity.kt @@ -3,40 +3,244 @@ package com.gyf.csams.ui import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.material.MaterialTheme -import androidx.compose.material.Surface +import androidx.compose.foundation.Image +import androidx.compose.foundation.background +import androidx.compose.foundation.border +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.* import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.rotate +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import androidx.constraintlayout.compose.ConstraintLayout +import androidx.navigation.compose.NavHost +import androidx.navigation.compose.composable +import androidx.navigation.compose.rememberNavController +import com.gyf.csams.R import com.gyf.csams.ui.theme.CSAMSTheme +/** + * 主界面 + * + */ class MainActivity: ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { CSAMSTheme { - // A surface container using the 'background' color from the theme - Surface(color = MaterialTheme.colors.background) { - Row(horizontalArrangement = Arrangement.Center, - verticalAlignment = Alignment.CenterVertically, - modifier = Modifier.fillMaxSize()){ - AnimationText(text = "主界面设计中。。。。") + Body() + } + } + } +} + +@Composable +fun Body(){ + // A surface container using the 'background' color from the theme + Surface(color = MaterialTheme.colors.background) { + val navController = rememberNavController() + val scaffoldState = rememberScaffoldState() + + Scaffold(scaffoldState=scaffoldState) { + NavHost(navController, startDestination = MainMenu.Main.name) { + composable(MainMenu.Main.name){ + Box(modifier = Modifier.fillMaxSize()) { + Column { + Notification() + MessageBoard() + Spacer(modifier = Modifier.height(10.dp)) + ClubActivitiesTitle() + Spacer(modifier = Modifier.height(10.dp)) + Column(Modifier.rotate(180F)) { + MyBottomAppBar(MainMenu.Main, navController,Modifier.rotate(180F)) + ClubActivitiesImage() + } + } + } + } + composable(MainMenu.List.name){ + Box(modifier = Modifier.fillMaxSize()) { + Column(Modifier.rotate(180F)){ + MyBottomAppBar(MainMenu.List, navController,Modifier.rotate(180F)) + Row(modifier = Modifier + .fillMaxSize() + .rotate(180F), + horizontalArrangement = Arrangement.Center, + verticalAlignment = Alignment.CenterVertically) { + AnimationText(text = "社团列表") + } + } + } + } + composable(MainMenu.Center.name){ + Box(modifier = Modifier.fillMaxSize()) { + Column(Modifier.rotate(180F)){ + MyBottomAppBar(MainMenu.Center, navController,Modifier.rotate(180F)) + Row(modifier = Modifier + .fillMaxSize() + .rotate(180F), + horizontalArrangement = Arrangement.Center, + verticalAlignment = Alignment.CenterVertically) { + AnimationText(text = "个人中心") + } + } } } } } + } } -@Preview(showBackground = true) +/** + * 通知 + * + */ +@Composable +fun Notification(){ + Row(horizontalArrangement = Arrangement.End, + modifier = Modifier + .fillMaxWidth() + .padding(10.dp)) { + Icon(painter = painterResource(id = R.drawable.ic_notification), + contentDescription = null, + modifier = Modifier.size(50.dp)) + } +} + +/** + * 圆角矩形边框 + * + */ +@Composable +fun MyBorder(content: @Composable BoxScope.() -> Unit){ + Box(modifier = Modifier.padding(horizontal = 15.dp)) { + Box( + modifier = Modifier + .border(width = 1.dp, color = Color.Black, shape = RoundedCornerShape(size = 20.dp)), + ){ + content() + } + } +} + +/** + * 留言板 + * + */ +@Composable +fun MessageBoard() { + MyBorder { + Row(modifier = Modifier.rotate(180F), + verticalAlignment = Alignment.CenterVertically) { + + Icon( + painter = painterResource(id = R.drawable.ic_comments), + contentDescription = null, + modifier = Modifier + .size(50.dp) + .rotate(180F) + ) + Row( + horizontalArrangement = Arrangement.Center, + modifier = Modifier + .fillMaxWidth() + .rotate(180F) + ) { + Text(text = "跑马灯留言") + } + + } + } +} + +/** + * 活动标题 + * + */ +@Composable +fun ClubActivitiesTitle(){ + MyBorder { + Row( + modifier = Modifier + .fillMaxWidth() + .height(50.dp), + horizontalArrangement = Arrangement.Center, + verticalAlignment = Alignment.CenterVertically + ) { + Text(text = "超级课程表X滴滴出行-了不起的社团", + style = MaterialTheme.typography.h6, + overflow = TextOverflow.Ellipsis, + maxLines = 1) + } + } +} + +/** + * 活动海报 + * + */ +@Composable +fun ClubActivitiesImage(){ + Column(modifier=Modifier.fillMaxSize()) { + Card(modifier = Modifier + .weight(0.4f) + .fillMaxWidth()) { + Image(painter = painterResource(id = R.drawable.hot_activity_desc_background), + contentDescription = null) + Box(modifier = Modifier + .padding(horizontal = 85.dp, vertical = 30.dp) + .rotate(180F)){ + Text(text = "文字对任何界面都属于核心内容,而利用 Jetpack Compose 可以更轻松地显示或写入文字。Compose 可以充分利用其构建块的组合,这意味着您无需覆盖各种属性和方法,也无需扩展大型类,即可拥有特定的可组合项设计以及按您期望的方式运行的逻辑。" + .repeat(10),overflow = TextOverflow.Ellipsis) + } + + } + Card(modifier = Modifier + .weight(0.6f) + .fillMaxWidth()) { + Image(painter = painterResource(id = R.drawable.hot_activity_background), + contentDescription = null) + Image(painter = painterResource(id = R.drawable.ic_launcher_foreground), + contentDescription = null) + + } + } +} + +//@Preview(showBackground = true) @Composable fun DefaultPreview() { CSAMSTheme { - // A surface container using the 'background' color from the theme - AnimationText(text = "sdfsdf") + Box(modifier = Modifier.fillMaxSize()) { + Column { + ClubActivitiesImage() + } + } + } +} + +@Preview +@Composable +fun ConstraintLayoutContent() { + Box(modifier = Modifier.background(Color.Cyan)) { + ConstraintLayout { + // Create references for the composables to constrain + val (button, text,text2,box) = createRefs() + + Box(Modifier.fillMaxSize()) + + Box(Modifier.size(50.dp).background(Color.Red).constrainAs(box){ + bottom.linkTo(parent.bottom) + + end.linkTo(parent.end) + }) + } } } \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_account.xml b/app/src/main/res/drawable/ic_account.xml new file mode 100644 index 0000000..c209003 --- /dev/null +++ b/app/src/main/res/drawable/ic_account.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_account_fill.xml b/app/src/main/res/drawable/ic_account_fill.xml new file mode 100644 index 0000000..8d3b735 --- /dev/null +++ b/app/src/main/res/drawable/ic_account_fill.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_all.xml b/app/src/main/res/drawable/ic_all.xml new file mode 100644 index 0000000..83b27b0 --- /dev/null +++ b/app/src/main/res/drawable/ic_all.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_all_fill.xml b/app/src/main/res/drawable/ic_all_fill.xml new file mode 100644 index 0000000..1c38c96 --- /dev/null +++ b/app/src/main/res/drawable/ic_all_fill.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_comments.xml b/app/src/main/res/drawable/ic_comments.xml new file mode 100644 index 0000000..d5ea5e2 --- /dev/null +++ b/app/src/main/res/drawable/ic_comments.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home.xml b/app/src/main/res/drawable/ic_home.xml new file mode 100644 index 0000000..df3983e --- /dev/null +++ b/app/src/main/res/drawable/ic_home.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_home_fill.xml b/app/src/main/res/drawable/ic_home_fill.xml new file mode 100644 index 0000000..6b19821 --- /dev/null +++ b/app/src/main/res/drawable/ic_home_fill.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_notification.xml b/app/src/main/res/drawable/ic_notification.xml new file mode 100644 index 0000000..15c4247 --- /dev/null +++ b/app/src/main/res/drawable/ic_notification.xml @@ -0,0 +1,9 @@ + + +