增加活动详情界面

master
pan 4 years ago
parent 31e1d9fd92
commit 4ee124d927
  1. 2
      app/src/androidTest/java/com/gyf/csams/ExampleInstrumentedTest.kt
  2. 9
      app/src/androidTest/java/com/gyf/csams/MainActivityTest.kt
  3. 5
      app/src/main/AndroidManifest.xml
  4. 13
      app/src/main/java/com/gyf/csams/Api.kt
  5. 3
      app/src/main/java/com/gyf/csams/InitActivity.kt
  6. 290
      app/src/main/java/com/gyf/csams/activity/model/ActivityDetailViewModel.kt
  7. 491
      app/src/main/java/com/gyf/csams/activity/ui/ActivityDetailActivity.kt
  8. 26
      app/src/main/java/com/gyf/csams/association/model/AssociationViewModel.kt
  9. 7
      app/src/main/java/com/gyf/csams/association/model/ExamViewModel.kt
  10. 3
      app/src/main/java/com/gyf/csams/association/model/RegAssociationViewModel.kt
  11. 3
      app/src/main/java/com/gyf/csams/association/model/RenameViewModel.kt
  12. 44
      app/src/main/java/com/gyf/csams/association/ui/AssociationActivity.kt
  13. 5
      app/src/main/java/com/gyf/csams/association/ui/ExamActivity.kt
  14. 4
      app/src/main/java/com/gyf/csams/association/ui/ReNameActivity.kt
  15. 6
      app/src/main/java/com/gyf/csams/association/ui/RegAssociationActivity.kt
  16. 7
      app/src/main/java/com/gyf/csams/main/model/MainViewModel.kt
  17. 14
      app/src/main/java/com/gyf/csams/main/ui/MainActivity.kt
  18. 206
      app/src/main/java/com/gyf/csams/uikit/BaseView.kt
  19. 55
      app/src/main/java/com/gyf/csams/util/RandomUtil.kt
  20. 9
      app/src/main/res/drawable/ic_upload.xml
  21. 15
      app/src/test/java/com/gyf/csams/ExampleUnitTest.kt

@ -18,7 +18,5 @@ class ExampleInstrumentedTest {
// Context of the app under test. // Context of the app under test.
val appContext = InstrumentationRegistry.getInstrumentation().targetContext val appContext = InstrumentationRegistry.getInstrumentation().targetContext
assertEquals("com.gyf.csams", appContext.packageName) assertEquals("com.gyf.csams", appContext.packageName)
} }
} }

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

@ -62,6 +62,11 @@
<activity android:name=".association.ui.ExamActivity" <activity android:name=".association.ui.ExamActivity"
android:exported="true"> android:exported="true">
</activity> </activity>
<!--活动详情-->
<activity android:name=".activity.ui.ActivityDetailActivity"
android:exported="true">
</activity>
</application> </application>
</manifest> </manifest>

@ -5,6 +5,11 @@ interface UrlPath{
fun build():String fun build():String
} }
/**
* 帐号接口
*
* @property path
*/
enum class AccountApi(val path: String):UrlPath{ enum class AccountApi(val path: String):UrlPath{
register("/register"), register("/register"),
checkId("/register/checkId"), checkId("/register/checkId"),
@ -17,7 +22,10 @@ enum class AccountApi(val path: String):UrlPath{
} }
} }
/**
* 构建服务端请求接口地址
*
*/
class Api { class Api {
companion object{ companion object{
fun buildUrl(urlPath: UrlPath):String{ fun buildUrl(urlPath: UrlPath):String{
@ -26,3 +34,6 @@ class Api {
} }
} }
const val NOT_IMPL_TIP="功能尚未实现!"

@ -37,7 +37,7 @@ class InitActivity : ComponentActivity() {
} }
} }
} }
}
@Composable @Composable
private fun Init(initViewModel:InitViewModel= viewModel()){ private fun Init(initViewModel:InitViewModel= viewModel()){
@ -54,3 +54,4 @@ private fun Init(initViewModel:InitViewModel= viewModel()){
} }
} }
}

@ -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<ActivityDetailMenu> {
override val _currentMenu: MutableLiveData<ActivityDetailMenu> = MutableLiveData()
override val currentMenu: LiveData<ActivityDetailMenu> = _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<ActivityDetailVo>()
val activityDetailVo:LiveData<ActivityDetailVo> = _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<ActivityPhotoVo>(){
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<ActivityPhotoVo>()
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<ActivityMemberVo>?)
class ActivityMemberViewModel:ScrollList<ActivityMemberVo>(){
override val initSize: Int = 10
private val _allMember=MutableLiveData<ActivityMembersVo>()
val allMember:LiveData<ActivityMembersVo> = _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<ActivityMemberVo>()
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<BBSVo>(){
override val initSize: Int = 10
val title="发送评论"
val newContent = StringForm(formDesc = "评论内容",textLength = 80)
private val _openDialog=MutableLiveData<Boolean>()
val openDialog:LiveData<Boolean> = _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<BBSVo>()
list.addAll(this)
repeat(initSize){
add(BBSVo(studentId = randomNum(),name = randomChinese(3),createTime = randomDateTime(),content = randomChinese(50)))
}
_data.postValue(list)
callback("成功加载更多评论")
}
}
}
}
}

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

@ -4,18 +4,19 @@ import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import com.gyf.csams.NOT_IMPL_TIP
import com.gyf.csams.uikit.AssociationMenu import com.gyf.csams.uikit.AssociationMenu
import com.gyf.csams.uikit.ScrollList import com.gyf.csams.uikit.ScrollList
import com.gyf.csams.uikit.StringForm import com.gyf.csams.uikit.StringForm
import com.gyf.csams.uikit.TopMenuInterface
import com.orhanobut.logger.Logger import com.orhanobut.logger.Logger
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
class AssociationViewModel:ViewModel() {
/** class AssociationViewModel:ViewModel(),TopMenuInterface<AssociationMenu>{
* 当前菜单
*/ override val _currentMenu: MutableLiveData<AssociationMenu> = MutableLiveData()
private val _currentMenu=MutableLiveData<AssociationMenu>() override val currentMenu: LiveData<AssociationMenu> = _currentMenu
val currentMenu:LiveData<AssociationMenu> = _currentMenu
/** /**
* 下拉菜单状态 * 下拉菜单状态
@ -23,14 +24,7 @@ class AssociationViewModel:ViewModel() {
private val _expanded=MutableLiveData(false) private val _expanded=MutableLiveData(false)
val expanded:LiveData<Boolean> = _expanded val expanded:LiveData<Boolean> = _expanded
/**
* 切换顶部菜单
*
* @param menu
*/
fun clickMenu(menu:AssociationMenu){
_currentMenu.value=menu
}
/** /**
* 切换下拉菜单状态 * 切换下拉菜单状态
@ -113,7 +107,7 @@ class MemberViewModel:ScrollList<MemberVo>(){
*/ */
fun search(callback: (value: String) -> Unit){ fun search(callback: (value: String) -> Unit){
Logger.i("搜索条件[成员姓名:${name.formValue.value}]") Logger.i("搜索条件[成员姓名:${name.formValue.value}]")
callback("功能尚未实现,敬请期待") callback(NOT_IMPL_TIP)
} }
} }
@ -131,6 +125,7 @@ class HistoryActViewModel: ScrollList<HistoryActVo>() {
} }
override fun load() { override fun load() {
viewModelScope.launch {
_data.value?.apply { _data.value?.apply {
repeat(initSize){ repeat(initSize){
add(HistoryActVo(name = "活动${size+1}")) add(HistoryActVo(name = "活动${size+1}"))
@ -138,6 +133,7 @@ class HistoryActViewModel: ScrollList<HistoryActVo>() {
Logger.i("初始化活动数量:${size}") Logger.i("初始化活动数量:${size}")
} }
} }
}
override fun loadMore(callback:(message:String) -> Unit) { override fun loadMore(callback:(message:String) -> Unit) {
_data.value?.apply { _data.value?.apply {

@ -3,6 +3,7 @@ package com.gyf.csams.association.model
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import com.gyf.csams.NOT_IMPL_TIP
import com.gyf.csams.uikit.ScrollList import com.gyf.csams.uikit.ScrollList
import com.gyf.csams.uikit.StringForm import com.gyf.csams.uikit.StringForm
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@ -159,7 +160,7 @@ class ExamViewModel:ScrollList<Exam>() {
* @param callback * @param callback
*/ */
fun updateExam(callback: (message: String) -> Unit){ fun updateExam(callback: (message: String) -> Unit){
callback("功能尚未实现,敬请期待") callback(NOT_IMPL_TIP)
} }
/** /**
@ -168,7 +169,7 @@ class ExamViewModel:ScrollList<Exam>() {
* @param callback * @param callback
*/ */
fun postAnswer(callback: (message: String) -> Unit){ fun postAnswer(callback: (message: String) -> Unit){
callback("功能尚未实现,敬请期待") callback(NOT_IMPL_TIP)
} }
/** /**
@ -220,7 +221,7 @@ class ExamViewModel:ScrollList<Exam>() {
// callback("成功加载更多题目") // callback("成功加载更多题目")
// } // }
// callback("功能尚未实现,敬请期待") // callback(NOT_IMPL_TIP)
} }
fun addQuestion() { fun addQuestion() {

@ -4,6 +4,7 @@ import android.net.Uri
import androidx.lifecycle.LiveData import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import com.gyf.csams.NOT_IMPL_TIP
import com.gyf.csams.uikit.StringForm import com.gyf.csams.uikit.StringForm
@ -39,7 +40,7 @@ class RegAssociationViewModel : ViewModel() {
* @param callback * @param callback
*/ */
fun register(callback: (value: String) -> Unit){ fun register(callback: (value: String) -> Unit){
callback("功能尚未实现,敬请期待") callback(NOT_IMPL_TIP)
} }
} }

@ -1,6 +1,7 @@
package com.gyf.csams.association.model package com.gyf.csams.association.model
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import com.gyf.csams.NOT_IMPL_TIP
import com.gyf.csams.uikit.StringForm import com.gyf.csams.uikit.StringForm
/** /**
@ -22,6 +23,6 @@ class RenameViewModel:ViewModel() {
* *
*/ */
fun post(callback:(message:String) -> Unit){ fun post(callback:(message:String) -> Unit){
callback("功能尚未实现,敬请期待") callback(NOT_IMPL_TIP)
} }
} }

@ -19,7 +19,6 @@ import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.painterResource
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.DpOffset
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.PopupProperties import androidx.compose.ui.window.PopupProperties
import androidx.lifecycle.viewmodel.compose.viewModel 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.association.model.*
import com.gyf.csams.uikit.* import com.gyf.csams.uikit.*
import com.gyf.csams.uikit.theme.CSAMSTheme import com.gyf.csams.uikit.theme.CSAMSTheme
import com.gyf.csams.util.randomChinese
import com.orhanobut.logger.Logger import com.orhanobut.logger.Logger
/** /**
* 社团界面 * 社团界面
* *
@ -44,18 +46,20 @@ class AssociationActivity: ComponentActivity() {
nav, scaffoldState -> nav, scaffoldState ->
val context= LocalContext.current as AssociationActivity val context= LocalContext.current as AssociationActivity
val model:AssociationViewModel= viewModel() val model:AssociationViewModel= viewModel()
val startMenu=AssociationMenu.main val currentMenuName:AssociationMenu by model.currentMenu.observeAsState(AssociationMenu.startMenu)
val menu:AssociationMenu by model.currentMenu.observeAsState(startMenu)
val intent=Intent(context,ExamActivity::class.java) val intent=Intent(context,ExamActivity::class.java)
val expanded by model.expanded.observeAsState(false) val expanded by model.expanded.observeAsState(false)
Column { Column {
Logger.i("expanded=$expanded") 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{ Row{
DropdownMenu(expanded = expanded, DropdownMenu(expanded = expanded,
onDismissRequest = { /*TODO*/ }, onDismissRequest = { /*TODO*/ },
offset = DpOffset.Zero.copy(x=50.dp), // offset = DpOffset.Zero.copy(x=50.dp),
properties = PopupProperties() properties = PopupProperties()
) { ) {
DropdownMenuItem(onClick = { DropdownMenuItem(onClick = {
@ -111,22 +115,21 @@ class AssociationActivity: ComponentActivity() {
} }
} }
} }
} }
NavHost(navController = nav, startDestination = startMenu.name) { NavHost(navController = nav, startDestination = AssociationMenu.startMenu.name) {
composable(AssociationMenu.member.name){ composable(AssociationMenu.Member.name){
model.clickMenu(AssociationMenu.member) model.clickMenu(AssociationMenu.Member)
Member() Member()
ShowSnackbar(scaffoldState = scaffoldState) ShowSnackbar(scaffoldState = scaffoldState)
} }
composable(AssociationMenu.main.name){ composable(AssociationMenu.Main.name){
model.clickMenu(AssociationMenu.main) model.clickMenu(AssociationMenu.Main)
Main() Main()
ShowSnackbar(scaffoldState = scaffoldState) ShowSnackbar(scaffoldState = scaffoldState)
} }
composable(AssociationMenu.list.name){ composable(AssociationMenu.ActivityList.name){
model.clickMenu(AssociationMenu.list) model.clickMenu(AssociationMenu.ActivityList)
AssociationList() AssociationList()
ShowSnackbar(scaffoldState = scaffoldState) ShowSnackbar(scaffoldState = scaffoldState)
} }
@ -137,7 +140,7 @@ class AssociationActivity: ComponentActivity() {
} }
} }
} }
}
/** /**
* 社团成员 * 社团成员
@ -145,7 +148,7 @@ class AssociationActivity: ComponentActivity() {
*/ */
@Composable @Composable
private fun Member(){ private fun Member(){
MainFrame(background = { Background(image = BackgroundImage.association_main) }) { MainFrame(background = { Background(image = BackgroundImage.AssociationMain) }) {
val searchWeight=0.2F val searchWeight=0.2F
Search(modifier = Modifier Search(modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
@ -232,7 +235,7 @@ private fun MemberList(modifier: Modifier=Modifier, model: MemberViewModel=viewM
@Composable @Composable
private fun Main(){ private fun Main(){
MainFrame(background = { MainFrame(background = {
Background(image = BackgroundImage.association_main,alpha = 0.7F) Background(image = BackgroundImage.AssociationMain,alpha = 0.7F)
}) { }) {
val nameW=0.1F val nameW=0.1F
val cardW=0.66F*0.4F val cardW=0.66F*0.4F
@ -242,7 +245,8 @@ private fun Main(){
DescCard( DescCard(
modifier = Modifier modifier = Modifier
.weight(cardW) .weight(cardW)
.fillMaxWidth() .fillMaxWidth(),
content = randomChinese(500)
) )
Commander( Commander(
modifier = Modifier.weight(cardW) modifier = Modifier.weight(cardW)
@ -288,7 +292,7 @@ private fun Commander(modifier: Modifier){
Box(modifier=modifier,contentAlignment = Alignment.Center){ Box(modifier=modifier,contentAlignment = Alignment.Center){
Row(modifier = Modifier.fillMaxWidth(),horizontalArrangement = Arrangement.Center) { Row(modifier = Modifier.fillMaxWidth(),horizontalArrangement = Arrangement.Center) {
Image(painter = painterResource(id = R.drawable.association_persion_name_border), Image(painter = painterResource(id = R.drawable.persion_name_border),
contentDescription = null contentDescription = null
) )
} }
@ -317,7 +321,7 @@ private fun Showcase(modifier: Modifier){
*/ */
@Composable @Composable
private fun AssociationList(){ private fun AssociationList(){
MainFrame(background = { Background(image = BackgroundImage.association_main,alpha = 07F) }) { MainFrame(background = { Background(image = BackgroundImage.AssociationMain,alpha = 07F) }) {
val onGoWeight=0.3F val onGoWeight=0.3F
OngoingActivity(modifier = Modifier OngoingActivity(modifier = Modifier
.weight(onGoWeight) .weight(onGoWeight)
@ -397,5 +401,7 @@ private fun HistoryActivity(modifier: Modifier,historyActVo: HistoryActVo){
fun NamePreview(){ fun NamePreview(){
Divider(color = MaterialTheme.colors.background) Divider(color = MaterialTheme.colors.background)
} }
}

@ -39,7 +39,7 @@ class ExamActivity : ComponentActivity() {
setContent { setContent {
Body { scaffoldState -> Body { scaffoldState ->
MainFrame(background = { Background(image = BackgroundImage.exam) }) { MainFrame(background = { Background(image = BackgroundImage.Exam,alpha = 0.6F) }) {
Spacer(modifier = Modifier.weight(0.1F)) Spacer(modifier = Modifier.weight(0.1F))
Title(modifier = Modifier.weight(0.1F)) Title(modifier = Modifier.weight(0.1F))
Exam(modifier = Modifier.weight(0.8F)) Exam(modifier = Modifier.weight(0.8F))
@ -48,7 +48,7 @@ class ExamActivity : ComponentActivity() {
} }
} }
} }
}
@ -332,3 +332,4 @@ private fun ExamCQ(
} }
} }
}

@ -26,7 +26,7 @@ class ReNameActivity: ComponentActivity() {
setContent { setContent {
Body { Body {
scaffoldState -> scaffoldState ->
MainFrame(background = { Background(image = BackgroundImage.rename) }) { MainFrame(background = { Background(image = BackgroundImage.Rename) }) {
Spacer( Spacer(
modifier = Modifier modifier = Modifier
.weight(0.2F) .weight(0.2F)
@ -48,7 +48,6 @@ class ReNameActivity: ComponentActivity() {
} }
} }
} }
}
/** /**
* 标题 * 标题
@ -112,3 +111,4 @@ private fun BottomButton(modifier: Modifier=Modifier,model:RenameViewModel= view
Spacer(modifier = Modifier.weight(weight)) Spacer(modifier = Modifier.weight(weight))
} }
} }
}

@ -50,7 +50,7 @@ class RegAssociationActivity: ComponentActivity(){
CSAMSTheme { CSAMSTheme {
Body { Body {
scaffoldState -> scaffoldState ->
MainFrame(background = { Background(BackgroundImage.reg_association,alpha = 0.5F) }) { MainFrame(background = { Background(BackgroundImage.RegAssociation,alpha = 0.5F) }) {
Spacer( Spacer(
modifier = Modifier modifier = Modifier
.weight(0.1F) .weight(0.1F)
@ -79,7 +79,6 @@ class RegAssociationActivity: ComponentActivity(){
} }
} }
}
/** /**
* 社团Logo * 社团Logo
@ -221,3 +220,6 @@ private fun Name(model:RegAssociationViewModel= viewModel()){
private fun Desc(model:RegAssociationViewModel= viewModel(),modifier:Modifier){ private fun Desc(model:RegAssociationViewModel= viewModel(),modifier:Modifier){
BaseTextField(form = model.desc,modifier = modifier) BaseTextField(form = model.desc,modifier = modifier)
} }
}

@ -4,6 +4,7 @@ import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import com.gyf.csams.NOT_IMPL_TIP
import com.gyf.csams.R import com.gyf.csams.R
import com.gyf.csams.uikit.ScrollList import com.gyf.csams.uikit.ScrollList
import com.gyf.csams.uikit.StringForm import com.gyf.csams.uikit.StringForm
@ -85,7 +86,7 @@ class MainViewModel:ViewModel(){
* *
*/ */
fun sendMessage(callback: (value: String) -> Unit){ fun sendMessage(callback: (value: String) -> Unit){
callback("功能尚未实现,敬请期待") callback(NOT_IMPL_TIP)
} }
/** /**
@ -94,7 +95,7 @@ class MainViewModel:ViewModel(){
* @param callback * @param callback
*/ */
fun openNotification(callback: (value: String) -> Unit){ fun openNotification(callback: (value: String) -> Unit){
callback("功能尚未实现,敬请期待") callback(NOT_IMPL_TIP)
} }
} }
@ -125,7 +126,7 @@ class ListViewModel: ScrollList<AssociationDto>() {
*/ */
fun search(callback: (value: String) -> Unit){ fun search(callback: (value: String) -> Unit){
Logger.i("搜索条件[社团名称:${name.formValue.value},社团简介:${desc.formValue.value}]") Logger.i("搜索条件[社团名称:${name.formValue.value},社团简介:${desc.formValue.value}]")
callback("功能尚未实现,敬请期待") callback(NOT_IMPL_TIP)
} }
override val initSize: Int = 10 override val initSize: Int = 10

@ -32,6 +32,7 @@ import com.gyf.csams.association.ui.RegAssociationActivity
import com.gyf.csams.main.model.* import com.gyf.csams.main.model.*
import com.gyf.csams.uikit.* import com.gyf.csams.uikit.*
import com.gyf.csams.uikit.theme.CSAMSTheme import com.gyf.csams.uikit.theme.CSAMSTheme
import com.gyf.csams.util.randomChinese
/** /**
@ -66,7 +67,6 @@ class MainActivity : ComponentActivity() {
} }
}
/** /**
* 个人中心 * 个人中心
@ -74,7 +74,7 @@ class MainActivity : ComponentActivity() {
*/ */
@Composable @Composable
private fun Center(model:CenterViewModel= viewModel(), scaffoldModel: ScaffoldModel= viewModel(), navController: NavHostController){ 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) { MainFrame(background = { Background(image = BackgroundImage.Center,alpha = 0.5F) }, mainMenu = MainMenu.Center, nav = navController) {
Column(modifier = Modifier Column(modifier = Modifier
.weight(0.33F) .weight(0.33F)
.fillMaxWidth(),verticalArrangement = Arrangement.Bottom) { .fillMaxWidth(),verticalArrangement = Arrangement.Bottom) {
@ -111,7 +111,7 @@ private fun Center(model:CenterViewModel= viewModel(), scaffoldModel: ScaffoldMo
*/ */
@Composable @Composable
private fun Main(navController: NavHostController) { private fun Main(navController: NavHostController) {
MainFrame(background = { Background(image = BackgroundImage.main) }, mainMenu = MainMenu.Main, nav = navController) { MainFrame(background = { Background(image = BackgroundImage.Main) }, mainMenu = MainMenu.Main, nav = navController) {
Column(modifier = Modifier.weight(0.33F)) { Column(modifier = Modifier.weight(0.33F)) {
Notification() Notification()
MessageBoard() MessageBoard()
@ -134,7 +134,7 @@ private fun Main(navController: NavHostController) {
@Composable @Composable
private fun AssociationList(navController: NavHostController) { private fun AssociationList(navController: NavHostController) {
MainFrame( MainFrame(
background = { Background(image = BackgroundImage.list) }, background = { Background(image = BackgroundImage.AssociationList) },
mainMenu = MainMenu.List, mainMenu = MainMenu.List,
nav = navController nav = navController
) { ) {
@ -374,7 +374,8 @@ private fun PosterWithDesc(model: CarouselViewModel = viewModel()) {
DescCard( DescCard(
modifier = Modifier modifier = Modifier
.weight(0.4F) .weight(0.4F)
.fillMaxWidth() .fillMaxWidth(),
content = randomChinese(500)
) )
} }
} }
@ -388,6 +389,9 @@ fun DefaultPreview() {
Text(text = "666") Text(text = "666")
} }
} }
}

@ -1,19 +1,18 @@
package com.gyf.csams.uikit package com.gyf.csams.uikit
import android.app.Activity
import androidx.annotation.DrawableRes import androidx.annotation.DrawableRes
import androidx.compose.animation.Crossfade import androidx.compose.animation.Crossfade
import androidx.compose.animation.animateColor import androidx.compose.animation.animateColor
import androidx.compose.animation.core.* import androidx.compose.animation.core.*
import androidx.compose.foundation.Image import androidx.compose.foundation.Image
import androidx.compose.foundation.border
import androidx.compose.foundation.clickable import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.* import androidx.compose.foundation.layout.*
import androidx.compose.foundation.text.KeyboardActions import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material.* import androidx.compose.material.*
import androidx.compose.runtime.Composable import androidx.compose.runtime.*
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.State
import androidx.compose.runtime.getValue
import androidx.compose.runtime.livedata.observeAsState import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier 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.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.viewmodel.compose.viewModel import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.NavHostController import androidx.navigation.NavHostController
import androidx.navigation.compose.navigate import androidx.navigation.compose.navigate
@ -35,7 +36,6 @@ import com.gyf.csams.APP
import com.gyf.csams.R import com.gyf.csams.R
import com.gyf.csams.main.model.CarouselViewModel import com.gyf.csams.main.model.CarouselViewModel
import com.gyf.csams.main.model.MarqueeViewModel import com.gyf.csams.main.model.MarqueeViewModel
import com.gyf.csams.uikit.theme.CSAMSTheme
import com.orhanobut.logger.Logger import com.orhanobut.logger.Logger
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@ -90,7 +90,7 @@ enum class MainMenu(
* @param onClick * @param onClick
*/ */
@Composable @Composable
fun MenuIconButton(_menu: MainMenu, menu: MainMenu, modifier: Modifier, onClick: () -> Unit) { fun MenuIconButton(_menu: MainMenu, menu: MainMenu, modifier: Modifier=Modifier, onClick: () -> Unit) {
Row( Row(
modifier = modifier, horizontalArrangement = Arrangement.Center modifier = modifier, horizontalArrangement = Arrangement.Center
) { ) {
@ -113,30 +113,74 @@ fun MenuIconButton(_menu: MainMenu, menu: MainMenu, modifier: Modifier, onClick:
@Composable @Composable
fun MainBottomAppBar(menu: MainMenu, nav: NavHostController, modifier: Modifier = Modifier) { fun MainBottomAppBar(menu: MainMenu, nav: NavHostController, modifier: Modifier = Modifier) {
BottomAppBar(backgroundColor = MaterialTheme.colors.background, modifier = modifier) { BottomAppBar(backgroundColor = MaterialTheme.colors.background, modifier = modifier) {
//图标宽度平等分 Row(Modifier.fillMaxWidth(),horizontalArrangement = Arrangement.SpaceBetween) {
MenuIconButton(_menu = menu, menu = MainMenu.Main,
val weight = 1 / (MainMenu.values().size * 1.0f)
Row(Modifier.fillMaxWidth()) {
MenuIconButton(_menu = menu, menu = MainMenu.Main, Modifier.weight(weight),
onClick = { nav.navigate(MainMenu.Main.name) }) 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) }) 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) }) onClick = { nav.navigate(MainMenu.Center.name) })
} }
} }
} }
/**
* 顶部菜单
*
*/
interface TopMenuInterface<T:TopBarMenu>{
/**
* 当前菜单
*/
val _currentMenu: MutableLiveData<T>
val currentMenu: LiveData<T>
/**
* 切换顶部菜单
*
* @param menu
*/
fun clickMenu(menu:T){
_currentMenu.value=menu
}
}
interface TopBarMenu{
val menuName:String
val name:String
}
interface StartMenu<T>{
val startMenu:T
}
/** /**
* 社团菜单 * 社团菜单
* *
*/ */
enum class AssociationMenu(val menuName: String) { enum class AssociationMenu(override val menuName: String):TopBarMenu {
member("社团成员"), Member("社团成员"),
main("社团主页"), Main("社团主页"),
list("活动列表") ActivityList("活动列表");
companion object Menu:StartMenu<AssociationMenu>{
override val startMenu: AssociationMenu = Main
}
}
enum class ActivityDetailMenu(override val menuName:String):TopBarMenu{
Info("活动信息"),
Photo("相册"),
Member("活动成员"),
BBS("交流区");
companion object Menu:StartMenu<ActivityDetailMenu>{
override val startMenu: ActivityDetailMenu = Info
}
} }
/** /**
@ -144,16 +188,18 @@ enum class AssociationMenu(val menuName: String) {
* *
*/ */
@Composable @Composable
fun AssociationAppBar( fun TextTopAppBar(
menu: AssociationMenu,
nav:NavHostController, nav:NavHostController,
back: () -> Unit, currentMenuName:String,
dropMenu: () -> Unit, menuNames:Array<out TopBarMenu>,
content:@Composable () -> Unit iconMenu: (() -> Unit)? = null,
@DrawableRes icon:Int = R.drawable.ic_configuration,
dropMenuContent:@Composable () -> Unit = {},
) { ) {
TopAppBar(backgroundColor = MaterialTheme.colors.secondary) { TopAppBar(backgroundColor = MaterialTheme.colors.secondary) {
Row(modifier = Modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically) { Row(modifier = Modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically) {
IconButton(onClick = back, modifier = Modifier.weight(0.1F)) { val context= LocalContext.current as Activity
IconButton(onClick = {context.onBackPressed()}, modifier = Modifier.weight(0.1F)) {
Icon( Icon(
painter = painterResource(id = R.drawable.ic_arrow_left), painter = painterResource(id = R.drawable.ic_arrow_left),
contentDescription = null contentDescription = null
@ -163,32 +209,35 @@ fun AssociationAppBar(
modifier = Modifier modifier = Modifier
.weight(0.8F) .weight(0.8F)
.fillMaxHeight(), .fillMaxHeight(),
horizontalArrangement = Arrangement.Center, horizontalArrangement = Arrangement.SpaceAround,
verticalAlignment = Alignment.CenterVertically verticalAlignment = Alignment.CenterVertically
) { ) {
val menus = AssociationMenu.values() menuNames.forEach {
menus.forEach {
Row( Row(
modifier = Modifier modifier = Modifier
.weight(1F / menus.size) .weight(1F / menuNames.size)
.clickable(onClick = { nav.navigate(it.name) }), .clickable(onClick = { nav.navigate(it.name) }),
horizontalArrangement = Arrangement.Center horizontalArrangement = Arrangement.Center
) { ) {
Text( Text(
text = it.menuName, text = it.menuName,
color = if (menu == it) MaterialTheme.colors.primary else MaterialTheme.colors.onBackground 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( Icon(
painter = painterResource(id = R.drawable.ic_configuration), painter = painterResource(id = icon),
contentDescription = null 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) { 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 @Composable
fun DescCard(modifier: Modifier) { fun DescCard(modifier: Modifier,content:String) {
Card( Card(
modifier = modifier, modifier = modifier,
backgroundColor = Color.Transparent backgroundColor = Color.Transparent
) { ) {
Box {
Image( Image(
painter = painterResource(id = R.drawable.hot_activity_desc_background), painter = painterResource(id = R.drawable.hot_activity_desc_background),
contentDescription = null contentDescription = null,
contentScale = ContentScale.FillBounds,
modifier = Modifier.fillMaxSize()
) )
Column(modifier = Modifier.fillMaxSize().padding(horizontal = 10.dp)) {
Row(modifier = Modifier.fillMaxWidth()) { Spacer(modifier = Modifier.weight(0.15F))
Spacer(modifier = Modifier.weight(0.2F))
Column(
modifier = Modifier
.weight(0.5F)
) {
Spacer(modifier = Modifier.weight(0.1F))
Text( Text(
text = "文字对任何界面都属于核心内容,而利用 Jetpack Compose 可以更轻松地显示或写入文字。Compose 可以充分利用其构建块的组合,这意味着您无需覆盖各种属性和方法,也无需扩展大型类,即可拥有特定的可组合项设计以及按您期望的方式运行的逻辑。" modifier = Modifier.weight(0.65F),
.repeat(10), overflow = TextOverflow.Ellipsis, text = content,
modifier = Modifier.weight(0.8F) overflow = TextOverflow.Ellipsis
) )
Spacer(modifier = Modifier.weight(0.1F)) Spacer(modifier = Modifier.weight(0.15F))
} }
Spacer(modifier = Modifier.weight(0.2F))
} }
} }
} }
//@Preview
@Preview
@Composable @Composable
fun AnimationTextPreview() { fun AnimationTextPreview() {
AnimationText(text = "6666") AnimationText(text = "6666")
} }
//@Preview @Preview
@Composable @Composable
fun MyBottomAppBarPreview() { fun MyBottomAppBarPreview() {
CSAMSTheme { val arr:List<Arrangement.Horizontal> = 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)
}
}
}
}
} }
} }

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

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="200dp"
android:height="200dp"
android:viewportWidth="1024"
android:viewportHeight="1024">
<path
android:fillColor="#FF000000"
android:pathData="M704,341.33h64a64,64 0,0 1,64 64v362.67a64,64 0,0 1,-64 64H256a64,64 0,0 1,-64 -64V405.33a64,64 0,0 1,64 -64h64v64h-64v362.67h512V405.33h-64v-64zM517.65,124.63l150.83,150.83 -45.23,45.27 -74.03,-74.01v304.77h-64V247.62l-73.17,73.13 -45.25,-45.25 150.83,-150.85z"/>
</vector>

@ -3,6 +3,7 @@ package com.gyf.csams
import com.google.gson.Gson import com.google.gson.Gson
import com.google.gson.reflect.TypeToken import com.google.gson.reflect.TypeToken
import com.gyf.csams.util.ApiResponse import com.gyf.csams.util.ApiResponse
import com.gyf.csams.util.randomChinese
import org.junit.Assert.assertEquals import org.junit.Assert.assertEquals
import org.junit.Test import org.junit.Test
@ -32,16 +33,16 @@ class ExampleUnitTest {
println(e.body) println(e.body)
} }
@Test
fun testYear(){
repeat(10,{
println(it)
})
}
@Test @Test
fun testCharRange(){ fun testCharRange(){
println(('A'..'D').map { "选项$it" }) repeat(100){
println(randomChinese())
}
// println(java.time.format.DateTimeFormatter.ISO_INSTANT
// .format(java.time.Instant.ofEpochMilli(1532358895000)))
} }
} }

Loading…
Cancel
Save