From 4ee124d927deb83badb8fadafc96892f9be51e70 Mon Sep 17 00:00:00 2001 From: pan <1029559041@qq.com> Date: Mon, 17 May 2021 14:27:30 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=B4=BB=E5=8A=A8=E8=AF=A6?= =?UTF-8?q?=E6=83=85=E7=95=8C=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/gyf/csams/ExampleInstrumentedTest.kt | 2 - .../java/com/gyf/csams/MainActivityTest.kt | 9 + app/src/main/AndroidManifest.xml | 5 + app/src/main/java/com/gyf/csams/Api.kt | 13 +- .../main/java/com/gyf/csams/InitActivity.kt | 31 +- .../activity/model/ActivityDetailViewModel.kt | 290 ++++++++++ .../activity/ui/ActivityDetailActivity.kt | 491 +++++++++++++++++ .../association/model/AssociationViewModel.kt | 34 +- .../csams/association/model/ExamViewModel.kt | 7 +- .../model/RegAssociationViewModel.kt | 3 +- .../association/model/RenameViewModel.kt | 3 +- .../association/ui/AssociationActivity.kt | 446 +++++++-------- .../gyf/csams/association/ui/ExamActivity.kt | 471 ++++++++-------- .../csams/association/ui/ReNameActivity.kt | 112 ++-- .../association/ui/RegAssociationActivity.kt | 220 ++++---- .../com/gyf/csams/main/model/MainViewModel.kt | 7 +- .../com/gyf/csams/main/ui/MainActivity.kt | 520 +++++++++--------- .../main/java/com/gyf/csams/uikit/BaseView.kt | 258 ++++++--- .../java/com/gyf/csams/util/RandomUtil.kt | 55 ++ app/src/main/res/drawable/ic_upload.xml | 9 + .../java/com/gyf/csams/ExampleUnitTest.kt | 15 +- 21 files changed, 1986 insertions(+), 1015 deletions(-) create mode 100644 app/src/androidTest/java/com/gyf/csams/MainActivityTest.kt create mode 100644 app/src/main/java/com/gyf/csams/activity/model/ActivityDetailViewModel.kt create mode 100644 app/src/main/java/com/gyf/csams/activity/ui/ActivityDetailActivity.kt create mode 100644 app/src/main/java/com/gyf/csams/util/RandomUtil.kt create mode 100644 app/src/main/res/drawable/ic_upload.xml diff --git a/app/src/androidTest/java/com/gyf/csams/ExampleInstrumentedTest.kt b/app/src/androidTest/java/com/gyf/csams/ExampleInstrumentedTest.kt index a2231e6..6833343 100644 --- a/app/src/androidTest/java/com/gyf/csams/ExampleInstrumentedTest.kt +++ b/app/src/androidTest/java/com/gyf/csams/ExampleInstrumentedTest.kt @@ -18,7 +18,5 @@ class ExampleInstrumentedTest { // Context of the app under test. val appContext = InstrumentationRegistry.getInstrumentation().targetContext assertEquals("com.gyf.csams", appContext.packageName) - - } } \ No newline at end of file diff --git a/app/src/androidTest/java/com/gyf/csams/MainActivityTest.kt b/app/src/androidTest/java/com/gyf/csams/MainActivityTest.kt new file mode 100644 index 0000000..98e846f --- /dev/null +++ b/app/src/androidTest/java/com/gyf/csams/MainActivityTest.kt @@ -0,0 +1,9 @@ +package com.gyf.csams + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class MainActivityTest { + +} \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index b7cb9b5..a16986a 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -62,6 +62,11 @@ + + + + \ No newline at end of file diff --git a/app/src/main/java/com/gyf/csams/Api.kt b/app/src/main/java/com/gyf/csams/Api.kt index 3c62a5f..b696784 100644 --- a/app/src/main/java/com/gyf/csams/Api.kt +++ b/app/src/main/java/com/gyf/csams/Api.kt @@ -5,6 +5,11 @@ interface UrlPath{ fun build():String } +/** + * 帐号接口 + * + * @property path + */ enum class AccountApi(val path: String):UrlPath{ register("/register"), checkId("/register/checkId"), @@ -17,7 +22,10 @@ enum class AccountApi(val path: String):UrlPath{ } } - +/** + * 构建服务端请求接口地址 + * + */ class Api { companion object{ fun buildUrl(urlPath: UrlPath):String{ @@ -26,3 +34,6 @@ class Api { } } +const val NOT_IMPL_TIP="功能尚未实现!" + + diff --git a/app/src/main/java/com/gyf/csams/InitActivity.kt b/app/src/main/java/com/gyf/csams/InitActivity.kt index 11a85bb..f5948d4 100644 --- a/app/src/main/java/com/gyf/csams/InitActivity.kt +++ b/app/src/main/java/com/gyf/csams/InitActivity.kt @@ -37,20 +37,21 @@ class InitActivity : ComponentActivity() { } } } -} -@Composable -private fun Init(initViewModel:InitViewModel= viewModel()){ - Logger.i("初始化。。。。") - val context= LocalContext.current - //后台检查token - initViewModel.hasOnlyUserToken(context) - //监听token校验状态 - val isValid: Boolean? by initViewModel.token.observeAsState(null) - - when (isValid) { - false -> context.startActivity(Intent(context, AccountActivity::class.java)) - true -> context.startActivity(Intent(context, MainActivity::class.java)) - } -} \ No newline at end of file + @Composable + private fun Init(initViewModel:InitViewModel= viewModel()){ + Logger.i("初始化。。。。") + val context= LocalContext.current + //后台检查token + initViewModel.hasOnlyUserToken(context) + //监听token校验状态 + val isValid: Boolean? by initViewModel.token.observeAsState(null) + + when (isValid) { + false -> context.startActivity(Intent(context, AccountActivity::class.java)) + true -> context.startActivity(Intent(context, MainActivity::class.java)) + } + + } +} diff --git a/app/src/main/java/com/gyf/csams/activity/model/ActivityDetailViewModel.kt b/app/src/main/java/com/gyf/csams/activity/model/ActivityDetailViewModel.kt new file mode 100644 index 0000000..dac851b --- /dev/null +++ b/app/src/main/java/com/gyf/csams/activity/model/ActivityDetailViewModel.kt @@ -0,0 +1,290 @@ +package com.gyf.csams.activity.model + +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.gyf.csams.NOT_IMPL_TIP +import com.gyf.csams.uikit.ActivityDetailMenu +import com.gyf.csams.uikit.ScrollList +import com.gyf.csams.uikit.StringForm +import com.gyf.csams.uikit.TopMenuInterface +import com.gyf.csams.util.randomChinese +import com.gyf.csams.util.randomDateTime +import com.gyf.csams.util.randomNum +import com.orhanobut.logger.Logger +import kotlinx.coroutines.launch +import java.util.* + +/** + * 活动详情菜单通用状态 + * + */ +class ActivityDetailViewModel:ViewModel(), TopMenuInterface { + override val _currentMenu: MutableLiveData = MutableLiveData() + override val currentMenu: LiveData = _currentMenu +} + +/** + * TODO + * + * @property associationName 社团名字 + * @property activityName 活动名 + * @property activityTime 活动时间 + * @property activityLocation 活动地点 + * @property activityDesc 活动介绍 + */ +data class ActivityDetailVo(val associationName:String,val activityName:String, + val activityTime:Date,val activityLocation:String, + val activityDesc:String) + + + +/** + * 活动信息 + * + */ +class ActivityInfoViewModel:ViewModel(){ + private val _activityDetailVo=MutableLiveData() + val activityDetailVo:LiveData = _activityDetailVo + + val like = "点赞" + val collect="收藏" + + init { + loadInfo() + } + + /** + * TODO 点赞 + * + * @param callback + */ + fun like(callback:(message:String)->Unit){ + callback(NOT_IMPL_TIP) + } + + /** + * TODO 收藏 + * + * @param callback + */ + fun collect(callback:(message:String)->Unit){ + callback(NOT_IMPL_TIP) + } + + private fun loadInfo(){ + viewModelScope.launch { + _activityDetailVo.value = ActivityDetailVo( + activityName = randomChinese(4), + associationName = randomChinese(4), + activityTime = randomDateTime(), + activityLocation = randomChinese(3), + activityDesc = randomChinese(500) + ) + } + + } + +} + +/** + * 图片 + * @property name 文件名 + * @property size 文件大小 + * @property url 文件路径 + * @property md5 文件hash + * @property createTime 文件创建时间 + * @property studentId 文件上传人 + */ +data class ActivityPhotoVo(val name:String, val size:Long, val url:String, val md5:String, val createTime: Date, val studentId:String) + +/** + * 活动相册数据状态管理 + * + */ +class ActivityPhotoViewModel:ScrollList(){ + override val initSize: Int = 10 + + init { + load() + } + + fun upload(callback: (message: String) -> Unit){ + callback(NOT_IMPL_TIP) + } + + /** + * TODO 加载相册 + * + */ + override fun load() { + viewModelScope.launch { + _data.value?.apply { + repeat(initSize){ + add(ActivityPhotoVo(name=randomChinese(3), + size= randomNum(3).toLong(), + url="", + md5 = "", + createTime = randomDateTime(), + studentId = "")) + } + } + } + } + + + /** + * TODO 加载更多相册 + * + * @param callback + */ + override fun loadMore(callback: (message: String) -> Unit) { + Logger.i("加载更多") + viewModelScope.launch { + _data.value?.apply { + val list= mutableListOf() + list.addAll(this) + repeat(initSize){ + add(ActivityPhotoVo(name=randomChinese(3), + size= randomNum(3).toLong(), + url="", + md5 = "", + createTime = randomDateTime(), + studentId = "")) + } + _data.postValue(list) + callback("成功加载更多相册") + } + } + } +} + +data class ActivityMemberVo(val studentId: String,val name:String) + +data class ActivityMembersVo(val organizer:ActivityMemberVo, val participant:MutableList?) + +class ActivityMemberViewModel:ScrollList(){ + override val initSize: Int = 10 + + private val _allMember=MutableLiveData() + val allMember:LiveData = _allMember + + init { + load() + } + + /** + * TODO 加载活动成员 + * + */ + override fun load() { + viewModelScope.launch { + _data.value?.apply { + repeat(initSize){ + add(ActivityMemberVo(studentId = randomNum(),name = randomChinese(3))) + } + _allMember.value= ActivityMembersVo(organizer = ActivityMemberVo(studentId = randomNum(),name = randomChinese(3)),participant = _data.value) + } + } + } + + /** + * TODO 加载更多活动成员 + * + * @param callback + */ + override fun loadMore(callback: (message: String) -> Unit) { + viewModelScope.launch { + _data.value?.apply { + val list= mutableListOf() + list.addAll(this) + repeat(initSize){ + add(ActivityMemberVo(studentId = randomNum(),name = randomChinese(3))) + } + _allMember.value?.apply { + _data.postValue(list) + _allMember.postValue(ActivityMembersVo(organizer=organizer,participant=list)) + callback("成功加载更多活动参与者") + } + } + } + } +} + +data class BBSVo(val studentId:String,val name:String,val createTime:Date,val content:String) + +/** + * 交流区数据状态管理 + * + */ +class BBSViewModel:ScrollList(){ + override val initSize: Int = 10 + + val title="发送评论" + + val newContent = StringForm(formDesc = "评论内容",textLength = 80) + + private val _openDialog=MutableLiveData() + val openDialog:LiveData = _openDialog + + init { + load() + } + + /** + * 打开评论弹窗 + * + */ + fun openDialog(){ + _openDialog.value=true + } + + fun closeDialog(){ + _openDialog.value=false + } + + /** + * TODO 发送评论 + * + * @param callback + */ + fun send(callback: (message: String) -> Unit){ + callback(NOT_IMPL_TIP) + } + + /** + * TODO 加载评论 + * + */ + override fun load() { + viewModelScope.launch { + _data.value?.apply { + repeat(initSize){ + add(BBSVo(studentId = randomNum(),createTime = randomDateTime(),content = randomChinese(50),name = randomChinese(3))) + } + } + } + } + + /** + * TODO 加载更多评论 + * + * @param callback + */ + override fun loadMore(callback: (message: String) -> Unit) { + viewModelScope.launch { + _data.value?.apply { + repeat(initSize){ + val list= mutableListOf() + list.addAll(this) + repeat(initSize){ + add(BBSVo(studentId = randomNum(),name = randomChinese(3),createTime = randomDateTime(),content = randomChinese(50))) + } + _data.postValue(list) + callback("成功加载更多评论") + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/gyf/csams/activity/ui/ActivityDetailActivity.kt b/app/src/main/java/com/gyf/csams/activity/ui/ActivityDetailActivity.kt new file mode 100644 index 0000000..86a0687 --- /dev/null +++ b/app/src/main/java/com/gyf/csams/activity/ui/ActivityDetailActivity.kt @@ -0,0 +1,491 @@ +package com.gyf.csams.activity.ui + +import android.os.Bundle +import androidx.activity.ComponentActivity +import androidx.activity.compose.setContent +import androidx.compose.foundation.Canvas +import androidx.compose.foundation.Image +import androidx.compose.foundation.border +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.rememberLazyListState +import androidx.compose.material.* +import androidx.compose.runtime.Composable +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.res.painterResource +import androidx.compose.ui.unit.dp +import androidx.lifecycle.viewmodel.compose.viewModel +import androidx.navigation.compose.NavHost +import androidx.navigation.compose.composable +import com.gyf.csams.R +import com.gyf.csams.activity.model.* +import com.gyf.csams.uikit.* +import com.gyf.csams.util.format + +/** + * 活动详情 + * + */ +class ActivityDetailActivity : ComponentActivity() { + + + @ExperimentalMaterialApi + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + + setContent { + Body { nav, scaffoldState -> + val model: ActivityDetailViewModel = viewModel() + val currentMenuName by model.currentMenu.observeAsState(ActivityDetailMenu.startMenu) + Column { + TextTopAppBar( + nav = nav, + currentMenuName = currentMenuName.menuName, + menuNames = ActivityDetailMenu.values() + ) + NavHost( + navController = nav, + startDestination = ActivityDetailMenu.startMenu.name + ) { + composable(ActivityDetailMenu.Info.name) { + Info() + ShowSnackbar(scaffoldState = scaffoldState) + model.clickMenu(ActivityDetailMenu.Info) + } + composable(ActivityDetailMenu.Photo.name) { + Photo() + ShowSnackbar(scaffoldState = scaffoldState) + model.clickMenu(ActivityDetailMenu.Photo) + } + composable(ActivityDetailMenu.Member.name) { + Member() + ShowSnackbar(scaffoldState = scaffoldState) + model.clickMenu(ActivityDetailMenu.Member) + } + composable(ActivityDetailMenu.BBS.name) { + BBS() + ShowSnackbar(scaffoldState = scaffoldState) + model.clickMenu(ActivityDetailMenu.BBS) + } + } + } + } + } + } + + /** + * 底部按钮 + * + * @param modifier + */ + @Composable + private fun BottomButton( + modifier: Modifier = Modifier, + model: ActivityInfoViewModel = viewModel(), + scaffoldModel: ScaffoldModel = viewModel() + ) { + Row(modifier = modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceEvenly) { + OutlinedButton(onClick = { model.like { scaffoldModel.update(message = it) } }) { + Text(text = model.like) + } + OutlinedButton(onClick = { model.collect { scaffoldModel.update(message = it) } }) { + Text(text = model.collect) + } + } + } + + /** + * 活动信息 + * + */ + @Composable + private fun Info() { + MainFrame(background = { Background(image = BackgroundImage.ActivityInfo, alpha = 0.7F) }) { + RectList(modifier = Modifier.weight(0.4F)) + ActivityDesc(modifier = Modifier.weight(0.4F)) + Spacer(modifier = Modifier.weight(0.05F)) + BottomButton() + Spacer(modifier = Modifier.weight(0.05F)) + } + } + + /** + * 活动基础信息 + * + */ + @Composable + private fun RectList( + modifier: Modifier = Modifier, + model: ActivityInfoViewModel = viewModel() + ) { + val activityDetailVo by model.activityDetailVo.observeAsState() + activityDetailVo?.let { + Card(modifier = modifier, backgroundColor = MaterialTheme.colors.background) { + Column( + modifier = Modifier.fillMaxSize(), + verticalArrangement = Arrangement.SpaceAround + ) { + RectListItem(text = it.associationName) + RectListItem(text = it.activityName) + RectListItem(text = it.activityTime.format()) + RectListItem(text = it.activityLocation) + } + } + + } + + } + + /** + * 列表项 + * + * @param text + */ + @Composable + private fun RectListItem(text: String) { + Row(modifier = Modifier.fillMaxWidth()) { + val color = MaterialTheme.colors.secondaryVariant + val canvasSize = 30.dp + Box(modifier = Modifier.weight(0.5F), contentAlignment = Alignment.Center) { + Canvas(modifier = Modifier.size(canvasSize)) { + drawCircle(color = color) + } + } + Text(text = text, style = MaterialTheme.typography.h5, modifier = Modifier.weight(0.5F)) + } + } + + /** + * 活动介绍 + * + * @param modifier + * @param model + */ + @Composable + private fun ActivityDesc( + modifier: Modifier = Modifier, + model: ActivityInfoViewModel = viewModel() + ) { + Column(modifier = modifier) { + val activityDetailVo by model.activityDetailVo.observeAsState() + activityDetailVo?.let { + DescCard(modifier = Modifier.weight(0.5F), content = it.activityDesc) + } + } + } + + /** + * 相册 + * + */ + @Composable + private fun Photo( + model: ActivityPhotoViewModel = viewModel(), + scaffoldModel: ScaffoldModel = viewModel() + ) { + MainFrame(background = { + Background( + image = BackgroundImage.ActivityPhoto, + alpha = 0.7F + ) + }) { + Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.End) { + IconButton(onClick = { model.upload { scaffoldModel.update(message = it) } }) { + Icon( + painter = painterResource(id = R.drawable.ic_upload), + contentDescription = null + ) + } + } + + Spacer(modifier = Modifier.height(10.dp)) + + Box( + modifier = Modifier + .fillMaxSize() + .padding(10.dp) + .border( + width = 1.dp, + color = MaterialTheme.colors.background + ) + ) { + val listState = rememberLazyListState() + val photos by model.data.observeAsState() + photos?.let { + LazyColumn(state = listState) { + it.chunked(2).forEach { + item { + Spacer(modifier = Modifier.height(20.dp)) + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.SpaceEvenly + ) { + Spacer(modifier = Modifier.weight(0.05F)) + PhotoItem(vo = it[0], modifier = Modifier.weight(0.4F)) + Spacer(modifier = Modifier.weight(0.1F)) + if (it.size == 2) { + PhotoItem(vo = it[1], modifier = Modifier.weight(0.4F)) + } else { + Spacer(modifier = Modifier.weight(0.4F)) + } + Spacer(modifier = Modifier.weight(0.05F)) + } + Spacer(modifier = Modifier.height(20.dp)) + } + } + } +// Logger.i("totalItemsCount=${listState.layoutInfo.totalItemsCount},firstVisibleItemIndex=${listState.firstVisibleItemIndex}") + if (listState.layoutInfo.totalItemsCount - listState.firstVisibleItemIndex == model.initSize / 2 - 1) { + model.loadMore { scaffoldModel.update(message = it) } + } + } + } + } + } + + @Composable + private fun PhotoItem(modifier: Modifier = Modifier, vo: ActivityPhotoVo) { + Box( + modifier = modifier.border(width = 1.dp, color = MaterialTheme.colors.background), + contentAlignment = Alignment.Center + ) { + Image( + painter = painterResource(id = R.drawable.ic_launcher_foreground), + contentDescription = null, + ) + } + } + + /** + * 活动成员 + * + */ + @Composable + private fun Member( + model: ActivityMemberViewModel = viewModel(), + scaffoldModel: ScaffoldModel = viewModel() + ) { + MainFrame(background = { + Background( + image = BackgroundImage.ActivityMember, + alpha = 0.7F + ) + }) { + + val data by model.allMember.observeAsState() + + data?.apply { + Spacer(modifier = Modifier.height(5.dp)) + Row( + modifier = Modifier + .fillMaxWidth() + .weight(0.2F), horizontalArrangement = Arrangement.Center + ) { + Box(contentAlignment = Alignment.Center) { + Image( + painter = painterResource(id = R.drawable.persion_name_border), + contentDescription = null + ) + Text(text = organizer.name) + } + } + Spacer(modifier = Modifier.height(5.dp)) + + + Box( + modifier = Modifier + .fillMaxWidth() + .weight(0.8F) + .padding(10.dp) + .border(width = 1.dp, color = MaterialTheme.colors.background) + ) { + val listState = rememberLazyListState() + participant?.let { + LazyColumn(state = listState) { + it.chunked(2).forEach { + item { + Spacer(modifier = Modifier.height(10.dp)) + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.SpaceEvenly + ) { + Spacer(modifier = Modifier.weight(0.05F)) + Participant(vo = it[0], modifier = Modifier.weight(0.4F)) + Spacer(modifier = Modifier.weight(0.1F)) + if (it.size == 2) { + Participant( + vo = it[1], + modifier = Modifier.weight(0.4F) + ) + } else { + Spacer(modifier = Modifier.weight(0.4F)) + } + Spacer(modifier = Modifier.weight(0.05F)) + } + Spacer(modifier = Modifier.height(10.dp)) + } + } + } +// Logger.i("totalItemsCount=${listState.layoutInfo.totalItemsCount},firstVisibleItemIndex=${listState.firstVisibleItemIndex}") + if (listState.layoutInfo.totalItemsCount - listState.firstVisibleItemIndex == model.initSize / 2 - 1) { + model.loadMore { scaffoldModel.update(message = it) } + } + } + } + } + + } + } + + @Composable + private fun Participant(modifier: Modifier = Modifier, vo: ActivityMemberVo) { + Box(modifier = modifier, contentAlignment = Alignment.Center) { + Image( + painter = painterResource(id = R.drawable.participant_border), + contentDescription = null, +// contentScale = ContentScale.FillBounds, +// modifier = Modifier.fillMaxSize() + ) + Text(text = vo.name) + } + } + + /** + * 交流区 + * + */ + @ExperimentalMaterialApi + @Composable + private fun BBS(model: BBSViewModel = viewModel(), scaffoldModel: ScaffoldModel = viewModel()) { + MainFrame(background = { Background(image = BackgroundImage.ActivityBBS, alpha = 0.7F) }) { + +// val drawerState = rememberBottomDrawerState(BottomDrawerValue.Closed) + val openDialog=model.openDialog.observeAsState() + + + Row( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 10.dp), + horizontalArrangement = Arrangement.End, + verticalAlignment = Alignment.CenterVertically + ) { + // IconToggleButton(checked = false, onCheckedChange = { /*TODO*/ }) { + // Row(horizontalArrangement = Arrangement.SpaceEvenly) { + // Icon(painter = painterResource(id = R.drawable.ic_configuration), contentDescription = null) + // } + // } + // Text(text = "") + + + IconButton(onClick = { model.openDialog() }) { + Icon( + painter = painterResource(id = R.drawable.ic_editor), + contentDescription = null + ) + } + } + + if(openDialog.value ==true) { + AlertDialog(onDismissRequest = { /*TODO*/ }, + buttons = { + Row( + modifier = Modifier + .padding(10.dp) + .fillMaxWidth(), + horizontalArrangement = Arrangement.SpaceEvenly + ) { + OutlinedButton(onClick = { + model.send { scaffoldModel.update(message = it) } + }) { + + Text(text = "发送") + } + OutlinedButton(onClick = { + model.closeDialog() + }) { + Text(text = "关闭") + } + } + }, text = { + Column(modifier = Modifier.padding(10.dp)) { + Card( + backgroundColor = MaterialTheme.colors.background, + modifier = Modifier.padding(10.dp) + ) { + BaseTextField( + form = model.newContent, modifier = Modifier + .fillMaxWidth() + .height(200.dp) + ) + } + } + }) + } + + Box( + modifier = Modifier + .weight(0.9F) + .padding(10.dp) + .border(width = 1.dp, color = MaterialTheme.colors.background) + ) { + val listState = rememberLazyListState() + val data by model.data.observeAsState() + LazyColumn(state = listState) { + data?.forEach { + item { + BBSItem(vo = it) + Spacer(modifier = Modifier.height(5.dp)) + Divider(color = MaterialTheme.colors.onBackground) + } + } + } +// Logger.i("totalItemsCount=${listState.layoutInfo.totalItemsCount},firstVisibleItemIndex=${listState.firstVisibleItemIndex}") + if (listState.layoutInfo.totalItemsCount - listState.firstVisibleItemIndex == model.initSize / 2 - 1) { + model.loadMore { scaffoldModel.update(message = it) } + } + } + + } + } + + @Composable + private fun BBSItem(vo: BBSVo) { + Column { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(10.dp) + ) { + Card( + backgroundColor = MaterialTheme.colors.secondaryVariant, + modifier = Modifier.weight(0.5F) + ) { + Column( + modifier = Modifier.height(50.dp), + verticalArrangement = Arrangement.SpaceEvenly + ) { + Text(text = vo.name) + Text(text = vo.createTime.format()) + } + } + Spacer(modifier = Modifier.weight(0.5F)) + } + + Card( + backgroundColor = MaterialTheme.colors.background, + modifier = Modifier.padding(10.dp) + ) { + Text( + text = vo.content, modifier = Modifier + .fillMaxWidth() + .height(100.dp) + ) + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/gyf/csams/association/model/AssociationViewModel.kt b/app/src/main/java/com/gyf/csams/association/model/AssociationViewModel.kt index 0768cfb..1e7de0f 100644 --- a/app/src/main/java/com/gyf/csams/association/model/AssociationViewModel.kt +++ b/app/src/main/java/com/gyf/csams/association/model/AssociationViewModel.kt @@ -4,18 +4,19 @@ import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope +import com.gyf.csams.NOT_IMPL_TIP import com.gyf.csams.uikit.AssociationMenu import com.gyf.csams.uikit.ScrollList import com.gyf.csams.uikit.StringForm +import com.gyf.csams.uikit.TopMenuInterface import com.orhanobut.logger.Logger import kotlinx.coroutines.launch -class AssociationViewModel:ViewModel() { - /** - * 当前菜单 - */ - private val _currentMenu=MutableLiveData() - val currentMenu:LiveData = _currentMenu + +class AssociationViewModel:ViewModel(),TopMenuInterface{ + + override val _currentMenu: MutableLiveData = MutableLiveData() + override val currentMenu: LiveData = _currentMenu /** * 下拉菜单状态 @@ -23,14 +24,7 @@ class AssociationViewModel:ViewModel() { private val _expanded=MutableLiveData(false) val expanded:LiveData = _expanded - /** - * 切换顶部菜单 - * - * @param menu - */ - fun clickMenu(menu:AssociationMenu){ - _currentMenu.value=menu - } + /** * 切换下拉菜单状态 @@ -113,7 +107,7 @@ class MemberViewModel:ScrollList(){ */ fun search(callback: (value: String) -> Unit){ Logger.i("搜索条件[成员姓名:${name.formValue.value}]") - callback("功能尚未实现,敬请期待") + callback(NOT_IMPL_TIP) } } @@ -131,11 +125,13 @@ class HistoryActViewModel: ScrollList() { } override fun load() { - _data.value?.apply { - repeat(initSize){ - add(HistoryActVo(name = "活动${size+1}")) + viewModelScope.launch { + _data.value?.apply { + repeat(initSize){ + add(HistoryActVo(name = "活动${size+1}")) + } + Logger.i("初始化活动数量:${size}") } - Logger.i("初始化活动数量:${size}") } } diff --git a/app/src/main/java/com/gyf/csams/association/model/ExamViewModel.kt b/app/src/main/java/com/gyf/csams/association/model/ExamViewModel.kt index bcff8c9..e2f92d0 100644 --- a/app/src/main/java/com/gyf/csams/association/model/ExamViewModel.kt +++ b/app/src/main/java/com/gyf/csams/association/model/ExamViewModel.kt @@ -3,6 +3,7 @@ package com.gyf.csams.association.model import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.viewModelScope +import com.gyf.csams.NOT_IMPL_TIP import com.gyf.csams.uikit.ScrollList import com.gyf.csams.uikit.StringForm import kotlinx.coroutines.launch @@ -159,7 +160,7 @@ class ExamViewModel:ScrollList() { * @param callback */ fun updateExam(callback: (message: String) -> Unit){ - callback("功能尚未实现,敬请期待") + callback(NOT_IMPL_TIP) } /** @@ -168,7 +169,7 @@ class ExamViewModel:ScrollList() { * @param callback */ fun postAnswer(callback: (message: String) -> Unit){ - callback("功能尚未实现,敬请期待") + callback(NOT_IMPL_TIP) } /** @@ -220,7 +221,7 @@ class ExamViewModel:ScrollList() { // callback("成功加载更多题目") // } -// callback("功能尚未实现,敬请期待") +// callback(NOT_IMPL_TIP) } fun addQuestion() { diff --git a/app/src/main/java/com/gyf/csams/association/model/RegAssociationViewModel.kt b/app/src/main/java/com/gyf/csams/association/model/RegAssociationViewModel.kt index 87dd954..5b9dc0e 100644 --- a/app/src/main/java/com/gyf/csams/association/model/RegAssociationViewModel.kt +++ b/app/src/main/java/com/gyf/csams/association/model/RegAssociationViewModel.kt @@ -4,6 +4,7 @@ import android.net.Uri import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel +import com.gyf.csams.NOT_IMPL_TIP import com.gyf.csams.uikit.StringForm @@ -39,7 +40,7 @@ class RegAssociationViewModel : ViewModel() { * @param callback */ fun register(callback: (value: String) -> Unit){ - callback("功能尚未实现,敬请期待") + callback(NOT_IMPL_TIP) } } \ No newline at end of file diff --git a/app/src/main/java/com/gyf/csams/association/model/RenameViewModel.kt b/app/src/main/java/com/gyf/csams/association/model/RenameViewModel.kt index 08e3db3..bb861b6 100644 --- a/app/src/main/java/com/gyf/csams/association/model/RenameViewModel.kt +++ b/app/src/main/java/com/gyf/csams/association/model/RenameViewModel.kt @@ -1,6 +1,7 @@ package com.gyf.csams.association.model import androidx.lifecycle.ViewModel +import com.gyf.csams.NOT_IMPL_TIP import com.gyf.csams.uikit.StringForm /** @@ -22,6 +23,6 @@ class RenameViewModel:ViewModel() { * */ fun post(callback:(message:String) -> Unit){ - callback("功能尚未实现,敬请期待") + callback(NOT_IMPL_TIP) } } \ No newline at end of file diff --git a/app/src/main/java/com/gyf/csams/association/ui/AssociationActivity.kt b/app/src/main/java/com/gyf/csams/association/ui/AssociationActivity.kt index aa75f73..d1927a4 100644 --- a/app/src/main/java/com/gyf/csams/association/ui/AssociationActivity.kt +++ b/app/src/main/java/com/gyf/csams/association/ui/AssociationActivity.kt @@ -19,7 +19,6 @@ import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.painterResource import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.unit.DpOffset import androidx.compose.ui.unit.dp import androidx.compose.ui.window.PopupProperties import androidx.lifecycle.viewmodel.compose.viewModel @@ -29,8 +28,11 @@ import com.gyf.csams.R import com.gyf.csams.association.model.* import com.gyf.csams.uikit.* import com.gyf.csams.uikit.theme.CSAMSTheme +import com.gyf.csams.util.randomChinese import com.orhanobut.logger.Logger + + /** * 社团界面 * @@ -44,18 +46,20 @@ class AssociationActivity: ComponentActivity() { nav, scaffoldState -> val context= LocalContext.current as AssociationActivity val model:AssociationViewModel= viewModel() - val startMenu=AssociationMenu.main - val menu:AssociationMenu by model.currentMenu.observeAsState(startMenu) + val currentMenuName:AssociationMenu by model.currentMenu.observeAsState(AssociationMenu.startMenu) val intent=Intent(context,ExamActivity::class.java) val expanded by model.expanded.observeAsState(false) Column { Logger.i("expanded=$expanded") - AssociationAppBar(menu = menu,nav = nav,back = { context.onBackPressed() },dropMenu = {model.switchType()}){ + TextTopAppBar(nav = nav, + currentMenuName= currentMenuName.menuName, + menuNames = AssociationMenu.values(), + iconMenu = {model.switchType()}){ Row{ DropdownMenu(expanded = expanded, onDismissRequest = { /*TODO*/ }, - offset = DpOffset.Zero.copy(x=50.dp), +// offset = DpOffset.Zero.copy(x=50.dp), properties = PopupProperties() ) { DropdownMenuItem(onClick = { @@ -111,22 +115,21 @@ class AssociationActivity: ComponentActivity() { } } } - } - NavHost(navController = nav, startDestination = startMenu.name) { - composable(AssociationMenu.member.name){ - model.clickMenu(AssociationMenu.member) + NavHost(navController = nav, startDestination = AssociationMenu.startMenu.name) { + composable(AssociationMenu.Member.name){ + model.clickMenu(AssociationMenu.Member) Member() ShowSnackbar(scaffoldState = scaffoldState) } - composable(AssociationMenu.main.name){ - model.clickMenu(AssociationMenu.main) + composable(AssociationMenu.Main.name){ + model.clickMenu(AssociationMenu.Main) Main() ShowSnackbar(scaffoldState = scaffoldState) } - composable(AssociationMenu.list.name){ - model.clickMenu(AssociationMenu.list) + composable(AssociationMenu.ActivityList.name){ + model.clickMenu(AssociationMenu.ActivityList) AssociationList() ShowSnackbar(scaffoldState = scaffoldState) } @@ -137,80 +140,80 @@ class AssociationActivity: ComponentActivity() { } } } -} -/** - * 社团成员 - * - */ -@Composable -private fun Member(){ - MainFrame(background = { Background(image = BackgroundImage.association_main) }) { - val searchWeight=0.2F - Search(modifier = Modifier - .fillMaxWidth() - .weight(searchWeight)) - MemberList(modifier = Modifier - .fillMaxWidth() - .weight(1 - searchWeight)) + /** + * 社团成员 + * + */ + @Composable + private fun Member(){ + MainFrame(background = { Background(image = BackgroundImage.AssociationMain) }) { + val searchWeight=0.2F + Search(modifier = Modifier + .fillMaxWidth() + .weight(searchWeight)) + MemberList(modifier = Modifier + .fillMaxWidth() + .weight(1 - searchWeight)) + + } } -} -/** - * 检索成员 - * - */ -@Composable -private fun Search(modifier:Modifier=Modifier, model: MemberViewModel= viewModel(), scaffoldModel: ScaffoldModel= viewModel()){ - Column(modifier = modifier.fillMaxSize()) { - Spacer(modifier = Modifier.weight(0.5F)) - Row(modifier = Modifier - .fillMaxWidth() - .weight(0.5F),verticalAlignment = Alignment.CenterVertically) { + /** + * 检索成员 + * + */ + @Composable + private fun Search(modifier:Modifier=Modifier, model: MemberViewModel= viewModel(), scaffoldModel: ScaffoldModel= viewModel()){ + Column(modifier = modifier.fillMaxSize()) { + Spacer(modifier = Modifier.weight(0.5F)) + Row(modifier = Modifier + .fillMaxWidth() + .weight(0.5F),verticalAlignment = Alignment.CenterVertically) { - val textFieldWeight=0.4F - val buttonWeight=0.2F - val spaceWeight=(1-textFieldWeight-buttonWeight)/3 - Spacer(modifier = Modifier.weight((spaceWeight))) - BaseTextField(modifier = Modifier.weight(textFieldWeight),form = model.name,singeLine = true) - Spacer(modifier = Modifier.weight(spaceWeight)) - OutlinedButton(onClick = { model.search { scaffoldModel.update(message=it) } },modifier = Modifier.weight(buttonWeight)) { - Text(text = model.search) + val textFieldWeight=0.4F + val buttonWeight=0.2F + val spaceWeight=(1-textFieldWeight-buttonWeight)/3 + Spacer(modifier = Modifier.weight((spaceWeight))) + BaseTextField(modifier = Modifier.weight(textFieldWeight),form = model.name,singeLine = true) + Spacer(modifier = Modifier.weight(spaceWeight)) + OutlinedButton(onClick = { model.search { scaffoldModel.update(message=it) } },modifier = Modifier.weight(buttonWeight)) { + Text(text = model.search) + } + Spacer(modifier = Modifier.weight(spaceWeight)) } - Spacer(modifier = Modifier.weight(spaceWeight)) } } -} -/** - * 成员列表 - * - */ -@Composable -private fun MemberList(modifier: Modifier=Modifier, model: MemberViewModel=viewModel(), scaffoldModel: ScaffoldModel= viewModel()){ - val list:MutableList? by model.memberList.observeAsState() - val listState= rememberLazyListState() + /** + * 成员列表 + * + */ + @Composable + private fun MemberList(modifier: Modifier=Modifier, model: MemberViewModel=viewModel(), scaffoldModel: ScaffoldModel= viewModel()){ + val list:MutableList? by model.memberList.observeAsState() + val listState= rememberLazyListState() LazyColumn(state = listState,modifier = modifier) { list?.forEach { - item { - Column { - Spacer(modifier = Modifier.height(10.dp)) - Row{ - val weight = 1F / 3 - Spacer(modifier = Modifier.weight(weight)) - Card( - modifier = Modifier.weight(weight), - backgroundColor = MaterialTheme.colors.background - ) { - Text(text = it.name) - } - Spacer(modifier = Modifier.weight(weight)) + item { + Column { + Spacer(modifier = Modifier.height(10.dp)) + Row{ + val weight = 1F / 3 + Spacer(modifier = Modifier.weight(weight)) + Card( + modifier = Modifier.weight(weight), + backgroundColor = MaterialTheme.colors.background + ) { + Text(text = it.name) } - Spacer(modifier = Modifier.height(10.dp)) - Divider(color = MaterialTheme.colors.background) + Spacer(modifier = Modifier.weight(weight)) } + Spacer(modifier = Modifier.height(10.dp)) + Divider(color = MaterialTheme.colors.background) } + } } item { Row(horizontalArrangement = Arrangement.Center,modifier = Modifier.fillMaxWidth()) { @@ -222,180 +225,183 @@ private fun MemberList(modifier: Modifier=Modifier, model: MemberViewModel=viewM } } + } } -} -/** - * 社团主页 - * - */ -@Composable -private fun Main(){ - MainFrame(background = { - Background(image = BackgroundImage.association_main,alpha = 0.7F) - }) { - val nameW=0.1F - val cardW=0.66F*0.4F - Name(modifier = Modifier - .fillMaxWidth() - .weight(nameW)) - DescCard( - modifier = Modifier - .weight(cardW) + /** + * 社团主页 + * + */ + @Composable + private fun Main(){ + MainFrame(background = { + Background(image = BackgroundImage.AssociationMain,alpha = 0.7F) + }) { + val nameW=0.1F + val cardW=0.66F*0.4F + Name(modifier = Modifier .fillMaxWidth() - ) - Commander( - modifier = Modifier.weight(cardW) - ) - Showcase(modifier = Modifier.weight(1F-nameW-cardW-cardW)) + .weight(nameW)) + DescCard( + modifier = Modifier + .weight(cardW) + .fillMaxWidth(), + content = randomChinese(500) + ) + Commander( + modifier = Modifier.weight(cardW) + ) + Showcase(modifier = Modifier.weight(1F-nameW-cardW-cardW)) + } } -} -/** - * 社团名字 - * - * @param modifier - */ -@Composable -private fun Name(modifier: Modifier){ - Box(modifier = modifier) { - Image( - painter = painterResource(id = R.drawable.association_name_border), - contentDescription = null, - contentScale = ContentScale.FillBounds, - modifier=Modifier.fillMaxSize() - ) - Column{ - Spacer(modifier = Modifier.weight(1.7F / 3)) - Row(modifier = Modifier - .fillMaxWidth() - .weight(1F / 3), - horizontalArrangement = Arrangement.Center) { - Text(text = "社团名字") + /** + * 社团名字 + * + * @param modifier + */ + @Composable + private fun Name(modifier: Modifier){ + Box(modifier = modifier) { + Image( + painter = painterResource(id = R.drawable.association_name_border), + contentDescription = null, + contentScale = ContentScale.FillBounds, + modifier=Modifier.fillMaxSize() + ) + Column{ + Spacer(modifier = Modifier.weight(1.7F / 3)) + Row(modifier = Modifier + .fillMaxWidth() + .weight(1F / 3), + horizontalArrangement = Arrangement.Center) { + Text(text = "社团名字") + } + Spacer(modifier = Modifier.weight(0.3F / 3)) } - Spacer(modifier = Modifier.weight(0.3F / 3)) } } -} -/** - * 团长名字 - * - * @param modifier - */ -@Composable -private fun Commander(modifier: Modifier){ - Box(modifier=modifier,contentAlignment = Alignment.Center){ - Row(modifier = Modifier.fillMaxWidth(),horizontalArrangement = Arrangement.Center) { + /** + * 团长名字 + * + * @param modifier + */ + @Composable + private fun Commander(modifier: Modifier){ + Box(modifier=modifier,contentAlignment = Alignment.Center){ + Row(modifier = Modifier.fillMaxWidth(),horizontalArrangement = Arrangement.Center) { - Image(painter = painterResource(id = R.drawable.association_persion_name_border), - contentDescription = null - ) + Image(painter = painterResource(id = R.drawable.persion_name_border), + contentDescription = null + ) + } + Text(text = "团长") } - Text(text = "团长") } -} -/** - * 风采展示区 - * - * @param modifier - */ -@Composable -private fun Showcase(modifier: Modifier){ - Box(modifier = modifier,contentAlignment = Alignment.Center) { - Image(painter = painterResource(id = R.drawable.showcase_border), - contentDescription = null, - modifier=Modifier.fillMaxSize()) - Image(painter = painterResource(id = R.drawable.ic_launcher_foreground), contentDescription = null) + /** + * 风采展示区 + * + * @param modifier + */ + @Composable + private fun Showcase(modifier: Modifier){ + Box(modifier = modifier,contentAlignment = Alignment.Center) { + Image(painter = painterResource(id = R.drawable.showcase_border), + contentDescription = null, + modifier=Modifier.fillMaxSize()) + Image(painter = painterResource(id = R.drawable.ic_launcher_foreground), contentDescription = null) + } } -} -/** - * 活动列表 - * - */ -@Composable -private fun AssociationList(){ - MainFrame(background = { Background(image = BackgroundImage.association_main,alpha = 07F) }) { - val onGoWeight=0.3F - OngoingActivity(modifier = Modifier - .weight(onGoWeight) - .fillMaxWidth()) - HistoryActivityList(modifier = Modifier - .fillMaxWidth() - .weight(1 - onGoWeight) - .border(width = 1.dp, color = MaterialTheme.colors.onBackground)) + /** + * 活动列表 + * + */ + @Composable + private fun AssociationList(){ + MainFrame(background = { Background(image = BackgroundImage.AssociationMain,alpha = 07F) }) { + val onGoWeight=0.3F + OngoingActivity(modifier = Modifier + .weight(onGoWeight) + .fillMaxWidth()) + HistoryActivityList(modifier = Modifier + .fillMaxWidth() + .weight(1 - onGoWeight) + .border(width = 1.dp, color = MaterialTheme.colors.onBackground)) + } } -} -/** - * 进行中的活动 - * - */ -@Composable -private fun OngoingActivity(modifier: Modifier=Modifier){ - Row(modifier = modifier,horizontalArrangement = Arrangement.Center) { - val weight=0.5F - val spaceWeight=(1-0.5F)/2 - Spacer(modifier = Modifier.weight(spaceWeight)) - Poster(id = R.drawable.ic_launcher_foreground,modifier = Modifier.weight(weight)) - Spacer(modifier = Modifier.weight(spaceWeight)) - } + /** + * 进行中的活动 + * + */ + @Composable + private fun OngoingActivity(modifier: Modifier=Modifier){ + Row(modifier = modifier,horizontalArrangement = Arrangement.Center) { + val weight=0.5F + val spaceWeight=(1-0.5F)/2 + Spacer(modifier = Modifier.weight(spaceWeight)) + Poster(id = R.drawable.ic_launcher_foreground,modifier = Modifier.weight(weight)) + Spacer(modifier = Modifier.weight(spaceWeight)) + } -} + } -/** - * 历史活动列表 - * - * @param modifier - */ -@Composable -private fun HistoryActivityList(modifier: Modifier,model:HistoryActViewModel= viewModel(),scaffoldModel: ScaffoldModel= viewModel()){ - val listState= rememberLazyListState() - val list by model.data.observeAsState() - LazyColumn(state = listState,modifier = modifier) { - list?.chunked(2)?.forEach { - item { - Row(modifier=Modifier.fillMaxWidth()) { - HistoryActivity(modifier = Modifier.weight(0.4F),it[0]) - Spacer(modifier = Modifier.weight(0.2F)) - if (it.size==2) HistoryActivity(modifier = Modifier.weight(0.4F),it[1]) - else Box(modifier = Modifier.weight(0.4F)) + /** + * 历史活动列表 + * + * @param modifier + */ + @Composable + private fun HistoryActivityList(modifier: Modifier,model:HistoryActViewModel= viewModel(),scaffoldModel: ScaffoldModel= viewModel()){ + val listState= rememberLazyListState() + val list by model.data.observeAsState() + LazyColumn(state = listState,modifier = modifier) { + list?.chunked(2)?.forEach { + item { + Row(modifier=Modifier.fillMaxWidth()) { + HistoryActivity(modifier = Modifier.weight(0.4F),it[0]) + Spacer(modifier = Modifier.weight(0.2F)) + if (it.size==2) HistoryActivity(modifier = Modifier.weight(0.4F),it[1]) + else Box(modifier = Modifier.weight(0.4F)) + } + Spacer(modifier = Modifier.height(10.dp)) + Divider(color = MaterialTheme.colors.background) } - Spacer(modifier = Modifier.height(10.dp)) - Divider(color = MaterialTheme.colors.background) } } + if(listState.layoutInfo.totalItemsCount-listState.firstVisibleItemIndex==model.initSize/2-1){ + model.loadMore { scaffoldModel.update(message=it) } + } } - if(listState.layoutInfo.totalItemsCount-listState.firstVisibleItemIndex==model.initSize/2-1){ - model.loadMore { scaffoldModel.update(message=it) } - } -} -/** - * 历史活动 - * - * @param modifier - */ -@Composable -private fun HistoryActivity(modifier: Modifier,historyActVo: HistoryActVo){ - Box(modifier=modifier,contentAlignment = Alignment.Center){ - Image(painter = painterResource(id = R.drawable.history_activity_border), - contentDescription = null, - modifier = Modifier.fillMaxSize()) - Image(painter = painterResource(id = R.drawable.ic_launcher_foreground), - contentDescription = null, - modifier = Modifier.fillMaxSize()) - Text(text = historyActVo.name) + /** + * 历史活动 + * + * @param modifier + */ + @Composable + private fun HistoryActivity(modifier: Modifier,historyActVo: HistoryActVo){ + Box(modifier=modifier,contentAlignment = Alignment.Center){ + Image(painter = painterResource(id = R.drawable.history_activity_border), + contentDescription = null, + modifier = Modifier.fillMaxSize()) + Image(painter = painterResource(id = R.drawable.ic_launcher_foreground), + contentDescription = null, + modifier = Modifier.fillMaxSize()) + Text(text = historyActVo.name) + } } -} -@Preview -@Composable -fun NamePreview(){ - Divider(color = MaterialTheme.colors.background) + @Preview + @Composable + fun NamePreview(){ + Divider(color = MaterialTheme.colors.background) + } } + diff --git a/app/src/main/java/com/gyf/csams/association/ui/ExamActivity.kt b/app/src/main/java/com/gyf/csams/association/ui/ExamActivity.kt index 9c5b263..ce80f90 100644 --- a/app/src/main/java/com/gyf/csams/association/ui/ExamActivity.kt +++ b/app/src/main/java/com/gyf/csams/association/ui/ExamActivity.kt @@ -39,7 +39,7 @@ class ExamActivity : ComponentActivity() { setContent { Body { scaffoldState -> - MainFrame(background = { Background(image = BackgroundImage.exam) }) { + MainFrame(background = { Background(image = BackgroundImage.Exam,alpha = 0.6F) }) { Spacer(modifier = Modifier.weight(0.1F)) Title(modifier = Modifier.weight(0.1F)) Exam(modifier = Modifier.weight(0.8F)) @@ -48,287 +48,288 @@ class ExamActivity : ComponentActivity() { } } } -} -/** - * 底部按钮 - * - */ -@Composable -private fun BottomButton( - modifier: Modifier = Modifier, - model: ExamViewModel = viewModel(), - scaffoldModel: ScaffoldModel = viewModel() -) { - val context = LocalContext.current as ExamActivity - - Row(modifier = modifier, horizontalArrangement = Arrangement.Center) { - when(context.activityType){ - ExamActivityType.SET_EXAM->OutlinedButton(onClick = { - model.updateExam { scaffoldModel.update(message=it) } - }, modifier = Modifier.background(color = MaterialTheme.colors.primary)) { - Text(text = model.updateExam) - } - ExamActivityType.JOIN_Association->OutlinedButton(onClick = { - model.postAnswer { scaffoldModel.update(message=it) } - }, modifier = Modifier.background(color = MaterialTheme.colors.primary)) { - Text(text = model.postAnswer) + + /** + * 底部按钮 + * + */ + @Composable + private fun BottomButton( + modifier: Modifier = Modifier, + model: ExamViewModel = viewModel(), + scaffoldModel: ScaffoldModel = viewModel() + ) { + val context = LocalContext.current as ExamActivity + + Row(modifier = modifier, horizontalArrangement = Arrangement.Center) { + when(context.activityType){ + ExamActivityType.SET_EXAM->OutlinedButton(onClick = { + model.updateExam { scaffoldModel.update(message=it) } + }, modifier = Modifier.background(color = MaterialTheme.colors.primary)) { + Text(text = model.updateExam) + } + ExamActivityType.JOIN_Association->OutlinedButton(onClick = { + model.postAnswer { scaffoldModel.update(message=it) } + }, modifier = Modifier.background(color = MaterialTheme.colors.primary)) { + Text(text = model.postAnswer) + } } - } - Spacer(modifier = Modifier.width(10.dp)) - OutlinedButton(onClick = { - context.onBackPressed() - }, modifier = Modifier.background(color = MaterialTheme.colors.secondary)) { - Text(text = model.back) + Spacer(modifier = Modifier.width(10.dp)) + OutlinedButton(onClick = { + context.onBackPressed() + }, modifier = Modifier.background(color = MaterialTheme.colors.secondary)) { + Text(text = model.back) + } } } -} -/** - * 标题 - * - * @param modifier - */ -@Composable -private fun Title(modifier: Modifier = Modifier) { - val context= LocalContext.current as ExamActivity - Row(horizontalArrangement = Arrangement.Center, modifier = modifier.fillMaxWidth()) { - Text(text = context.activityType.menuName, style = MaterialTheme.typography.h4) + /** + * 标题 + * + * @param modifier + */ + @Composable + private fun Title(modifier: Modifier = Modifier) { + val context= LocalContext.current as ExamActivity + Row(horizontalArrangement = Arrangement.Center, modifier = modifier.fillMaxWidth()) { + Text(text = context.activityType.menuName, style = MaterialTheme.typography.h4) + } } -} -@Composable -private fun ExamChild(it:Exam,examHeight: Dp,isAdd: Boolean=false){ - val questionWeight=0.3F - when (it) { - is OpenQuestionsVo -> ExamOQ( - openQuestionsVo = it, - modifier = Modifier.height(examHeight*questionWeight), - isAdd = isAdd - ) - is ChoiceQuestionVo -> ExamCQ( - choiceQuestionVo = it, - modifier = Modifier.height(examHeight), - questionWeight = questionWeight, - isAdd = isAdd - ) + @Composable + private fun ExamChild(it:Exam,examHeight: Dp,isAdd: Boolean=false){ + val questionWeight=0.3F + when (it) { + is OpenQuestionsVo -> ExamOQ( + openQuestionsVo = it, + modifier = Modifier.height(examHeight*questionWeight), + isAdd = isAdd + ) + is ChoiceQuestionVo -> ExamCQ( + choiceQuestionVo = it, + modifier = Modifier.height(examHeight), + questionWeight = questionWeight, + isAdd = isAdd + ) + } } -} -/** - * 题目列表 - * - * @param modifier - * @param model - */ -@Composable -private fun Exam( - modifier: Modifier = Modifier, - model: ExamViewModel = viewModel(), - scaffoldModel: ScaffoldModel = viewModel(), - examHeight: Dp = 350.dp -) { - val listState = rememberLazyListState() - val data by model.data.observeAsState() - val newExam by model.newExam.observeAsState() - LazyColumn(state = listState, modifier = modifier) { - data?.forEach { - item { - ExamChild(it = it, examHeight = examHeight) - Spacer(modifier = Modifier.height(20.dp)) + /** + * 题目列表 + * + * @param modifier + * @param model + */ + @Composable + private fun Exam( + modifier: Modifier = Modifier, + model: ExamViewModel = viewModel(), + scaffoldModel: ScaffoldModel = viewModel(), + examHeight: Dp = 350.dp + ) { + val listState = rememberLazyListState() + val data by model.data.observeAsState() + val newExam by model.newExam.observeAsState() + LazyColumn(state = listState, modifier = modifier) { + data?.forEach { + item { + ExamChild(it = it, examHeight = examHeight) + Spacer(modifier = Modifier.height(20.dp)) + } } - } - newExam?.let { - item { - Column { - OutlinedButton(onClick = { model.switchType(it) }) { - Text(text = "切换到${if (newExam is ChoiceQuestionVo) "开放题" else "选择题"}") + newExam?.let { + item { + Column { + OutlinedButton(onClick = { model.switchType(it) }) { + Text(text = "切换到${if (newExam is ChoiceQuestionVo) "开放题" else "选择题"}") + } + ExamChild(it = it, examHeight = examHeight,isAdd = true) } - ExamChild(it = it, examHeight = examHeight,isAdd = true) } } - } - item { - Column { - Divider(color = MaterialTheme.colors.background) - Spacer(modifier = Modifier.height(30.dp)) - BottomButton(modifier = Modifier.fillMaxWidth()) + item { + Column { + Divider(color = MaterialTheme.colors.background) + Spacer(modifier = Modifier.height(30.dp)) + BottomButton(modifier = Modifier.fillMaxWidth()) + } } - } - } - if (listState.layoutInfo.totalItemsCount - listState.firstVisibleItemIndex == model.initSize / 2 - 1) { - model.loadMore { scaffoldModel.update(message=it) } - } + } + if (listState.layoutInfo.totalItemsCount - listState.firstVisibleItemIndex == model.initSize / 2 - 1) { + model.loadMore { scaffoldModel.update(message=it) } + } -} + } -/** - * 问题 - * - * @param modifier - * @param exam - */ -@Composable -private fun Question(modifier: Modifier = Modifier, exam: Exam) { - BaseTextField( - form = exam.question, - modifier = modifier - .fillMaxSize() - .background(color = MaterialTheme.colors.background) - ) + /** + * 问题 + * + * @param modifier + * @param exam + */ + @Composable + private fun Question(modifier: Modifier = Modifier, exam: Exam) { + BaseTextField( + form = exam.question, + modifier = modifier + .fillMaxSize() + .background(color = MaterialTheme.colors.background) + ) -} + } -/** - * 操作按钮 - * - */ -@Composable -private fun ActionButton(modifier: Modifier = Modifier, isAdd: Boolean, - model: ExamViewModel= viewModel(), - scaffoldModel: ScaffoldModel= viewModel(), - exam: Exam) { - val list by model.data.observeAsState() - val newExam by model.newExam.observeAsState() - Box( - contentAlignment = Alignment.Center, - modifier = modifier - ) { - IconButton(onClick = { - if(isAdd){ - if((newExam?.question?.formValue?.value ?: "").isNotEmpty()){ - scaffoldModel.update(message=model.addTip,actionLabel = model.actionLabel){ - model.addQuestion() + /** + * 操作按钮 + * + */ + @Composable + private fun ActionButton(modifier: Modifier = Modifier, isAdd: Boolean, + model: ExamViewModel= viewModel(), + scaffoldModel: ScaffoldModel= viewModel(), + exam: Exam) { + val list by model.data.observeAsState() + val newExam by model.newExam.observeAsState() + Box( + contentAlignment = Alignment.Center, + modifier = modifier + ) { + IconButton(onClick = { + if(isAdd){ + if((newExam?.question?.formValue?.value ?: "").isNotEmpty()){ + scaffoldModel.update(message=model.addTip,actionLabel = model.actionLabel){ + model.addQuestion() + } + }else{ + scaffoldModel.update(message = model.questionIsNull) } - }else{ - scaffoldModel.update(message = model.questionIsNull) - } - }else{ - if(list?.size==1){ - scaffoldModel.update(model.deleteLeastOne) }else{ - scaffoldModel.update(message=model.deleteTip,actionLabel = model.actionLabel){ - model.deleteQuestion(exam = exam) + if(list?.size==1){ + scaffoldModel.update(model.deleteLeastOne) + }else{ + scaffoldModel.update(message=model.deleteTip,actionLabel = model.actionLabel){ + model.deleteQuestion(exam = exam) + } } } + }) { + Icon( + painter = painterResource(id = if (isAdd) R.drawable.ic_add_select else R.drawable.ic_sami_select), + contentDescription = null + ) } - }) { - Icon( - painter = painterResource(id = if (isAdd) R.drawable.ic_add_select else R.drawable.ic_sami_select), - contentDescription = null - ) } } -} -/** - * 开放题 - * - * @param openQuestionsVo - */ -@Composable -private fun ExamOQ( - modifier: Modifier = Modifier, - openQuestionsVo: OpenQuestionsVo, - isAdd: Boolean = false -) { - Row(modifier = modifier) { - val context= LocalContext.current as ExamActivity - Question( - exam = openQuestionsVo, modifier = - if(context.activityType==ExamActivityType.SET_EXAM) - Modifier.weight(0.8F).fillMaxHeight() - else - Modifier - ) - if(context.activityType==ExamActivityType.SET_EXAM){ - ActionButton( - modifier = Modifier - .weight(0.2F) - .fillMaxHeight(), - isAdd = isAdd, - exam = openQuestionsVo + /** + * 开放题 + * + * @param openQuestionsVo + */ + @Composable + private fun ExamOQ( + modifier: Modifier = Modifier, + openQuestionsVo: OpenQuestionsVo, + isAdd: Boolean = false + ) { + Row(modifier = modifier) { + val context= LocalContext.current as ExamActivity + Question( + exam = openQuestionsVo, modifier = + if(context.activityType==ExamActivityType.SET_EXAM) + Modifier.weight(0.8F).fillMaxHeight() + else + Modifier ) + if(context.activityType==ExamActivityType.SET_EXAM){ + ActionButton( + modifier = Modifier + .weight(0.2F) + .fillMaxHeight(), + isAdd = isAdd, + exam = openQuestionsVo + ) + } } } -} -/** - * 选择题 - * - * @param choiceQuestionVo - */ -@Composable -private fun ExamCQ( - modifier: Modifier = Modifier, - choiceQuestionVo: ChoiceQuestionVo, - isAdd: Boolean = false, - model: ExamViewModel = viewModel(), - questionWeight:Float -) { - Row(modifier = modifier) { - val context= LocalContext.current as ExamActivity - Column( - modifier = if(context.activityType==ExamActivityType.SET_EXAM) - Modifier.weight(0.8F).fillMaxHeight() - else - Modifier - ) { - Question( - exam = choiceQuestionVo, - modifier = Modifier - .fillMaxWidth() - .weight(questionWeight) - ) - Card( - backgroundColor = MaterialTheme.colors.secondaryVariant, - modifier = Modifier - .fillMaxWidth() - .weight(1 - questionWeight) + /** + * 选择题 + * + * @param choiceQuestionVo + */ + @Composable + private fun ExamCQ( + modifier: Modifier = Modifier, + choiceQuestionVo: ChoiceQuestionVo, + isAdd: Boolean = false, + model: ExamViewModel = viewModel(), + questionWeight:Float + ) { + Row(modifier = modifier) { + val context= LocalContext.current as ExamActivity + Column( + modifier = if(context.activityType==ExamActivityType.SET_EXAM) + Modifier.weight(0.8F).fillMaxHeight() + else + Modifier ) { + Question( + exam = choiceQuestionVo, + modifier = Modifier + .fillMaxWidth() + .weight(questionWeight) + ) + Card( + backgroundColor = MaterialTheme.colors.secondaryVariant, + modifier = Modifier + .fillMaxWidth() + .weight(1 - questionWeight) + ) { - choiceQuestionVo.answers.apply { - Column { - forEach { - Row(modifier = Modifier - .fillMaxWidth() - .weight(1F / ANSWER_SIZE)) { - val answerIndex: Int = indexOf(it) - val click = { - model.update( - oldExam = choiceQuestionVo, - newExam = choiceQuestionVo.copy(rightAnswer = answerIndex) - ) + choiceQuestionVo.answers.apply { + Column { + forEach { + Row(modifier = Modifier + .fillMaxWidth() + .weight(1F / ANSWER_SIZE)) { + val answerIndex: Int = indexOf(it) + val click = { + model.update( + oldExam = choiceQuestionVo, + newExam = choiceQuestionVo.copy(rightAnswer = answerIndex) + ) + } + val isRightAnswer = + choiceQuestionVo.rightAnswer == answerIndex + RadioButton(selected = isRightAnswer, onClick = click) + BaseTextField(form = it) } - val isRightAnswer = - choiceQuestionVo.rightAnswer == answerIndex - RadioButton(selected = isRightAnswer, onClick = click) - BaseTextField(form = it) } } } } } - } - if(context.activityType==ExamActivityType.SET_EXAM) { - ActionButton( - modifier = Modifier - .weight(0.2F) - .fillMaxHeight(), - isAdd = isAdd, - exam = choiceQuestionVo - ) - } + if(context.activityType==ExamActivityType.SET_EXAM) { + ActionButton( + modifier = Modifier + .weight(0.2F) + .fillMaxHeight(), + isAdd = isAdd, + exam = choiceQuestionVo + ) + } + } } -} \ No newline at end of file +} diff --git a/app/src/main/java/com/gyf/csams/association/ui/ReNameActivity.kt b/app/src/main/java/com/gyf/csams/association/ui/ReNameActivity.kt index b204ddd..09fdbae 100644 --- a/app/src/main/java/com/gyf/csams/association/ui/ReNameActivity.kt +++ b/app/src/main/java/com/gyf/csams/association/ui/ReNameActivity.kt @@ -26,7 +26,7 @@ class ReNameActivity: ComponentActivity() { setContent { Body { scaffoldState -> - MainFrame(background = { Background(image = BackgroundImage.rename) }) { + MainFrame(background = { Background(image = BackgroundImage.Rename) }) { Spacer( modifier = Modifier .weight(0.2F) @@ -48,67 +48,67 @@ class ReNameActivity: ComponentActivity() { } } } -} -/** - * 标题 - * - */ -@Composable -private fun Title(modifier: Modifier=Modifier,model:RenameViewModel= viewModel()){ - Row(modifier = modifier.fillMaxWidth(),horizontalArrangement = Arrangement.Center) { - Text(text = model.menuName,style = MaterialTheme.typography.h4) + /** + * 标题 + * + */ + @Composable + private fun Title(modifier: Modifier=Modifier,model:RenameViewModel= viewModel()){ + Row(modifier = modifier.fillMaxWidth(),horizontalArrangement = Arrangement.Center) { + Text(text = model.menuName,style = MaterialTheme.typography.h4) + } } -} -/** - * 社团原名 - * - */ -@Composable -private fun OldName(modifier: Modifier=Modifier,model:RenameViewModel= viewModel()){ - BaseTextField(form = model.oldName,modifier = modifier.fillMaxWidth(),singeLine = true) -} + /** + * 社团原名 + * + */ + @Composable + private fun OldName(modifier: Modifier=Modifier,model:RenameViewModel= viewModel()){ + BaseTextField(form = model.oldName,modifier = modifier.fillMaxWidth(),singeLine = true) + } -/** - * 社团新名 - * - */ -@Composable -private fun NewName(modifier: Modifier=Modifier,model:RenameViewModel= viewModel()){ - BaseTextField(form = model.newName,modifier = modifier.fillMaxWidth(),singeLine = true) -} + /** + * 社团新名 + * + */ + @Composable + private fun NewName(modifier: Modifier=Modifier,model:RenameViewModel= viewModel()){ + BaseTextField(form = model.newName,modifier = modifier.fillMaxWidth(),singeLine = true) + } -/** - * 换名原因 - * - */ -@Composable -private fun Cause(modifier: Modifier=Modifier,model:RenameViewModel= viewModel()){ - BaseTextField(form = model.cause,modifier = modifier.fillMaxWidth()) -} + /** + * 换名原因 + * + */ + @Composable + private fun Cause(modifier: Modifier=Modifier,model:RenameViewModel= viewModel()){ + BaseTextField(form = model.cause,modifier = modifier.fillMaxWidth()) + } -/** - * 操作按钮 - * - * @param modifier - * @param model - */ -@Composable -private fun BottomButton(modifier: Modifier=Modifier,model:RenameViewModel= viewModel(),scaffoldModel: ScaffoldModel= viewModel()){ - Row(modifier = modifier.fillMaxWidth()) { - val weight=(1-0.5F)/2 - val context= LocalContext.current as ReNameActivity - Spacer(modifier = Modifier.weight(weight)) - Row(modifier=Modifier.weight(0.5F)) { - OutlinedButton(onClick = { model.post{scaffoldModel.update(message=it)} }) { - Text(text = model.postDesc) - } - Spacer(modifier = Modifier.width(10.dp)) - OutlinedButton(onClick = { context.onBackPressed() }) { - Text(text = model.back) + /** + * 操作按钮 + * + * @param modifier + * @param model + */ + @Composable + private fun BottomButton(modifier: Modifier=Modifier,model:RenameViewModel= viewModel(),scaffoldModel: ScaffoldModel= viewModel()){ + Row(modifier = modifier.fillMaxWidth()) { + val weight=(1-0.5F)/2 + val context= LocalContext.current as ReNameActivity + Spacer(modifier = Modifier.weight(weight)) + Row(modifier=Modifier.weight(0.5F)) { + OutlinedButton(onClick = { model.post{scaffoldModel.update(message=it)} }) { + Text(text = model.postDesc) + } + Spacer(modifier = Modifier.width(10.dp)) + OutlinedButton(onClick = { context.onBackPressed() }) { + Text(text = model.back) + } } + Spacer(modifier = Modifier.weight(weight)) } - Spacer(modifier = Modifier.weight(weight)) } -} +} \ No newline at end of file diff --git a/app/src/main/java/com/gyf/csams/association/ui/RegAssociationActivity.kt b/app/src/main/java/com/gyf/csams/association/ui/RegAssociationActivity.kt index cfd59f7..267d28a 100644 --- a/app/src/main/java/com/gyf/csams/association/ui/RegAssociationActivity.kt +++ b/app/src/main/java/com/gyf/csams/association/ui/RegAssociationActivity.kt @@ -50,7 +50,7 @@ class RegAssociationActivity: ComponentActivity(){ CSAMSTheme { Body { scaffoldState -> - MainFrame(background = { Background(BackgroundImage.reg_association,alpha = 0.5F) }) { + MainFrame(background = { Background(BackgroundImage.RegAssociation,alpha = 0.5F) }) { Spacer( modifier = Modifier .weight(0.1F) @@ -79,145 +79,147 @@ class RegAssociationActivity: ComponentActivity(){ } } -} -/** - * 社团Logo - * - * @param modifier - */ -@Composable -private fun Logo(model:RegAssociationViewModel= viewModel(),modifier: Modifier) { - val photoIntent=Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI) - photoIntent.type = "image/*" - val uri:Uri? by model.picture.observeAsState() - - val resultLauncher=rememberLauncherForActivityResult(contract = ActivityResultContracts.StartActivityForResult()) { - when(it.resultCode){ - Activity.RESULT_OK->{ - Logger.i("uri=${it.data?.data}") - it.data?.data?.let { it1 -> model.setPicture(it1) } + /** + * 社团Logo + * + * @param modifier + */ + @Composable + private fun Logo(model:RegAssociationViewModel= viewModel(),modifier: Modifier) { + val photoIntent=Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI) + photoIntent.type = "image/*" + val uri:Uri? by model.picture.observeAsState() + + val resultLauncher=rememberLauncherForActivityResult(contract = ActivityResultContracts.StartActivityForResult()) { + when(it.resultCode){ + Activity.RESULT_OK->{ + Logger.i("uri=${it.data?.data}") + it.data?.data?.let { it1 -> model.setPicture(it1) } + } } } - } - val loadPicture={ - //model.loadPicture(context) - resultLauncher.launch(photoIntent) - } + val loadPicture={ + //model.loadPicture(context) + resultLauncher.launch(photoIntent) + } - val launcher = rememberLauncherForActivityResult( - ActivityResultContracts.RequestPermission() - ) { isGranted: Boolean -> - if (isGranted) { - // Permission Accepted: Do something - loadPicture() - } else { - // Permission Denied: Do something - Logger.w(model.deninedPermission) + val launcher = rememberLauncherForActivityResult( + ActivityResultContracts.RequestPermission() + ) { isGranted: Boolean -> + if (isGranted) { + // Permission Accepted: Do something + loadPicture() + } else { + // Permission Denied: Do something + Logger.w(model.deninedPermission) + } } - } - val context= LocalContext.current + val context= LocalContext.current - Box(contentAlignment = Alignment.Center,modifier = modifier) { - Row(verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.Center,modifier = Modifier - .fillMaxSize() - .border(width = 1.dp, color = Color.Black)) { + Box(contentAlignment = Alignment.Center,modifier = modifier) { + Row(verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.Center,modifier = Modifier + .fillMaxSize() + .border(width = 1.dp, color = Color.Black)) { - if (uri == null) { - OutlinedButton(onClick = { - when (PackageManager.PERMISSION_GRANTED) { - ContextCompat.checkSelfPermission( - context, - Manifest.permission.READ_EXTERNAL_STORAGE - ) -> { - // Some works that require permission - loadPicture() - } - else -> { - // Asking for permission - launcher.launch(Manifest.permission.READ_EXTERNAL_STORAGE) - } - } - }) { - Text(text = model.piciurePlaceHolder) - } - } else { - uri.let { - if(it!=null){ - Row { - Image(bitmap = BitmapFactory.decodeStream(context.contentResolver.openInputStream(it)) - .asImageBitmap(), contentDescription = null) - IconButton(onClick = { + if (uri == null) { + OutlinedButton(onClick = { + when (PackageManager.PERMISSION_GRANTED) { + ContextCompat.checkSelfPermission( + context, + Manifest.permission.READ_EXTERNAL_STORAGE + ) -> { + // Some works that require permission loadPicture() - }) { - Image(painter = painterResource(id = R.drawable.ic_exchange_rate), contentDescription = null) + } + else -> { + // Asking for permission + launcher.launch(Manifest.permission.READ_EXTERNAL_STORAGE) } } + }) { + Text(text = model.piciurePlaceHolder) + } + } else { + uri.let { + if(it!=null){ + Row { + Image(bitmap = BitmapFactory.decodeStream(context.contentResolver.openInputStream(it)) + .asImageBitmap(), contentDescription = null) + IconButton(onClick = { + loadPicture() + }) { + Image(painter = painterResource(id = R.drawable.ic_exchange_rate), contentDescription = null) + } + } - }else{ - Text(text = model.errorPicture) + }else{ + Text(text = model.errorPicture) + } } } - } + } + } + } + @Composable + private fun BottomButton(modifier: Modifier=Modifier,scaffoldModel: ScaffoldModel= viewModel(),model:RegAssociationViewModel= viewModel()){ + val context= LocalContext.current as RegAssociationActivity + Row(modifier = modifier,horizontalArrangement = Arrangement.Center) { + OutlinedButton(onClick = { + model.register { scaffoldModel.update(message=it) } + },modifier = Modifier.background(color = MaterialTheme.colors.primary)) { + Text(text = model.register) + } + Spacer(modifier = Modifier.width(10.dp)) + OutlinedButton(onClick = { + context.onBackPressed() + },modifier = Modifier.background(color = MaterialTheme.colors.secondary)) { + Text(text = model.back) + } + } -} + } -@Composable -private fun BottomButton(modifier: Modifier=Modifier,scaffoldModel: ScaffoldModel= viewModel(),model:RegAssociationViewModel= viewModel()){ - val context= LocalContext.current as RegAssociationActivity - Row(modifier = modifier,horizontalArrangement = Arrangement.Center) { - OutlinedButton(onClick = { - model.register { scaffoldModel.update(message=it) } - },modifier = Modifier.background(color = MaterialTheme.colors.primary)) { - Text(text = model.register) - } - Spacer(modifier = Modifier.width(10.dp)) - OutlinedButton(onClick = { - context.onBackPressed() - },modifier = Modifier.background(color = MaterialTheme.colors.secondary)) { - Text(text = model.back) + /** + * 菜单标题 + * + */ + @Composable + private fun Title(model:RegAssociationViewModel= viewModel()){ + Row(modifier = Modifier.fillMaxWidth(),horizontalArrangement = Arrangement.Center) { + Text(text = model.frameDesc,style = MaterialTheme.typography.h4) } } -} + /** + * 社团名称 + * @param model + */ + @Composable + private fun Name(model:RegAssociationViewModel= viewModel()){ + BaseTextField(form = model.name,singeLine = true,modifier = Modifier.fillMaxWidth()) + } -/** - * 菜单标题 - * - */ -@Composable -private fun Title(model:RegAssociationViewModel= viewModel()){ - Row(modifier = Modifier.fillMaxWidth(),horizontalArrangement = Arrangement.Center) { - Text(text = model.frameDesc,style = MaterialTheme.typography.h4) + /** + * 社团简介 + * @param model + */ + @Composable + private fun Desc(model:RegAssociationViewModel= viewModel(),modifier:Modifier){ + BaseTextField(form = model.desc,modifier = modifier) } -} -/** - * 社团名称 - * @param model - */ -@Composable -private fun Name(model:RegAssociationViewModel= viewModel()){ - BaseTextField(form = model.name,singeLine = true,modifier = Modifier.fillMaxWidth()) } -/** - * 社团简介 - * @param model - */ -@Composable -private fun Desc(model:RegAssociationViewModel= viewModel(),modifier:Modifier){ - BaseTextField(form = model.desc,modifier = modifier) -} diff --git a/app/src/main/java/com/gyf/csams/main/model/MainViewModel.kt b/app/src/main/java/com/gyf/csams/main/model/MainViewModel.kt index 4495312..fbfbafd 100644 --- a/app/src/main/java/com/gyf/csams/main/model/MainViewModel.kt +++ b/app/src/main/java/com/gyf/csams/main/model/MainViewModel.kt @@ -4,6 +4,7 @@ import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope +import com.gyf.csams.NOT_IMPL_TIP import com.gyf.csams.R import com.gyf.csams.uikit.ScrollList import com.gyf.csams.uikit.StringForm @@ -85,7 +86,7 @@ class MainViewModel:ViewModel(){ * */ fun sendMessage(callback: (value: String) -> Unit){ - callback("功能尚未实现,敬请期待") + callback(NOT_IMPL_TIP) } /** @@ -94,7 +95,7 @@ class MainViewModel:ViewModel(){ * @param callback */ fun openNotification(callback: (value: String) -> Unit){ - callback("功能尚未实现,敬请期待") + callback(NOT_IMPL_TIP) } } @@ -125,7 +126,7 @@ class ListViewModel: ScrollList() { */ fun search(callback: (value: String) -> Unit){ Logger.i("搜索条件[社团名称:${name.formValue.value},社团简介:${desc.formValue.value}]") - callback("功能尚未实现,敬请期待") + callback(NOT_IMPL_TIP) } override val initSize: Int = 10 diff --git a/app/src/main/java/com/gyf/csams/main/ui/MainActivity.kt b/app/src/main/java/com/gyf/csams/main/ui/MainActivity.kt index 5581691..949a4a9 100644 --- a/app/src/main/java/com/gyf/csams/main/ui/MainActivity.kt +++ b/app/src/main/java/com/gyf/csams/main/ui/MainActivity.kt @@ -32,6 +32,7 @@ import com.gyf.csams.association.ui.RegAssociationActivity import com.gyf.csams.main.model.* import com.gyf.csams.uikit.* import com.gyf.csams.uikit.theme.CSAMSTheme +import com.gyf.csams.util.randomChinese /** @@ -66,328 +67,331 @@ class MainActivity : ComponentActivity() { } -} -/** - * 个人中心 - * - */ -@Composable -private fun Center(model:CenterViewModel= viewModel(), scaffoldModel: ScaffoldModel= viewModel(), navController: NavHostController){ - MainFrame(background = { Background(image = BackgroundImage.center,alpha = 0.5F) }, mainMenu = MainMenu.Center, nav = navController) { - Column(modifier = Modifier - .weight(0.33F) - .fillMaxWidth(),verticalArrangement = Arrangement.Bottom) { - Card(backgroundColor = MaterialTheme.colors.background) { - val context= LocalContext.current - Row(modifier = Modifier - .fillMaxWidth() - .clickable(onClick = { - context.startActivity(Intent(context, AssociationActivity::class.java)) - }),verticalAlignment = Alignment.CenterVertically) { - Spacer(modifier = Modifier.weight(0.33F)) - Row(modifier = Modifier.weight(0.33F),horizontalArrangement = Arrangement.Center) { - Text(text = model.myAssociationDesc) - } - Row(modifier = Modifier.weight(0.33F),horizontalArrangement = Arrangement.End) { - Icon( - painter = painterResource(id = R.drawable.ic_arrow_right), - contentDescription = null, - modifier = Modifier.size(50.dp) - ) + /** + * 个人中心 + * + */ + @Composable + private fun Center(model:CenterViewModel= viewModel(), scaffoldModel: ScaffoldModel= viewModel(), navController: NavHostController){ + MainFrame(background = { Background(image = BackgroundImage.Center,alpha = 0.5F) }, mainMenu = MainMenu.Center, nav = navController) { + Column(modifier = Modifier + .weight(0.33F) + .fillMaxWidth(),verticalArrangement = Arrangement.Bottom) { + Card(backgroundColor = MaterialTheme.colors.background) { + val context= LocalContext.current + Row(modifier = Modifier + .fillMaxWidth() + .clickable(onClick = { + context.startActivity(Intent(context, AssociationActivity::class.java)) + }),verticalAlignment = Alignment.CenterVertically) { + Spacer(modifier = Modifier.weight(0.33F)) + Row(modifier = Modifier.weight(0.33F),horizontalArrangement = Arrangement.Center) { + Text(text = model.myAssociationDesc) + } + Row(modifier = Modifier.weight(0.33F),horizontalArrangement = Arrangement.End) { + Icon( + painter = painterResource(id = R.drawable.ic_arrow_right), + contentDescription = null, + modifier = Modifier.size(50.dp) + ) + } } - } + } } + Spacer(modifier = Modifier + .weight(0.66F) + .fillMaxWidth()) } - Spacer(modifier = Modifier - .weight(0.66F) - .fillMaxWidth()) } -} -/** - * 主界面 - */ -@Composable -private fun Main(navController: NavHostController) { - MainFrame(background = { Background(image = BackgroundImage.main) }, mainMenu = MainMenu.Main, nav = navController) { - Column(modifier = Modifier.weight(0.33F)) { - Notification() - MessageBoard() - Spacer(modifier = Modifier.height(10.dp)) - ClubActivitiesTitle() - Spacer(modifier = Modifier.height(10.dp)) - } - Column(modifier = Modifier.weight(0.66F)) { - PosterWithDesc() + /** + * 主界面 + */ + @Composable + private fun Main(navController: NavHostController) { + MainFrame(background = { Background(image = BackgroundImage.Main) }, mainMenu = MainMenu.Main, nav = navController) { + Column(modifier = Modifier.weight(0.33F)) { + Notification() + MessageBoard() + Spacer(modifier = Modifier.height(10.dp)) + ClubActivitiesTitle() + Spacer(modifier = Modifier.height(10.dp)) + } + Column(modifier = Modifier.weight(0.66F)) { + PosterWithDesc() + } } } -} -/** - * 社团列表 - * - * @param navController - */ -@Composable -private fun AssociationList(navController: NavHostController) { - MainFrame( - background = { Background(image = BackgroundImage.list) }, - mainMenu = MainMenu.List, - nav = navController - ) { - RegisterAssociation() - AssociationSearch() - AssociationListBody() + /** + * 社团列表 + * + * @param navController + */ + @Composable + private fun AssociationList(navController: NavHostController) { + MainFrame( + background = { Background(image = BackgroundImage.AssociationList) }, + mainMenu = MainMenu.List, + nav = navController + ) { + RegisterAssociation() + AssociationSearch() + AssociationListBody() + } } -} -/** - * 注册社团按钮 - * - */ -@Composable -private fun RegisterAssociation() { - val context= LocalContext.current - Row( - horizontalArrangement = Arrangement.End, - modifier = Modifier - .fillMaxWidth() - .padding(10.dp) - ) { - IconButton(onClick = { - context.startActivity(Intent(context, RegAssociationActivity::class.java)) - }) { - Icon( - painter = painterResource(id = R.drawable.ic_add_fill), - contentDescription = null, - modifier = Modifier.size(50.dp), - ) + /** + * 注册社团按钮 + * + */ + @Composable + private fun RegisterAssociation() { + val context= LocalContext.current + Row( + horizontalArrangement = Arrangement.End, + modifier = Modifier + .fillMaxWidth() + .padding(10.dp) + ) { + IconButton(onClick = { + context.startActivity(Intent(context, RegAssociationActivity::class.java)) + }) { + Icon( + painter = painterResource(id = R.drawable.ic_add_fill), + contentDescription = null, + modifier = Modifier.size(50.dp), + ) + } } } -} -/** - * 社团列表 - * - */ -@Composable -private fun AssociationListBody(model: ListViewModel = viewModel(),scaffoldModel: ScaffoldModel= viewModel()) { - val associationList: MutableList? by model.associationDto.observeAsState() - val listState = rememberLazyListState() - - LazyColumn(state = listState) { - associationList?.chunked(2)?.forEach { - item{ - Row { - Spacer(modifier = Modifier.weight(0.1F)) - Box(modifier = Modifier.weight(0.35F)) { - Association(associationDto = it[0]) - } - Spacer(modifier = Modifier.weight(0.05F)) - if(it.size==2) { + /** + * 社团列表 + * + */ + @Composable + private fun AssociationListBody(model: ListViewModel = viewModel(),scaffoldModel: ScaffoldModel= viewModel()) { + val associationList: MutableList? by model.associationDto.observeAsState() + val listState = rememberLazyListState() + + LazyColumn(state = listState) { + associationList?.chunked(2)?.forEach { + item{ + Row { + Spacer(modifier = Modifier.weight(0.1F)) Box(modifier = Modifier.weight(0.35F)) { - Association(associationDto = it[1]) + Association(associationDto = it[0]) } - }else{ - Box(modifier = Modifier - .weight(0.35F) - .border(width = 1.dp, color = MaterialTheme.colors.onBackground)) + Spacer(modifier = Modifier.weight(0.05F)) + if(it.size==2) { + Box(modifier = Modifier.weight(0.35F)) { + Association(associationDto = it[1]) + } + }else{ + Box(modifier = Modifier + .weight(0.35F) + .border(width = 1.dp, color = MaterialTheme.colors.onBackground)) + } + Spacer(modifier = Modifier.weight(0.1F)) } - Spacer(modifier = Modifier.weight(0.1F)) + Spacer(modifier = Modifier + .fillMaxWidth() + .height(10.dp)) } - Spacer(modifier = Modifier - .fillMaxWidth() - .height(10.dp)) } } - } - if(listState.layoutInfo.totalItemsCount-listState.firstVisibleItemIndex==model.associationListSize/2-1){ - model.loadMore { scaffoldModel.update(message=it) } + if(listState.layoutInfo.totalItemsCount-listState.firstVisibleItemIndex==model.associationListSize/2-1){ + model.loadMore { scaffoldModel.update(message=it) } + } } -} -@Composable -private fun Association(associationDto: AssociationDto) { - val context= LocalContext.current - Card(modifier = Modifier.clickable(onClick = { context.startActivity(Intent(context,AssociationActivity::class.java)) })) { - Image( - painter = painterResource(id = R.drawable.association_list_border), - contentDescription = null - ) - Row(modifier = Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.Center) { - Text(text = associationDto.name) + @Composable + private fun Association(associationDto: AssociationDto) { + val context= LocalContext.current + Card(modifier = Modifier.clickable(onClick = { context.startActivity(Intent(context,AssociationActivity::class.java)) })) { + Image( + painter = painterResource(id = R.drawable.association_list_border), + contentDescription = null + ) + Row(modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.Center) { + Text(text = associationDto.name) + } + } } -} - -/** - * 社团检索 - * - */ -@Composable -private fun AssociationSearch(model: ListViewModel = viewModel(),scaffoldModel: ScaffoldModel= viewModel()) { + /** + * 社团检索 + * + */ + @Composable + private fun AssociationSearch(model: ListViewModel = viewModel(),scaffoldModel: ScaffoldModel= viewModel()) { - Card(modifier = Modifier.padding(horizontal = 50.dp, vertical = 10.dp)) { - Column { + Card(modifier = Modifier.padding(horizontal = 50.dp, vertical = 10.dp)) { + Column { - BaseTextField(form = model.name,singeLine = true,modifier = Modifier.padding(horizontal = 10.dp)) - BaseTextField(form = model.desc,singeLine = true,modifier = Modifier.padding(horizontal = 10.dp)) - Spacer( - modifier = Modifier.height(10.dp) - ) - Row(horizontalArrangement = Arrangement.Center, modifier = Modifier.fillMaxWidth()) { - OutlinedButton(onClick = { model.search { scaffoldModel.update(message=it) } }, modifier = Modifier.width(100.dp)) { - Text(text = model.searchDesc) + BaseTextField(form = model.name,singeLine = true,modifier = Modifier.padding(horizontal = 10.dp)) + BaseTextField(form = model.desc,singeLine = true,modifier = Modifier.padding(horizontal = 10.dp)) + Spacer( + modifier = Modifier.height(10.dp) + ) + Row(horizontalArrangement = Arrangement.Center, modifier = Modifier.fillMaxWidth()) { + OutlinedButton(onClick = { model.search { scaffoldModel.update(message=it) } }, modifier = Modifier.width(100.dp)) { + Text(text = model.searchDesc) + } } + Spacer( + modifier = Modifier.height(10.dp) + ) } - Spacer( - modifier = Modifier.height(10.dp) - ) + } } -} + /** + * 通知 + * + */ + @Composable + private fun Notification(mainViewModel: MainViewModel= viewModel(),scaffoldModel: ScaffoldModel= viewModel()) { + Row( + horizontalArrangement = Arrangement.End, + modifier = Modifier + .fillMaxWidth() + .padding(10.dp) + ) { + IconButton(onClick = { + mainViewModel.openNotification { scaffoldModel.update(message=it) } + }) { + Icon( + painter = painterResource(id = R.drawable.ic_notification), + contentDescription = null + ) + } -/** - * 通知 - * - */ -@Composable -private fun Notification(mainViewModel: MainViewModel= viewModel(),scaffoldModel: ScaffoldModel= viewModel()) { - Row( - horizontalArrangement = Arrangement.End, - modifier = Modifier - .fillMaxWidth() - .padding(10.dp) - ) { - IconButton(onClick = { - mainViewModel.openNotification { scaffoldModel.update(message=it) } - }) { - Icon( - painter = painterResource(id = R.drawable.ic_notification), - contentDescription = null - ) } - } -} -/** - * 圆角矩形边框 - * - */ -@Composable -private fun MyBorder(content: @Composable BoxScope.() -> Unit) { - Box(modifier = Modifier.padding(horizontal = 15.dp)) { - Box( - modifier = Modifier - .border( - width = 1.dp, - color = MaterialTheme.colors.onBackground, - shape = RoundedCornerShape(size = 20.dp) - ), - ) { - content() + /** + * 圆角矩形边框 + * + */ + @Composable + private fun MyBorder(content: @Composable BoxScope.() -> Unit) { + Box(modifier = Modifier.padding(horizontal = 15.dp)) { + Box( + modifier = Modifier + .border( + width = 1.dp, + color = MaterialTheme.colors.onBackground, + shape = RoundedCornerShape(size = 20.dp) + ), + ) { + content() + } } } -} -/** - * 留言板 - * - */ -@Composable -private fun MessageBoard(model: MarqueeViewModel = viewModel(),mainViewModel:MainViewModel= viewModel(),scaffoldModel: ScaffoldModel= viewModel()) { - MyBorder { - Row( - verticalAlignment = Alignment.CenterVertically - ) { + /** + * 留言板 + * + */ + @Composable + private fun MessageBoard(model: MarqueeViewModel = viewModel(),mainViewModel:MainViewModel= viewModel(),scaffoldModel: ScaffoldModel= viewModel()) { + MyBorder { + Row( + verticalAlignment = Alignment.CenterVertically + ) { - IconButton(onClick = { mainViewModel.sendMessage { scaffoldModel.update(message=it) } }) { - Icon( - painter = painterResource(id = R.drawable.ic_comments), - contentDescription = null, - ) + IconButton(onClick = { mainViewModel.sendMessage { scaffoldModel.update(message=it) } }) { + Icon( + painter = painterResource(id = R.drawable.ic_comments), + contentDescription = null, + ) + } + Row( + horizontalArrangement = Arrangement.Center, + modifier = Modifier + .fillMaxWidth() + ) { + Marquee(model = model) { model, value -> + MarqueeText( + model = model, + offset = value + ) + } + } + } + } + } + + /** + * 活动标题 + * + */ + @Composable + private fun ClubActivitiesTitle() { + MyBorder { Row( - horizontalArrangement = Arrangement.Center, modifier = Modifier .fillMaxWidth() + .height(50.dp), + horizontalArrangement = Arrangement.Center, + verticalAlignment = Alignment.CenterVertically ) { - Marquee(model = model) { model, value -> - MarqueeText( - model = model, - offset = value - ) - } + Text( + text = "超级课程表X滴滴出行-了不起的社团", + style = MaterialTheme.typography.h6, + overflow = TextOverflow.Ellipsis, + maxLines = 1 + ) } - } } -} -/** - * 活动标题 - * - */ -@Composable -private 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 + private fun PosterWithDesc(model: CarouselViewModel = viewModel()) { + Carousel(model = model) { + Column { + Poster(modifier = Modifier + .weight(0.6F) + .fillMaxWidth(),id = it) + DescCard( + modifier = Modifier + .weight(0.4F) + .fillMaxWidth(), + content = randomChinese(500) + ) + } } } -} -/** - * 带介绍活动海报 - * - */ -@Composable -private fun PosterWithDesc(model: CarouselViewModel = viewModel()) { - Carousel(model = model) { - Column { - Poster(modifier = Modifier - .weight(0.6F) - .fillMaxWidth(),id = it) - DescCard( - modifier = Modifier - .weight(0.4F) - .fillMaxWidth() - ) + @Preview(showBackground = true) + @Composable + fun DefaultPreview() { + CSAMSTheme { + Text(text = "666") } } } -@Preview(showBackground = true) -@Composable -fun DefaultPreview() { - CSAMSTheme { - Text(text = "666") - } -} diff --git a/app/src/main/java/com/gyf/csams/uikit/BaseView.kt b/app/src/main/java/com/gyf/csams/uikit/BaseView.kt index eb05fab..458e602 100644 --- a/app/src/main/java/com/gyf/csams/uikit/BaseView.kt +++ b/app/src/main/java/com/gyf/csams/uikit/BaseView.kt @@ -1,19 +1,18 @@ package com.gyf.csams.uikit +import android.app.Activity import androidx.annotation.DrawableRes import androidx.compose.animation.Crossfade import androidx.compose.animation.animateColor import androidx.compose.animation.core.* import androidx.compose.foundation.Image +import androidx.compose.foundation.border import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.* import androidx.compose.foundation.text.KeyboardActions import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.material.* -import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.State -import androidx.compose.runtime.getValue +import androidx.compose.runtime.* import androidx.compose.runtime.livedata.observeAsState import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier @@ -27,6 +26,8 @@ import androidx.compose.ui.text.input.ImeAction import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData import androidx.lifecycle.viewmodel.compose.viewModel import androidx.navigation.NavHostController import androidx.navigation.compose.navigate @@ -35,7 +36,6 @@ import com.gyf.csams.APP import com.gyf.csams.R import com.gyf.csams.main.model.CarouselViewModel import com.gyf.csams.main.model.MarqueeViewModel -import com.gyf.csams.uikit.theme.CSAMSTheme import com.orhanobut.logger.Logger import kotlinx.coroutines.launch @@ -90,7 +90,7 @@ enum class MainMenu( * @param onClick */ @Composable -fun MenuIconButton(_menu: MainMenu, menu: MainMenu, modifier: Modifier, onClick: () -> Unit) { +fun MenuIconButton(_menu: MainMenu, menu: MainMenu, modifier: Modifier=Modifier, onClick: () -> Unit) { Row( modifier = modifier, horizontalArrangement = Arrangement.Center ) { @@ -113,30 +113,74 @@ fun MenuIconButton(_menu: MainMenu, menu: MainMenu, modifier: Modifier, onClick: @Composable fun MainBottomAppBar(menu: MainMenu, nav: NavHostController, modifier: Modifier = Modifier) { BottomAppBar(backgroundColor = MaterialTheme.colors.background, modifier = modifier) { - //图标宽度平等分 - - val weight = 1 / (MainMenu.values().size * 1.0f) - - Row(Modifier.fillMaxWidth()) { - MenuIconButton(_menu = menu, menu = MainMenu.Main, Modifier.weight(weight), + Row(Modifier.fillMaxWidth(),horizontalArrangement = Arrangement.SpaceBetween) { + MenuIconButton(_menu = menu, menu = MainMenu.Main, onClick = { nav.navigate(MainMenu.Main.name) }) - MenuIconButton(_menu = menu, menu = MainMenu.List, Modifier.weight(weight), + MenuIconButton(_menu = menu, menu = MainMenu.List, onClick = { nav.navigate(MainMenu.List.name) }) - MenuIconButton(_menu = menu, menu = MainMenu.Center, Modifier.weight(weight), + MenuIconButton(_menu = menu, menu = MainMenu.Center, onClick = { nav.navigate(MainMenu.Center.name) }) } } } + +/** + * 顶部菜单 + * + */ +interface TopMenuInterface{ + /** + * 当前菜单 + */ + val _currentMenu: MutableLiveData + val currentMenu: LiveData + + /** + * 切换顶部菜单 + * + * @param menu + */ + fun clickMenu(menu:T){ + _currentMenu.value=menu + } +} + +interface TopBarMenu{ + val menuName:String + + val name:String +} + + +interface StartMenu{ + val startMenu:T +} + /** * 社团菜单 * */ -enum class AssociationMenu(val menuName: String) { - member("社团成员"), - main("社团主页"), - list("活动列表") +enum class AssociationMenu(override val menuName: String):TopBarMenu { + Member("社团成员"), + Main("社团主页"), + ActivityList("活动列表"); + + companion object Menu:StartMenu{ + override val startMenu: AssociationMenu = Main + } +} + +enum class ActivityDetailMenu(override val menuName:String):TopBarMenu{ + Info("活动信息"), + Photo("相册"), + Member("活动成员"), + BBS("交流区"); + + companion object Menu:StartMenu{ + override val startMenu: ActivityDetailMenu = Info + } } /** @@ -144,51 +188,56 @@ enum class AssociationMenu(val menuName: String) { * */ @Composable -fun AssociationAppBar( - menu: AssociationMenu, - nav: NavHostController, - back: () -> Unit, - dropMenu: () -> Unit, - content:@Composable () -> Unit +fun TextTopAppBar( + nav:NavHostController, + currentMenuName:String, + menuNames:Array, + iconMenu: (() -> Unit)? = null, + @DrawableRes icon:Int = R.drawable.ic_configuration, + dropMenuContent:@Composable () -> Unit = {}, ) { TopAppBar(backgroundColor = MaterialTheme.colors.secondary) { - Row(modifier = Modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically) { - IconButton(onClick = back, modifier = Modifier.weight(0.1F)) { - Icon( - painter = painterResource(id = R.drawable.ic_arrow_left), - contentDescription = null - ) - } - Row( - modifier = Modifier - .weight(0.8F) - .fillMaxHeight(), - horizontalArrangement = Arrangement.Center, - verticalAlignment = Alignment.CenterVertically - ) { - val menus = AssociationMenu.values() - menus.forEach { - Row( - modifier = Modifier - .weight(1F / menus.size) - .clickable(onClick = { nav.navigate(it.name) }), - horizontalArrangement = Arrangement.Center - ) { - Text( - text = it.menuName, - color = if (menu == it) MaterialTheme.colors.primary else MaterialTheme.colors.onBackground - ) - } + Row(modifier = Modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically) { + val context= LocalContext.current as Activity + IconButton(onClick = {context.onBackPressed()}, modifier = Modifier.weight(0.1F)) { + Icon( + painter = painterResource(id = R.drawable.ic_arrow_left), + contentDescription = null + ) + } + Row( + modifier = Modifier + .weight(0.8F) + .fillMaxHeight(), + horizontalArrangement = Arrangement.SpaceAround, + verticalAlignment = Alignment.CenterVertically + ) { + menuNames.forEach { + Row( + modifier = Modifier + .weight(1F / menuNames.size) + .clickable(onClick = { nav.navigate(it.name) }), + horizontalArrangement = Arrangement.Center + ) { + Text( + text = it.menuName, + color = if (currentMenuName == it.menuName) MaterialTheme.colors.primary else MaterialTheme.colors.onBackground + ) } } - IconButton(onClick = dropMenu, modifier = Modifier.weight(0.1F)) { + } + if(iconMenu!=null) { + IconButton(onClick = iconMenu, modifier = Modifier.weight(0.1F)) { Icon( - painter = painterResource(id = R.drawable.ic_configuration), + painter = painterResource(id = icon), contentDescription = null ) } + }else{ + Spacer(modifier = Modifier.weight(0.1F)) } - content() + } + if(iconMenu!=null) dropMenuContent() } } @@ -383,26 +432,34 @@ fun ShowSnackbar(model: ScaffoldModel = viewModel(), scaffoldState: ScaffoldStat */ enum class BackgroundImage(@DrawableRes val id: Int) { //主页 - main(R.drawable.mb_bg_fb_08), + Main(R.drawable.mb_bg_fb_08), //社团列表 - list(R.drawable.mb_bg_fb_07), + AssociationList(R.drawable.mb_bg_fb_07), //个人中心 - center(R.drawable.mb_bg_fb_28), + Center(R.drawable.mb_bg_fb_28), //注册社团 - reg_association(R.drawable.mb_bg_fb_06), + RegAssociation(R.drawable.mb_bg_fb_06), //社团主界面 - association_main(R.drawable.mb_bg_fb_25_180), + AssociationMain(R.drawable.mb_bg_fb_25_180), //社团重命名 - rename(R.drawable.mb_bg_fb_27), + Rename(R.drawable.mb_bg_fb_27), //社团题库管理 - exam(R.drawable.mb_bg_fb_02) - + Exam(R.drawable.mb_bg_fb_09), + + //活动信息 + ActivityInfo(R.drawable.mb_bg_fb_01), + //活动相册 + ActivityPhoto(R.drawable.mb_bg_fb_02), + //活动成员 + ActivityMember(R.drawable.mb_bg_fb_03), + //交流区 + ActivityBBS(R.drawable.mb_bg_fb_04) } /** @@ -493,47 +550,78 @@ fun Poster(modifier: Modifier = Modifier, @DrawableRes id: Int) { * */ @Composable -fun DescCard(modifier: Modifier) { +fun DescCard(modifier: Modifier,content:String) { Card( modifier = modifier, backgroundColor = Color.Transparent ) { - Image( - painter = painterResource(id = R.drawable.hot_activity_desc_background), - contentDescription = null - ) - - Row(modifier = Modifier.fillMaxWidth()) { - Spacer(modifier = Modifier.weight(0.2F)) - Column( - modifier = Modifier - .weight(0.5F) - ) { - Spacer(modifier = Modifier.weight(0.1F)) + Box { + Image( + painter = painterResource(id = R.drawable.hot_activity_desc_background), + contentDescription = null, + contentScale = ContentScale.FillBounds, + modifier = Modifier.fillMaxSize() + ) + Column(modifier = Modifier.fillMaxSize().padding(horizontal = 10.dp)) { + Spacer(modifier = Modifier.weight(0.15F)) Text( - text = "文字对任何界面都属于核心内容,而利用 Jetpack Compose 可以更轻松地显示或写入文字。Compose 可以充分利用其构建块的组合,这意味着您无需覆盖各种属性和方法,也无需扩展大型类,即可拥有特定的可组合项设计以及按您期望的方式运行的逻辑。" - .repeat(10), overflow = TextOverflow.Ellipsis, - modifier = Modifier.weight(0.8F) + modifier = Modifier.weight(0.65F), + text = content, + overflow = TextOverflow.Ellipsis ) - Spacer(modifier = Modifier.weight(0.1F)) + Spacer(modifier = Modifier.weight(0.15F)) } - Spacer(modifier = Modifier.weight(0.2F)) } } } - -@Preview +//@Preview @Composable fun AnimationTextPreview() { AnimationText(text = "6666") } -//@Preview +@Preview @Composable fun MyBottomAppBarPreview() { - CSAMSTheme { - + val arr:List = listOf( + Arrangement.Start, + Arrangement.End, + Arrangement.Center, + Arrangement.SpaceBetween, + Arrangement.SpaceAround, + Arrangement.SpaceEvenly + ) + var i by remember { + mutableStateOf(3) + } + Column(modifier = Modifier.fillMaxSize()) { + Row(modifier = Modifier.fillMaxWidth(),horizontalArrangement = Arrangement.SpaceEvenly) { + OutlinedButton(onClick = { i += 1 }) { + Text(text = "添加元素") + } + if(i>1) { + OutlinedButton(onClick = { i -= 1 }) { + Text(text = "删除元素") + } + } + } + arr.forEach { + Column(modifier = Modifier + .weight(1F / arr.size) + .border(width = 1.dp, color = MaterialTheme.colors.background)) { + Row(modifier = Modifier.fillMaxWidth(),horizontalArrangement = Arrangement.Center) { + Text(text = "$it",style = MaterialTheme.typography.h5) + } + Row(modifier = Modifier.fillMaxSize(), + horizontalArrangement = it, + verticalAlignment = Alignment.CenterVertically) { + repeat(i) { + Text(text = "$it", style = MaterialTheme.typography.h3) + } + } + } + } } } \ No newline at end of file diff --git a/app/src/main/java/com/gyf/csams/util/RandomUtil.kt b/app/src/main/java/com/gyf/csams/util/RandomUtil.kt new file mode 100644 index 0000000..cc9deb4 --- /dev/null +++ b/app/src/main/java/com/gyf/csams/util/RandomUtil.kt @@ -0,0 +1,55 @@ +package com.gyf.csams.util + +import okhttp3.internal.toHexString +import java.text.SimpleDateFormat +import java.util.* + +fun randomNum(length:Int=8):String{ + return List(length) {('0' .. '9').random()}.joinToString("") +} + + +fun encode(char: Char) = "\\u${char.toInt().toHexString()}" + +//String ->unicode +fun String.encodeUnicode(text: String) = text + .toCharArray().joinToString(separator = "", truncated = "") { encode(it) } + +//unicode ->String +fun String.decodeUnicode(): String { + fun decode1(unicode: String) = unicode.toInt(16).toChar() + val unicodes = this.split("\\u").mapNotNull { if (it.isNotBlank()) decode1(it) else null } + return String(unicodes.toCharArray()) +} + +val CHINESE_UNICODE_AREA=0X4e00..0X9fa5 + +/** + * 随机中文 + * + * @param length + * @return + */ +fun randomChinese(length:Int=8):String{ + return List(length){ "\\u${CHINESE_UNICODE_AREA.random().toHexString()}".decodeUnicode() }.joinToString("") +} + +const val DATETIME_FORMAT="yyyy-MM-dd HH:mm" + +const val START_TIME="2021-01-01 00:00" + +val FORMAT=SimpleDateFormat(DATETIME_FORMAT,Locale.US) + +val startUnix= FORMAT.parse(START_TIME)?.time + +fun randomDateTime():Date{ + if (startUnix != null) { + return Date("${(startUnix..Date().time).random()}".toLong()) + }else{ + throw IllegalArgumentException("生成随机失败,无法获取起始时间") + } +} + +fun Date.format():String{ + return FORMAT.format(this) +} diff --git a/app/src/main/res/drawable/ic_upload.xml b/app/src/main/res/drawable/ic_upload.xml new file mode 100644 index 0000000..1f1fda5 --- /dev/null +++ b/app/src/main/res/drawable/ic_upload.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/test/java/com/gyf/csams/ExampleUnitTest.kt b/app/src/test/java/com/gyf/csams/ExampleUnitTest.kt index df62de0..83bf7f9 100644 --- a/app/src/test/java/com/gyf/csams/ExampleUnitTest.kt +++ b/app/src/test/java/com/gyf/csams/ExampleUnitTest.kt @@ -3,6 +3,7 @@ package com.gyf.csams import com.google.gson.Gson import com.google.gson.reflect.TypeToken import com.gyf.csams.util.ApiResponse +import com.gyf.csams.util.randomChinese import org.junit.Assert.assertEquals import org.junit.Test @@ -32,16 +33,16 @@ class ExampleUnitTest { println(e.body) } - @Test - fun testYear(){ - repeat(10,{ - println(it) - }) - } + @Test fun testCharRange(){ - println(('A'..'D').map { "选项$it" }) + repeat(100){ + println(randomChinese()) + } + +// println(java.time.format.DateTimeFormatter.ISO_INSTANT +// .format(java.time.Instant.ofEpochMilli(1532358895000))) } }