From 3234ec2974969e4f086e42a264a437fb10873b21 Mon Sep 17 00:00:00 2001 From: pan <1029559041@qq.com> Date: Fri, 14 May 2021 22:34:01 +0800 Subject: [PATCH] =?UTF-8?q?=E7=95=8C=E9=9D=A2=E9=80=BB=E8=BE=91=E5=B0=81?= =?UTF-8?q?=E8=A3=85=20=E5=AE=8C=E5=96=84=E7=A4=BE=E5=9B=A2=E7=95=8C?= =?UTF-8?q?=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/java/com/gyf/csams/APP.kt | 2 + .../association/model/AssociationViewModel.kt | 56 ++++++++++-- .../association/ui/AssociationActivity.kt | 87 +++++++++++++++++-- .../com/gyf/csams/main/model/MainViewModel.kt | 42 +++++---- .../com/gyf/csams/main/ui/MainActivity.kt | 28 ++---- .../main/java/com/gyf/csams/uikit/BaseView.kt | 25 ++++++ .../java/com/gyf/csams/uikit/ViewModel.kt | 29 ++++++- 7 files changed, 210 insertions(+), 59 deletions(-) diff --git a/app/src/main/java/com/gyf/csams/APP.kt b/app/src/main/java/com/gyf/csams/APP.kt index 8f1b314..f197a56 100644 --- a/app/src/main/java/com/gyf/csams/APP.kt +++ b/app/src/main/java/com/gyf/csams/APP.kt @@ -14,6 +14,8 @@ import com.orhanobut.logger.Logger class APP : Application() { + + private lateinit var memoryCache: LruCache // Get max available VM memory, exceeding this amount will throw an // OutOfMemory exception. Stored in kilobytes as LruCache takes an 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 c374ab9..e5bbc14 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 @@ -5,6 +5,7 @@ import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.gyf.csams.uikit.AssociationMenu +import com.gyf.csams.uikit.ScrollList import com.gyf.csams.uikit.StringForm import com.orhanobut.logger.Logger import kotlinx.coroutines.launch @@ -24,7 +25,7 @@ data class MemberVo(val name:String) * 社团会员 * */ -class MemberViewModel:ViewModel(){ +class MemberViewModel:ScrollList(){ val name=StringForm(formDesc = "姓名关键字",5) val search="搜索" @@ -33,30 +34,34 @@ class MemberViewModel:ViewModel(){ val memberList=_memberList + override val initSize: Int = 10 + init { - initMemberList() + load() } /** * 初始化成员 * */ - private fun initMemberList(){ + override fun load() { viewModelScope.launch { _memberList.value?.apply { - repeat(10) { - add(MemberVo(name = "成员${it+1}")) + repeat(initSize) { + add(MemberVo(name = "成员${size+1}")) } + Logger.i("初始化社团成员size=$size") } - Logger.i("初始化社团成员size=${_memberList.value?.size}") + } } + /** * 加载更多成员 * */ - fun loadMore(){ + override fun loadMore(callback: (message: String) -> Unit) { viewModelScope.launch { _memberList.value?.let { val t= mutableListOf() @@ -81,4 +86,41 @@ class MemberViewModel:ViewModel(){ Logger.i("搜索条件[成员姓名:${name.formValue.value}]") callback("功能尚未实现,敬请期待") } +} + +data class HistoryActVo(val name: String) + +/** + * 历史活动 + * + */ +class HistoryActViewModel: ScrollList() { + override val initSize = 10 + + init { + load() + } + + override fun load() { + _data.value?.apply { + repeat(initSize){ + add(HistoryActVo(name = "活动${size+1}")) + } + Logger.i("初始化活动数量:${size}") + } + } + + override fun loadMore(callback:(message:String) -> Unit) { + _data.value?.apply { + val t= mutableListOf() + t.addAll(this) + t.apply { + repeat(10){ + add(HistoryActVo(name = "活动${t.size+1}")) + } + } + _data.postValue(t) + callback("成功加载更多活动") + } + } } \ 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 725192f..5c3b9d3 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 @@ -4,6 +4,7 @@ import android.os.Bundle import androidx.activity.ComponentActivity import androidx.activity.compose.setContent 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 @@ -22,9 +23,7 @@ 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.association.model.AssociationViewModel -import com.gyf.csams.association.model.MemberViewModel -import com.gyf.csams.association.model.MemberVo +import com.gyf.csams.association.model.* import com.gyf.csams.uikit.* import com.gyf.csams.uikit.theme.CSAMSTheme @@ -46,7 +45,7 @@ class AssociationActivity: ComponentActivity() { Column { AssociationAppBar(menu = menu,nav = nav,back = { context.onBackPressed() }){ - + //TODO 显示下拉菜单 } NavHost(navController = nav, startDestination = startMenu.name) { composable(AssociationMenu.member.name){ @@ -122,8 +121,8 @@ private fun Search(modifier:Modifier=Modifier, model: MemberViewModel= viewModel * */ @Composable -private fun MemberList(modifier: Modifier=Modifier,viewModel: MemberViewModel=viewModel()){ - val list:MutableList? by viewModel.memberList.observeAsState() +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 { @@ -148,7 +147,9 @@ private fun MemberList(modifier: Modifier=Modifier,viewModel: MemberViewModel=vi } item { Row(horizontalArrangement = Arrangement.Center,modifier = Modifier.fillMaxWidth()) { - IconButton(onClick = { viewModel.loadMore() }) { + IconButton(onClick = { model.loadMore{ + scaffoldModel.update(it) + } }) { Icon(painter = painterResource(id = R.drawable.ic_arrow_down), contentDescription = null) } } @@ -250,7 +251,77 @@ private fun Showcase(modifier: Modifier){ @Composable private fun AssociationList(){ MainFrame(background = { Background(image = BackgroundImage.association_main,alpha = 07F) }) { - Text(text = "活动列表") + 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)) + } + +} + +/** + * 历史活动列表 + * + * @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) + } + } + } + if(listState.layoutInfo.totalItemsCount-listState.firstVisibleItemIndex==model.initSize/2-1){ + model.loadMore { scaffoldModel.update(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) + } } 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 52b44a0..4495312 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 @@ -5,6 +5,7 @@ import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.gyf.csams.R +import com.gyf.csams.uikit.ScrollList import com.gyf.csams.uikit.StringForm import com.orhanobut.logger.Logger import kotlinx.coroutines.Job @@ -101,7 +102,7 @@ class MainViewModel:ViewModel(){ * 社团列表 * */ -class ListViewModel:ViewModel(){ +class ListViewModel: ScrollList() { val name = StringForm(formDesc = "社团名称",textLength = 5) val desc = StringForm(formDesc = "社团简介",textLength = 10) @@ -115,9 +116,7 @@ class ListViewModel:ViewModel(){ val searchDesc="搜索" - init { - loadAssociation() - } + /** * TODO 社团检索 @@ -129,12 +128,18 @@ class ListViewModel:ViewModel(){ callback("功能尚未实现,敬请期待") } + override val initSize: Int = 10 + + init { + load() + + } + /** * 加载社团列表 * */ - private fun loadAssociation(){ - + override fun load() { viewModelScope.launch { _associationList.value?.apply { repeat(10 @@ -145,35 +150,28 @@ class ListViewModel:ViewModel(){ } Logger.i("初始化社团列表size=${_associationList.value?.size}") } - } - - /** * 加载更多社团列表 * */ - fun addMore(callback:(message:String) -> Unit){ + override fun loadMore(callback: (message: String) -> Unit) { viewModelScope.launch { - val c = _associationList.value - - if(c!=null){ - val t=mutableListOf() - t.addAll(c) - t.apply { - repeat(10 - ) { - add(AssociationDto(name = "社团${t.size}")) + _associationList.value?.apply { + val list= mutableListOf() + list.addAll(this) + list.apply { + repeat(10){ + add(AssociationDto(name = "社团${size}")) } } - Logger.i("t.size=${t.size}") - _associationList.postValue(t) + Logger.i("t.size=${size}") + _associationList.postValue(list) Logger.i("加载更多社团size=${_associationList.value?.size}") callback("成功加载更多社团") } } - } } 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 5393a15..132e19a 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 @@ -17,7 +17,6 @@ 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.graphics.Color import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.painterResource import androidx.compose.ui.text.style.TextOverflow @@ -121,7 +120,7 @@ private fun Main(navController: NavHostController) { Spacer(modifier = Modifier.height(10.dp)) } Column(modifier = Modifier.weight(0.66F)) { - ClubActivitiesImage() + PosterWithDesc() } } } @@ -207,7 +206,7 @@ private fun AssociationListBody(model: ListViewModel = viewModel(),scaffoldModel } if(listState.layoutInfo.totalItemsCount-listState.firstVisibleItemIndex==model.associationListSize/2-1){ - model.addMore { scaffoldModel.update(it) } + model.loadMore { scaffoldModel.update(it) } } } @@ -362,29 +361,16 @@ private fun ClubActivitiesTitle() { /** - * 活动海报 + * 带介绍活动海报 * */ @Composable -private fun ClubActivitiesImage(model: CarouselViewModel = viewModel()) { +private fun PosterWithDesc(model: CarouselViewModel = viewModel()) { Carousel(model = model) { Column { - Card( - modifier = Modifier - .weight(0.6F) - .fillMaxWidth(), - backgroundColor = Color.Transparent - ) { - Image( - painter = painterResource(id = R.drawable.hot_activity_background), - contentDescription = null - ) - - Image( - painter = painterResource(id = it), - contentDescription = null - ) - } + Poster(modifier = Modifier + .weight(0.6F) + .fillMaxWidth(),id = it) DescCard( modifier = Modifier .weight(0.4F) 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 0478bf9..42084c5 100644 --- a/app/src/main/java/com/gyf/csams/uikit/BaseView.kt +++ b/app/src/main/java/com/gyf/csams/uikit/BaseView.kt @@ -394,6 +394,31 @@ fun Body( content:@Composable (nav:NavHostController, scaffoldState:ScaffoldStat } } +/** + * 活动海报 + * + */ +@Composable +fun Poster(modifier: Modifier=Modifier,@DrawableRes id: Int){ + Card( + modifier = modifier, + backgroundColor = Color.Transparent + ) { + Box(contentAlignment = Alignment.Center) { + Image( + painter = painterResource(id = R.drawable.hot_activity_background), + contentDescription = null, + modifier=Modifier.fillMaxSize() + ) + Image( + painter = painterResource(id = id), + contentDescription = null, + modifier=Modifier.fillMaxSize() + ) + } + } +} + /** * 介绍卡片 * diff --git a/app/src/main/java/com/gyf/csams/uikit/ViewModel.kt b/app/src/main/java/com/gyf/csams/uikit/ViewModel.kt index 5a9843b..407ee1a 100644 --- a/app/src/main/java/com/gyf/csams/uikit/ViewModel.kt +++ b/app/src/main/java/com/gyf/csams/uikit/ViewModel.kt @@ -17,6 +17,14 @@ abstract class FormName(val formDesc:String){ abstract fun onChange(value:T) } +/** + * 文本输入框控制 + * + * @property textLength + * @constructor + * + * @param formDesc + */ open class StringForm(formDesc: String, val textLength: Int) : FormName(formDesc = formDesc), FormLength { override val nameLengthError="${formDesc}不能超过最大长度$textLength" @@ -31,6 +39,10 @@ open class StringForm(formDesc: String, val textLength: Int) : FormName( } } +/** + * snackbar + * + */ class ScaffoldModel:ViewModel(){ private val _message=MutableLiveData() val message:LiveData = _message @@ -38,4 +50,19 @@ class ScaffoldModel:ViewModel(){ fun update(message:String?=null){ _message.value=message } -} \ No newline at end of file +} + +abstract class ScrollList:ViewModel(){ + protected val _data=MutableLiveData>(mutableListOf()) + val data:LiveData> = _data + + abstract val initSize:Int + + //加载列表 + abstract fun load() + //加载更多数据 + abstract fun loadMore(callback:(message:String) -> Unit) +} + + +