|
|
|
@ -3,13 +3,16 @@ package com.gyf.csams.ui |
|
|
|
|
import android.os.Bundle |
|
|
|
|
import androidx.activity.ComponentActivity |
|
|
|
|
import androidx.activity.compose.setContent |
|
|
|
|
import androidx.compose.animation.core.* |
|
|
|
|
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.runtime.State |
|
|
|
|
import androidx.compose.runtime.getValue |
|
|
|
|
import androidx.compose.runtime.livedata.observeAsState |
|
|
|
|
import androidx.compose.ui.Alignment |
|
|
|
|
import androidx.compose.ui.Modifier |
|
|
|
|
import androidx.compose.ui.draw.rotate |
|
|
|
@ -18,38 +21,40 @@ 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.lifecycle.viewmodel.compose.viewModel |
|
|
|
|
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.model.MainViewModel |
|
|
|
|
import com.gyf.csams.ui.theme.CSAMSTheme |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* 主界面 |
|
|
|
|
* |
|
|
|
|
*/ |
|
|
|
|
class MainActivity: ComponentActivity() { |
|
|
|
|
class MainActivity : ComponentActivity() { |
|
|
|
|
override fun onCreate(savedInstanceState: Bundle?) { |
|
|
|
|
super.onCreate(savedInstanceState) |
|
|
|
|
setContent { |
|
|
|
|
CSAMSTheme { |
|
|
|
|
Body() |
|
|
|
|
Body() |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Composable |
|
|
|
|
fun Body(){ |
|
|
|
|
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) { |
|
|
|
|
Scaffold(scaffoldState = scaffoldState) { |
|
|
|
|
NavHost(navController, startDestination = MainMenu.Main.name) { |
|
|
|
|
composable(MainMenu.Main.name){ |
|
|
|
|
composable(MainMenu.Main.name) { |
|
|
|
|
Box(modifier = Modifier.fillMaxSize()) { |
|
|
|
|
Column { |
|
|
|
|
Notification() |
|
|
|
@ -58,35 +63,39 @@ fun Body(){ |
|
|
|
|
ClubActivitiesTitle() |
|
|
|
|
Spacer(modifier = Modifier.height(10.dp)) |
|
|
|
|
Column(Modifier.rotate(180F)) { |
|
|
|
|
MyBottomAppBar(MainMenu.Main, navController,Modifier.rotate(180F)) |
|
|
|
|
MyBottomAppBar(MainMenu.Main, navController, Modifier.rotate(180F)) |
|
|
|
|
ClubActivitiesImage() |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
composable(MainMenu.List.name){ |
|
|
|
|
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), |
|
|
|
|
Column(Modifier.rotate(180F)) { |
|
|
|
|
MyBottomAppBar(MainMenu.List, navController, Modifier.rotate(180F)) |
|
|
|
|
Row( |
|
|
|
|
modifier = Modifier |
|
|
|
|
.fillMaxSize() |
|
|
|
|
.rotate(180F), |
|
|
|
|
horizontalArrangement = Arrangement.Center, |
|
|
|
|
verticalAlignment = Alignment.CenterVertically) { |
|
|
|
|
verticalAlignment = Alignment.CenterVertically |
|
|
|
|
) { |
|
|
|
|
AnimationText(text = "社团列表") |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
composable(MainMenu.Center.name){ |
|
|
|
|
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), |
|
|
|
|
Column(Modifier.rotate(180F)) { |
|
|
|
|
MyBottomAppBar(MainMenu.Center, navController, Modifier.rotate(180F)) |
|
|
|
|
Row( |
|
|
|
|
modifier = Modifier |
|
|
|
|
.fillMaxSize() |
|
|
|
|
.rotate(180F), |
|
|
|
|
horizontalArrangement = Arrangement.Center, |
|
|
|
|
verticalAlignment = Alignment.CenterVertically) { |
|
|
|
|
verticalAlignment = Alignment.CenterVertically |
|
|
|
|
) { |
|
|
|
|
AnimationText(text = "个人中心") |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -103,14 +112,18 @@ fun Body(){ |
|
|
|
|
* |
|
|
|
|
*/ |
|
|
|
|
@Composable |
|
|
|
|
fun Notification(){ |
|
|
|
|
Row(horizontalArrangement = Arrangement.End, |
|
|
|
|
fun Notification() { |
|
|
|
|
Row( |
|
|
|
|
horizontalArrangement = Arrangement.End, |
|
|
|
|
modifier = Modifier |
|
|
|
|
.fillMaxWidth() |
|
|
|
|
.padding(10.dp)) { |
|
|
|
|
Icon(painter = painterResource(id = R.drawable.ic_notification), |
|
|
|
|
.padding(10.dp) |
|
|
|
|
) { |
|
|
|
|
Icon( |
|
|
|
|
painter = painterResource(id = R.drawable.ic_notification), |
|
|
|
|
contentDescription = null, |
|
|
|
|
modifier = Modifier.size(50.dp)) |
|
|
|
|
modifier = Modifier.size(50.dp) |
|
|
|
|
) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -119,12 +132,16 @@ fun Notification(){ |
|
|
|
|
* |
|
|
|
|
*/ |
|
|
|
|
@Composable |
|
|
|
|
fun MyBorder(content: @Composable BoxScope.() -> Unit){ |
|
|
|
|
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)), |
|
|
|
|
){ |
|
|
|
|
.border( |
|
|
|
|
width = 1.dp, |
|
|
|
|
color = Color.Black, |
|
|
|
|
shape = RoundedCornerShape(size = 20.dp) |
|
|
|
|
), |
|
|
|
|
) { |
|
|
|
|
content() |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -135,25 +152,27 @@ fun MyBorder(content: @Composable BoxScope.() -> Unit){ |
|
|
|
|
* |
|
|
|
|
*/ |
|
|
|
|
@Composable |
|
|
|
|
fun MessageBoard() { |
|
|
|
|
fun MessageBoard(model: MainViewModel= viewModel()) { |
|
|
|
|
MyBorder { |
|
|
|
|
Row(modifier = Modifier.rotate(180F), |
|
|
|
|
verticalAlignment = Alignment.CenterVertically) { |
|
|
|
|
Row( |
|
|
|
|
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 = "跑马灯留言") |
|
|
|
|
Marquee(model = model) { |
|
|
|
|
model, value -> TestA(model = model, |
|
|
|
|
offset = value) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} |
|
|
|
@ -165,7 +184,7 @@ fun MessageBoard() { |
|
|
|
|
* |
|
|
|
|
*/ |
|
|
|
|
@Composable |
|
|
|
|
fun ClubActivitiesTitle(){ |
|
|
|
|
fun ClubActivitiesTitle() { |
|
|
|
|
MyBorder { |
|
|
|
|
Row( |
|
|
|
|
modifier = Modifier |
|
|
|
@ -174,10 +193,12 @@ fun ClubActivitiesTitle(){ |
|
|
|
|
horizontalArrangement = Arrangement.Center, |
|
|
|
|
verticalAlignment = Alignment.CenterVertically |
|
|
|
|
) { |
|
|
|
|
Text(text = "超级课程表X滴滴出行-了不起的社团", |
|
|
|
|
Text( |
|
|
|
|
text = "超级课程表X滴滴出行-了不起的社团", |
|
|
|
|
style = MaterialTheme.typography.h6, |
|
|
|
|
overflow = TextOverflow.Ellipsis, |
|
|
|
|
maxLines = 1) |
|
|
|
|
maxLines = 1 |
|
|
|
|
) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -187,60 +208,122 @@ fun ClubActivitiesTitle(){ |
|
|
|
|
* |
|
|
|
|
*/ |
|
|
|
|
@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 |
|
|
|
|
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) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
.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) |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
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) |
|
|
|
|
|
|
|
|
|
@Preview(showBackground = true) |
|
|
|
|
@Composable |
|
|
|
|
fun DefaultPreview() { |
|
|
|
|
val model = MainViewModel() |
|
|
|
|
CSAMSTheme { |
|
|
|
|
Box(modifier = Modifier.fillMaxSize()) { |
|
|
|
|
Column { |
|
|
|
|
ClubActivitiesImage() |
|
|
|
|
// Marquee(model = model) { |
|
|
|
|
// model, value -> TestA(model = model, |
|
|
|
|
// offset = value) |
|
|
|
|
// } |
|
|
|
|
MessageBoard(model = model) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Preview |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Composable |
|
|
|
|
fun ConstraintLayoutContent() { |
|
|
|
|
Box(modifier = Modifier.background(Color.Cyan)) { |
|
|
|
|
ConstraintLayout { |
|
|
|
|
// Create references for the composables to constrain |
|
|
|
|
val (button, text,text2,box) = createRefs() |
|
|
|
|
fun TestA(model: MainViewModel= viewModel(),offset:State<Float>){ |
|
|
|
|
val poetryIndex: Int by model.poetryIndex.observeAsState(0) |
|
|
|
|
|
|
|
|
|
Box(Modifier.fillMaxSize()) |
|
|
|
|
// Text(text = "$poetryIndex") |
|
|
|
|
// Text(text = "offset.value=${offset.value}") |
|
|
|
|
Text( |
|
|
|
|
text = model.poetry[poetryIndex % model.poetry.size], |
|
|
|
|
modifier = Modifier.offset(x = offset.value.dp), |
|
|
|
|
maxLines = 1, |
|
|
|
|
overflow = TextOverflow.Ellipsis |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
Box(Modifier.size(50.dp).background(Color.Red).constrainAs(box){ |
|
|
|
|
bottom.linkTo(parent.bottom) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* 轮播 |
|
|
|
|
* |
|
|
|
|
*/ |
|
|
|
|
@Composable |
|
|
|
|
fun Carousel(){ |
|
|
|
|
|
|
|
|
|
end.linkTo(parent.end) |
|
|
|
|
}) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* 跑马灯 |
|
|
|
|
* |
|
|
|
|
* @param model |
|
|
|
|
* @param content |
|
|
|
|
*/ |
|
|
|
|
@Composable |
|
|
|
|
fun Marquee(model: MainViewModel= viewModel(),content: @Composable BoxScope.(model:MainViewModel, |
|
|
|
|
value:State<Float>) -> Unit) { |
|
|
|
|
|
|
|
|
|
val delayMillis=2000 |
|
|
|
|
Column { |
|
|
|
|
BoxWithConstraints { |
|
|
|
|
val transition = rememberInfiniteTransition() |
|
|
|
|
val maxWidth = maxWidth + 30.dp |
|
|
|
|
val offset = transition.animateFloat( |
|
|
|
|
initialValue = 0F, |
|
|
|
|
targetValue = maxWidth.value, |
|
|
|
|
animationSpec = infiniteRepeatable( |
|
|
|
|
animation = tween(durationMillis = 3000,delayMillis = delayMillis), |
|
|
|
|
repeatMode = RepeatMode.Restart |
|
|
|
|
) |
|
|
|
|
) |
|
|
|
|
Box(modifier = Modifier.fillMaxWidth()) { |
|
|
|
|
content(model=model,value=offset) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (offset.value.toInt() == maxWidth.value.toInt()) { |
|
|
|
|
model.addAsync(delayMillis = delayMillis) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |