界面逻辑封装

完善社团界面
master
pan 4 years ago
parent 743486211b
commit 3234ec2974
  1. 2
      app/src/main/java/com/gyf/csams/APP.kt
  2. 56
      app/src/main/java/com/gyf/csams/association/model/AssociationViewModel.kt
  3. 87
      app/src/main/java/com/gyf/csams/association/ui/AssociationActivity.kt
  4. 42
      app/src/main/java/com/gyf/csams/main/model/MainViewModel.kt
  5. 28
      app/src/main/java/com/gyf/csams/main/ui/MainActivity.kt
  6. 25
      app/src/main/java/com/gyf/csams/uikit/BaseView.kt
  7. 29
      app/src/main/java/com/gyf/csams/uikit/ViewModel.kt

@ -14,6 +14,8 @@ import com.orhanobut.logger.Logger
class APP : Application() { class APP : Application() {
private lateinit var memoryCache: LruCache<BackgroundImage, Bitmap> private lateinit var memoryCache: LruCache<BackgroundImage, Bitmap>
// Get max available VM memory, exceeding this amount will throw an // Get max available VM memory, exceeding this amount will throw an
// OutOfMemory exception. Stored in kilobytes as LruCache takes an // OutOfMemory exception. Stored in kilobytes as LruCache takes an

@ -5,6 +5,7 @@ import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import com.gyf.csams.uikit.AssociationMenu import com.gyf.csams.uikit.AssociationMenu
import com.gyf.csams.uikit.ScrollList
import com.gyf.csams.uikit.StringForm import com.gyf.csams.uikit.StringForm
import com.orhanobut.logger.Logger import com.orhanobut.logger.Logger
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@ -24,7 +25,7 @@ data class MemberVo(val name:String)
* 社团会员 * 社团会员
* *
*/ */
class MemberViewModel:ViewModel(){ class MemberViewModel:ScrollList<MemberVo>(){
val name=StringForm(formDesc = "姓名关键字",5) val name=StringForm(formDesc = "姓名关键字",5)
val search="搜索" val search="搜索"
@ -33,30 +34,34 @@ class MemberViewModel:ViewModel(){
val memberList=_memberList val memberList=_memberList
override val initSize: Int = 10
init { init {
initMemberList() load()
} }
/** /**
* 初始化成员 * 初始化成员
* *
*/ */
private fun initMemberList(){ override fun load() {
viewModelScope.launch { viewModelScope.launch {
_memberList.value?.apply { _memberList.value?.apply {
repeat(10) { repeat(initSize) {
add(MemberVo(name = "成员${it+1}")) 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 { viewModelScope.launch {
_memberList.value?.let { _memberList.value?.let {
val t= mutableListOf<MemberVo>() val t= mutableListOf<MemberVo>()
@ -81,4 +86,41 @@ class MemberViewModel:ViewModel(){
Logger.i("搜索条件[成员姓名:${name.formValue.value}]") Logger.i("搜索条件[成员姓名:${name.formValue.value}]")
callback("功能尚未实现,敬请期待") callback("功能尚未实现,敬请期待")
} }
}
data class HistoryActVo(val name: String)
/**
* 历史活动
*
*/
class HistoryActViewModel: ScrollList<HistoryActVo>() {
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<HistoryActVo>()
t.addAll(this)
t.apply {
repeat(10){
add(HistoryActVo(name = "活动${t.size+1}"))
}
}
_data.postValue(t)
callback("成功加载更多活动")
}
}
} }

@ -4,6 +4,7 @@ import android.os.Bundle
import androidx.activity.ComponentActivity import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent import androidx.activity.compose.setContent
import androidx.compose.foundation.Image import androidx.compose.foundation.Image
import androidx.compose.foundation.border
import androidx.compose.foundation.layout.* import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.rememberLazyListState 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.NavHost
import androidx.navigation.compose.composable import androidx.navigation.compose.composable
import com.gyf.csams.R import com.gyf.csams.R
import com.gyf.csams.association.model.AssociationViewModel import com.gyf.csams.association.model.*
import com.gyf.csams.association.model.MemberViewModel
import com.gyf.csams.association.model.MemberVo
import com.gyf.csams.uikit.* import com.gyf.csams.uikit.*
import com.gyf.csams.uikit.theme.CSAMSTheme import com.gyf.csams.uikit.theme.CSAMSTheme
@ -46,7 +45,7 @@ class AssociationActivity: ComponentActivity() {
Column { Column {
AssociationAppBar(menu = menu,nav = nav,back = { context.onBackPressed() }){ AssociationAppBar(menu = menu,nav = nav,back = { context.onBackPressed() }){
//TODO 显示下拉菜单
} }
NavHost(navController = nav, startDestination = startMenu.name) { NavHost(navController = nav, startDestination = startMenu.name) {
composable(AssociationMenu.member.name){ composable(AssociationMenu.member.name){
@ -122,8 +121,8 @@ private fun Search(modifier:Modifier=Modifier, model: MemberViewModel= viewModel
* *
*/ */
@Composable @Composable
private fun MemberList(modifier: Modifier=Modifier,viewModel: MemberViewModel=viewModel()){ private fun MemberList(modifier: Modifier=Modifier, model: MemberViewModel=viewModel(), scaffoldModel: ScaffoldModel= viewModel()){
val list:MutableList<MemberVo>? by viewModel.memberList.observeAsState() val list:MutableList<MemberVo>? by model.memberList.observeAsState()
val listState= rememberLazyListState() val listState= rememberLazyListState()
LazyColumn(state = listState,modifier = modifier) { LazyColumn(state = listState,modifier = modifier) {
list?.forEach { list?.forEach {
@ -148,7 +147,9 @@ private fun MemberList(modifier: Modifier=Modifier,viewModel: MemberViewModel=vi
} }
item { item {
Row(horizontalArrangement = Arrangement.Center,modifier = Modifier.fillMaxWidth()) { 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) Icon(painter = painterResource(id = R.drawable.ic_arrow_down), contentDescription = null)
} }
} }
@ -250,7 +251,77 @@ 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.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)
} }
} }

@ -5,6 +5,7 @@ import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import com.gyf.csams.R import com.gyf.csams.R
import com.gyf.csams.uikit.ScrollList
import com.gyf.csams.uikit.StringForm import com.gyf.csams.uikit.StringForm
import com.orhanobut.logger.Logger import com.orhanobut.logger.Logger
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
@ -101,7 +102,7 @@ class MainViewModel:ViewModel(){
* 社团列表 * 社团列表
* *
*/ */
class ListViewModel:ViewModel(){ class ListViewModel: ScrollList<AssociationDto>() {
val name = StringForm(formDesc = "社团名称",textLength = 5) val name = StringForm(formDesc = "社团名称",textLength = 5)
val desc = StringForm(formDesc = "社团简介",textLength = 10) val desc = StringForm(formDesc = "社团简介",textLength = 10)
@ -115,9 +116,7 @@ class ListViewModel:ViewModel(){
val searchDesc="搜索" val searchDesc="搜索"
init {
loadAssociation()
}
/** /**
* TODO 社团检索 * TODO 社团检索
@ -129,12 +128,18 @@ class ListViewModel:ViewModel(){
callback("功能尚未实现,敬请期待") callback("功能尚未实现,敬请期待")
} }
override val initSize: Int = 10
init {
load()
}
/** /**
* 加载社团列表 * 加载社团列表
* *
*/ */
private fun loadAssociation(){ override fun load() {
viewModelScope.launch { viewModelScope.launch {
_associationList.value?.apply { _associationList.value?.apply {
repeat(10 repeat(10
@ -145,35 +150,28 @@ class ListViewModel:ViewModel(){
} }
Logger.i("初始化社团列表size=${_associationList.value?.size}") Logger.i("初始化社团列表size=${_associationList.value?.size}")
} }
} }
/** /**
* 加载更多社团列表 * 加载更多社团列表
* *
*/ */
fun addMore(callback:(message:String) -> Unit){ override fun loadMore(callback: (message: String) -> Unit) {
viewModelScope.launch { viewModelScope.launch {
val c = _associationList.value _associationList.value?.apply {
val list= mutableListOf<AssociationDto>()
if(c!=null){ list.addAll(this)
val t=mutableListOf<AssociationDto>() list.apply {
t.addAll(c) repeat(10){
t.apply { add(AssociationDto(name = "社团${size}"))
repeat(10
) {
add(AssociationDto(name = "社团${t.size}"))
} }
} }
Logger.i("t.size=${t.size}") Logger.i("t.size=${size}")
_associationList.postValue(t) _associationList.postValue(list)
Logger.i("加载更多社团size=${_associationList.value?.size}") Logger.i("加载更多社团size=${_associationList.value?.size}")
callback("成功加载更多社团") callback("成功加载更多社团")
} }
} }
} }
} }

@ -17,7 +17,6 @@ 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
import androidx.compose.ui.graphics.Color
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.text.style.TextOverflow import androidx.compose.ui.text.style.TextOverflow
@ -121,7 +120,7 @@ private fun Main(navController: NavHostController) {
Spacer(modifier = Modifier.height(10.dp)) Spacer(modifier = Modifier.height(10.dp))
} }
Column(modifier = Modifier.weight(0.66F)) { 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){ 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 @Composable
private fun ClubActivitiesImage(model: CarouselViewModel = viewModel()) { private fun PosterWithDesc(model: CarouselViewModel = viewModel()) {
Carousel(model = model) { Carousel(model = model) {
Column { Column {
Card( Poster(modifier = Modifier
modifier = Modifier .weight(0.6F)
.weight(0.6F) .fillMaxWidth(),id = it)
.fillMaxWidth(),
backgroundColor = Color.Transparent
) {
Image(
painter = painterResource(id = R.drawable.hot_activity_background),
contentDescription = null
)
Image(
painter = painterResource(id = it),
contentDescription = null
)
}
DescCard( DescCard(
modifier = Modifier modifier = Modifier
.weight(0.4F) .weight(0.4F)

@ -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()
)
}
}
}
/** /**
* 介绍卡片 * 介绍卡片
* *

@ -17,6 +17,14 @@ abstract class FormName<T>(val formDesc:String){
abstract fun onChange(value:T) abstract fun onChange(value:T)
} }
/**
* 文本输入框控制
*
* @property textLength
* @constructor
*
* @param formDesc
*/
open class StringForm(formDesc: String, val textLength: Int) : FormName<String>(formDesc = formDesc), open class StringForm(formDesc: String, val textLength: Int) : FormName<String>(formDesc = formDesc),
FormLength { FormLength {
override val nameLengthError="${formDesc}不能超过最大长度$textLength" override val nameLengthError="${formDesc}不能超过最大长度$textLength"
@ -31,6 +39,10 @@ open class StringForm(formDesc: String, val textLength: Int) : FormName<String>(
} }
} }
/**
* snackbar
*
*/
class ScaffoldModel:ViewModel(){ class ScaffoldModel:ViewModel(){
private val _message=MutableLiveData<String>() private val _message=MutableLiveData<String>()
val message:LiveData<String> = _message val message:LiveData<String> = _message
@ -38,4 +50,19 @@ class ScaffoldModel:ViewModel(){
fun update(message:String?=null){ fun update(message:String?=null){
_message.value=message _message.value=message
} }
} }
abstract class ScrollList<T>:ViewModel(){
protected val _data=MutableLiveData<MutableList<T>>(mutableListOf())
val data:LiveData<MutableList<T>> = _data
abstract val initSize:Int
//加载列表
abstract fun load()
//加载更多数据
abstract fun loadMore(callback:(message:String) -> Unit)
}

Loading…
Cancel
Save