diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 3af8a99..8e700c4 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -44,6 +44,10 @@ + + + \ No newline at end of file diff --git a/app/src/main/java/com/gyf/csams/account/ui/AccountActivity.kt b/app/src/main/java/com/gyf/csams/account/ui/AccountActivity.kt index 2775a8f..a30b45d 100644 --- a/app/src/main/java/com/gyf/csams/account/ui/AccountActivity.kt +++ b/app/src/main/java/com/gyf/csams/account/ui/AccountActivity.kt @@ -27,11 +27,11 @@ import androidx.lifecycle.viewmodel.compose.viewModel import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable import androidx.navigation.compose.navigate -import androidx.navigation.compose.rememberNavController import com.gyf.csams.BuildConfig import com.gyf.csams.account.model.AccountViewModel import com.gyf.csams.account.model.DialogMessage import com.gyf.csams.uikit.AnimationText +import com.gyf.csams.uikit.Body import com.gyf.csams.uikit.theme.CSAMSTheme @@ -46,62 +46,57 @@ class AccountActivity: ComponentActivity() { setContent { CSAMSTheme { - // A surface container using the 'background' color from the theme - Surface(color = MaterialTheme.colors.background) { - val navController = rememberNavController() - val scaffoldState = rememberScaffoldState() - - Scaffold(scaffoldState=scaffoldState) { - NavHost(navController, startDestination = AccountRoute.login.name) { - composable(AccountRoute.login.name) { - Account(scaffoldState=scaffoldState,route = AccountRoute.login) { isValidForm: Boolean, accountViewModel: AccountViewModel -> - Spacer(modifier = Modifier.height(10.dp)) - - OutlinedButton(onClick = {accountViewModel.login()}, - enabled = isValidForm, - modifier = Modifier - .fillMaxWidth() - .padding(bottom = 10.dp)) { - - Text(text = accountViewModel.loginDesc) - } - - val finishLogin:Boolean? by accountViewModel.finishLogin.observeAsState() - if(finishLogin==true){ - finish() - } - - OutlinedButton(onClick = { navController.navigate(AccountRoute.register.name)}, - modifier = Modifier.fillMaxWidth(), - colors = ButtonDefaults.outlinedButtonColors( - contentColor = MaterialTheme.colors.onBackground)) { - Text(text = accountViewModel.goRegister) - } - } + Body { + nav, scaffoldState -> + NavHost(navController = nav, startDestination = AccountRoute.login.name) { + composable(AccountRoute.login.name) { + Account(scaffoldState=scaffoldState,route = AccountRoute.login) { isValidForm: Boolean, accountViewModel: AccountViewModel -> + Spacer(modifier = Modifier.height(10.dp)) + + OutlinedButton(onClick = {accountViewModel.login()}, + enabled = isValidForm, + modifier = Modifier + .fillMaxWidth() + .padding(bottom = 10.dp)) { + + Text(text = accountViewModel.loginDesc) + } + + val finishLogin:Boolean? by accountViewModel.finishLogin.observeAsState() + if(finishLogin==true){ + finish() + } + + OutlinedButton(onClick = { nav.navigate(AccountRoute.register.name)}, + modifier = Modifier.fillMaxWidth(), + colors = ButtonDefaults.outlinedButtonColors( + contentColor = MaterialTheme.colors.onBackground)) { + Text(text = accountViewModel.goRegister) + } + } + + } + + composable(AccountRoute.register.name) { + Account(scaffoldState=scaffoldState,route = AccountRoute.register) { isValidForm: Boolean, accountViewModel: AccountViewModel -> + Spacer(modifier = Modifier.height(10.dp)) + OutlinedButton(onClick = { accountViewModel.register()}, + enabled = isValidForm, + modifier = Modifier + .fillMaxWidth() + .padding(bottom = 10.dp)) { + Text(text = accountViewModel.regBtnDesc) } - composable(AccountRoute.register.name) { - Account(scaffoldState=scaffoldState,route = AccountRoute.register) { isValidForm: Boolean, accountViewModel: AccountViewModel -> - Spacer(modifier = Modifier.height(10.dp)) - - OutlinedButton(onClick = { accountViewModel.register()}, - enabled = isValidForm, - modifier = Modifier - .fillMaxWidth() - .padding(bottom = 10.dp)) { - Text(text = accountViewModel.regBtnDesc) - } - - OutlinedButton(onClick = { navController.navigate(AccountRoute.login.name)}, - modifier = Modifier.fillMaxWidth(), - colors = ButtonDefaults.outlinedButtonColors( - contentColor = MaterialTheme.colors.onBackground)) { - Text(text = accountViewModel.backLogin) - } - } + OutlinedButton(onClick = { nav.navigate(AccountRoute.login.name)}, + modifier = Modifier.fillMaxWidth(), + colors = ButtonDefaults.outlinedButtonColors( + contentColor = MaterialTheme.colors.onBackground)) { + Text(text = accountViewModel.backLogin) } } + } } } } 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 new file mode 100644 index 0000000..c374ab9 --- /dev/null +++ b/app/src/main/java/com/gyf/csams/association/model/AssociationViewModel.kt @@ -0,0 +1,84 @@ +package com.gyf.csams.association.model + +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.gyf.csams.uikit.AssociationMenu +import com.gyf.csams.uikit.StringForm +import com.orhanobut.logger.Logger +import kotlinx.coroutines.launch + +class AssociationViewModel:ViewModel() { + private val _currentMenu=MutableLiveData() + val currentMenu:LiveData = _currentMenu + + fun clickMenu(menu:AssociationMenu){ + _currentMenu.value=menu + } +} + +data class MemberVo(val name:String) + +/** + * 社团会员 + * + */ +class MemberViewModel:ViewModel(){ + val name=StringForm(formDesc = "姓名关键字",5) + + val search="搜索" + + private val _memberList=MutableLiveData>(mutableListOf()) + + val memberList=_memberList + + init { + initMemberList() + } + + /** + * 初始化成员 + * + */ + private fun initMemberList(){ + viewModelScope.launch { + _memberList.value?.apply { + repeat(10) { + add(MemberVo(name = "成员${it+1}")) + } + } + Logger.i("初始化社团成员size=${_memberList.value?.size}") + } + } + + /** + * 加载更多成员 + * + */ + fun loadMore(){ + viewModelScope.launch { + _memberList.value?.let { + val t= mutableListOf() + t.addAll(it) + t.apply { + repeat(10){ + add(MemberVo(name = "成员${t.size+1}")) + } + } + _memberList.postValue(t) + Logger.i("加载更多社团成员,size=${t.size}") + } + } + } + + /** + * TODO 社团成员搜索 + * + * @param callback + */ + fun search(callback: (value: String) -> Unit){ + Logger.i("搜索条件[成员姓名:${name.formValue.value}]") + 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 new file mode 100644 index 0000000..725192f --- /dev/null +++ b/app/src/main/java/com/gyf/csams/association/ui/AssociationActivity.kt @@ -0,0 +1,263 @@ +package com.gyf.csams.association.ui + +import android.os.Bundle +import androidx.activity.ComponentActivity +import androidx.activity.compose.setContent +import androidx.compose.foundation.Image +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.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.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.association.model.AssociationViewModel +import com.gyf.csams.association.model.MemberViewModel +import com.gyf.csams.association.model.MemberVo +import com.gyf.csams.uikit.* +import com.gyf.csams.uikit.theme.CSAMSTheme + +/** + * 社团界面 + * + */ +class AssociationActivity: ComponentActivity() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContent { + CSAMSTheme { + Body { + nav, scaffoldState -> + val context= LocalContext.current as AssociationActivity + val model:AssociationViewModel= viewModel() + val startMenu=AssociationMenu.main + val menu:AssociationMenu by model.currentMenu.observeAsState(startMenu) + + Column { + AssociationAppBar(menu = menu,nav = nav,back = { context.onBackPressed() }){ + + } + NavHost(navController = nav, startDestination = startMenu.name) { + composable(AssociationMenu.member.name){ + model.clickMenu(AssociationMenu.member) + Member() + ShowSnackbar(scaffoldState = scaffoldState) + } + composable(AssociationMenu.main.name){ + model.clickMenu(AssociationMenu.main) + Main() + ShowSnackbar(scaffoldState = scaffoldState) + } + composable(AssociationMenu.list.name){ + model.clickMenu(AssociationMenu.list) + AssociationList() + ShowSnackbar(scaffoldState = scaffoldState) + } + } + } + + } + } + } + } +} + +/** + * 社团成员 + * + */ +@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 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(it) } },modifier = Modifier.weight(buttonWeight)) { + Text(text = model.search) + } + Spacer(modifier = Modifier.weight(spaceWeight)) + } + } +} + +/** + * 成员列表 + * + */ +@Composable +private fun MemberList(modifier: Modifier=Modifier,viewModel: MemberViewModel=viewModel()){ + val list:MutableList? by viewModel.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)) + } + Spacer(modifier = Modifier.height(10.dp)) + Divider(color = MaterialTheme.colors.background) + } + } + } + item { + Row(horizontalArrangement = Arrangement.Center,modifier = Modifier.fillMaxWidth()) { + IconButton(onClick = { viewModel.loadMore() }) { + Icon(painter = painterResource(id = R.drawable.ic_arrow_down), contentDescription = null) + } + } + + } + } +} + +/** + * 社团主页 + * + */ +@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) + .fillMaxWidth() + ) + 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 = "社团名字") + } + 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) { + + Image(painter = painterResource(id = R.drawable.association_persion_name_border), + contentDescription = null + ) + } + 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) + } +} + +/** + * 活动列表 + * + */ +@Composable +private fun AssociationList(){ + MainFrame(background = { Background(image = BackgroundImage.association_main,alpha = 07F) }) { + Text(text = "活动列表") + } +} + +@Preview +@Composable +fun NamePreview(){ + Divider(color = MaterialTheme.colors.background) +} + + 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 87bbccb..9656279 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 @@ -2,7 +2,6 @@ package com.gyf.csams.association.ui import android.Manifest import android.app.Activity -import android.content.Context import android.content.Intent import android.content.pm.PackageManager import android.graphics.BitmapFactory @@ -12,13 +11,15 @@ import android.provider.MediaStore import androidx.activity.ComponentActivity import androidx.activity.compose.rememberLauncherForActivityResult import androidx.activity.compose.setContent -import androidx.activity.result.ActivityResultLauncher import androidx.activity.result.contract.ActivityResultContracts import androidx.compose.foundation.Image import androidx.compose.foundation.background import androidx.compose.foundation.border import androidx.compose.foundation.layout.* -import androidx.compose.material.* +import androidx.compose.material.IconButton +import androidx.compose.material.MaterialTheme +import androidx.compose.material.OutlinedButton +import androidx.compose.material.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.livedata.observeAsState @@ -28,7 +29,6 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.asImageBitmap import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.painterResource -import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.core.content.ContextCompat import androidx.lifecycle.viewmodel.compose.viewModel @@ -48,72 +48,46 @@ class RegAssociationActivity: ComponentActivity(){ super.onCreate(savedInstanceState) setContent { CSAMSTheme { - Body() + Body { + scaffoldState -> + MainFrame(background = { Background(BackgroundImage.reg_association,alpha = 0.5F) }) { + Spacer( + modifier = Modifier + .weight(0.1F) + ) + Title() + Name() + Desc( + modifier = Modifier + .weight(0.1F) + .fillMaxWidth() + ) + Spacer(modifier = Modifier.weight(0.05F)) + Logo( + modifier = Modifier + .weight(0.2F) + .fillMaxWidth() + ) + Spacer(modifier = Modifier.weight(0.05F)) + BottomButton(modifier = Modifier.fillMaxWidth()) + Spacer(modifier = Modifier.weight(0.05F)) + + ShowSnackbar(scaffoldState = scaffoldState) + } + } } } } } -@Composable -fun Body(model:RegAssociationViewModel= viewModel()){ - val scaffoldState = rememberScaffoldState() - Scaffold(scaffoldState = scaffoldState) { - Surface(color = MaterialTheme.colors.background) { - MainFrame(background = { Background(BackgroundImage.reg_association,alpha = 0.7F) }) { - Spacer( - modifier = Modifier - .weight(0.1F) - ) - Title(model = model) - Name(model = model) - Desc( - model = model, modifier = Modifier - .weight(0.1F) - .fillMaxWidth() - ) - Spacer(modifier = Modifier.weight(0.05F)) - Logo( - model = model, modifier = Modifier - .weight(0.2F) - .fillMaxWidth() - ) - Spacer(modifier = Modifier.weight(0.05F)) - BottomButton(modifier = Modifier.fillMaxWidth()) - Spacer(modifier = Modifier.weight(0.05F)) - - ShowSnackbar(scaffoldState = scaffoldState) - } - } - } -} - - -//@Composable -fun PermissionHandle(context: Context, launcher: ActivityResultLauncher,onGranted:()->Unit){ - // Check permission - when (PackageManager.PERMISSION_GRANTED) { - ContextCompat.checkSelfPermission( - context, - Manifest.permission.READ_EXTERNAL_STORAGE - ) -> { - // Some works that require permission - onGranted() - } - else -> { - // Asking for permission - launcher.launch(Manifest.permission.READ_EXTERNAL_STORAGE) - } - } -} - /** * 社团Logo * * @param modifier */ @Composable -fun Logo(model:RegAssociationViewModel= viewModel(),modifier: Modifier) { +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() @@ -201,7 +175,7 @@ fun Logo(model:RegAssociationViewModel= viewModel(),modifier: Modifier) { } @Composable -fun BottomButton(modifier: Modifier=Modifier,scaffoldModel: ScaffoldModel= viewModel(),model:RegAssociationViewModel= viewModel()){ +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 = { @@ -224,7 +198,7 @@ fun BottomButton(modifier: Modifier=Modifier,scaffoldModel: ScaffoldModel= viewM * */ @Composable -fun Title(model:RegAssociationViewModel= viewModel()){ +private fun Title(model:RegAssociationViewModel= viewModel()){ Row(modifier = Modifier.fillMaxWidth(),horizontalArrangement = Arrangement.Center) { Text(text = model.frameDesc,style = MaterialTheme.typography.h4) } @@ -235,7 +209,7 @@ fun Title(model:RegAssociationViewModel= viewModel()){ * @param model */ @Composable -fun Name(model:RegAssociationViewModel= viewModel()){ +private fun Name(model:RegAssociationViewModel= viewModel()){ BaseTextField(form = model.name,singeLine = true,modifier = Modifier.fillMaxWidth()) } @@ -244,15 +218,6 @@ fun Name(model:RegAssociationViewModel= viewModel()){ * @param model */ @Composable -fun Desc(model:RegAssociationViewModel= viewModel(),modifier:Modifier){ +private fun Desc(model:RegAssociationViewModel= viewModel(),modifier:Modifier){ BaseTextField(form = model.desc,modifier = modifier) } - - -@Preview -@Composable -fun NamePreview(){ - val model=RegAssociationViewModel() - Body(model=model) - -} \ No newline at end of file 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 8174c8f..52b44a0 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 @@ -183,13 +183,4 @@ class ListViewModel:ViewModel(){ */ class CenterViewModel:ViewModel(){ val myAssociationDesc="我的社团" - - /** - * TODO 打开我的社团 - * - * @param callback - */ - fun openMyAssociation(callback: (value: String) -> Unit){ - 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 0d6127d..5393a15 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 @@ -24,11 +24,11 @@ import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.lifecycle.viewmodel.compose.viewModel -import androidx.navigation.NavController +import androidx.navigation.NavHostController import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable -import androidx.navigation.compose.rememberNavController import com.gyf.csams.R +import com.gyf.csams.association.ui.AssociationActivity import com.gyf.csams.association.ui.RegAssociationActivity import com.gyf.csams.main.model.* import com.gyf.csams.uikit.* @@ -45,38 +45,27 @@ class MainActivity : ComponentActivity() { setContent { CSAMSTheme { - Body() - } - } - - - } -} + Body { nav, scaffoldState -> + NavHost(navController = nav, startDestination = MainMenu.Main.name) { + composable(MainMenu.Main.name) { + Main(navController = nav) + ShowSnackbar(scaffoldState = scaffoldState) + } + composable(MainMenu.List.name) { + AssociationList(navController = nav) + ShowSnackbar(scaffoldState = scaffoldState) + } + composable(MainMenu.Center.name) { + Center(navController = nav) + ShowSnackbar(scaffoldState = scaffoldState) + } + } -@Composable -fun Body() { - // A surface container using the 'background' color from the theme - Surface(color = MaterialTheme.colors.background) { - val navController = rememberNavController() - val scaffoldState = rememberScaffoldState() - - Scaffold(scaffoldState = scaffoldState) { - NavHost(navController, startDestination = MainMenu.Main.name) { - composable(MainMenu.Main.name) { - Main(navController = navController) - ShowSnackbar(scaffoldState = scaffoldState) - } - composable(MainMenu.List.name) { - AssociationList(navController = navController) - ShowSnackbar(scaffoldState = scaffoldState) - } - composable(MainMenu.Center.name) { - Center(navController = navController) - ShowSnackbar(scaffoldState = scaffoldState) } } } + } } @@ -85,16 +74,17 @@ fun Body() { * */ @Composable -fun Center(model:CenterViewModel= viewModel(), scaffoldModel: ScaffoldModel= viewModel(), navController: NavController){ +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 = { - model.openMyAssociation { scaffoldModel.update(it) } + 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) { @@ -121,7 +111,7 @@ fun Center(model:CenterViewModel= viewModel(), scaffoldModel: ScaffoldModel= vie * 主界面 */ @Composable -fun Main(navController: NavController) { +private fun Main(navController: NavHostController) { MainFrame(background = { Background(image = BackgroundImage.main) }, mainMenu = MainMenu.Main, nav = navController) { Column(modifier = Modifier.weight(0.33F)) { Notification() @@ -143,7 +133,7 @@ fun Main(navController: NavController) { * @param navController */ @Composable -fun AssociationList(navController: NavController) { +private fun AssociationList(navController: NavHostController) { MainFrame( background = { Background(image = BackgroundImage.list) }, mainMenu = MainMenu.List, @@ -160,7 +150,7 @@ fun AssociationList(navController: NavController) { * */ @Composable -fun RegisterAssociation() { +private fun RegisterAssociation() { val context= LocalContext.current Row( horizontalArrangement = Arrangement.End, @@ -185,7 +175,7 @@ fun RegisterAssociation() { * */ @Composable -fun AssociationListBody(model: ListViewModel = viewModel(),scaffoldModel: ScaffoldModel= viewModel()) { +private fun AssociationListBody(model: ListViewModel = viewModel(),scaffoldModel: ScaffoldModel= viewModel()) { val associationList: MutableList? by model.associationDto.observeAsState() val listState = rememberLazyListState() @@ -222,8 +212,9 @@ fun AssociationListBody(model: ListViewModel = viewModel(),scaffoldModel: Scaffo } @Composable -fun Association(associationDto: AssociationDto) { - Card { +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 @@ -242,7 +233,7 @@ fun Association(associationDto: AssociationDto) { * */ @Composable -fun AssociationSearch(model: ListViewModel = viewModel(),scaffoldModel: ScaffoldModel= viewModel()) { +private fun AssociationSearch(model: ListViewModel = viewModel(),scaffoldModel: ScaffoldModel= viewModel()) { Card(modifier = Modifier.padding(horizontal = 50.dp, vertical = 10.dp)) { Column { @@ -271,7 +262,7 @@ fun AssociationSearch(model: ListViewModel = viewModel(),scaffoldModel: Scaffold * */ @Composable -fun Notification(mainViewModel: MainViewModel= viewModel(),scaffoldModel: ScaffoldModel= viewModel()) { +private fun Notification(mainViewModel: MainViewModel= viewModel(),scaffoldModel: ScaffoldModel= viewModel()) { Row( horizontalArrangement = Arrangement.End, modifier = Modifier @@ -295,7 +286,7 @@ fun Notification(mainViewModel: MainViewModel= viewModel(),scaffoldModel: Scaffo * */ @Composable -fun MyBorder(content: @Composable BoxScope.() -> Unit) { +private fun MyBorder(content: @Composable BoxScope.() -> Unit) { Box(modifier = Modifier.padding(horizontal = 15.dp)) { Box( modifier = Modifier @@ -315,7 +306,7 @@ fun MyBorder(content: @Composable BoxScope.() -> Unit) { * */ @Composable -fun MessageBoard(model: MarqueeViewModel = viewModel(),mainViewModel:MainViewModel= viewModel(),scaffoldModel: ScaffoldModel= viewModel()) { +private fun MessageBoard(model: MarqueeViewModel = viewModel(),mainViewModel:MainViewModel= viewModel(),scaffoldModel: ScaffoldModel= viewModel()) { MyBorder { Row( verticalAlignment = Alignment.CenterVertically @@ -350,7 +341,7 @@ fun MessageBoard(model: MarqueeViewModel = viewModel(),mainViewModel:MainViewMod * */ @Composable -fun ClubActivitiesTitle() { +private fun ClubActivitiesTitle() { MyBorder { Row( modifier = Modifier @@ -369,12 +360,13 @@ fun ClubActivitiesTitle() { } } + /** * 活动海报 * */ @Composable -fun ClubActivitiesImage(model: CarouselViewModel = viewModel()) { +private fun ClubActivitiesImage(model: CarouselViewModel = viewModel()) { Carousel(model = model) { Column { Card( @@ -393,35 +385,11 @@ fun ClubActivitiesImage(model: CarouselViewModel = viewModel()) { contentDescription = null ) } - Card( + DescCard( modifier = Modifier .weight(0.4F) - .fillMaxWidth(), - 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)) - Text( - text = "文字对任何界面都属于核心内容,而利用 Jetpack Compose 可以更轻松地显示或写入文字。Compose 可以充分利用其构建块的组合,这意味着您无需覆盖各种属性和方法,也无需扩展大型类,即可拥有特定的可组合项设计以及按您期望的方式运行的逻辑。" - .repeat(10), overflow = TextOverflow.Ellipsis, - modifier = Modifier.weight(0.8F) - ) - Spacer(modifier = Modifier.weight(0.1F)) - } - Spacer(modifier = Modifier.weight(0.2F)) - - } - } + .fillMaxWidth() + ) } } } 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 68a6d4f..0478bf9 100644 --- a/app/src/main/java/com/gyf/csams/uikit/BaseView.kt +++ b/app/src/main/java/com/gyf/csams/uikit/BaseView.kt @@ -5,6 +5,7 @@ import androidx.compose.animation.Crossfade import androidx.compose.animation.animateColor import androidx.compose.animation.core.* import androidx.compose.foundation.Image +import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.* import androidx.compose.foundation.text.KeyboardActions import androidx.compose.foundation.text.KeyboardOptions @@ -14,7 +15,9 @@ import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.State import androidx.compose.runtime.getValue import androidx.compose.runtime.livedata.observeAsState +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.DefaultAlpha import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.platform.LocalContext @@ -25,7 +28,7 @@ import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.lifecycle.viewmodel.compose.viewModel -import androidx.navigation.NavController +import androidx.navigation.NavHostController import androidx.navigation.compose.navigate import androidx.navigation.compose.rememberNavController import com.gyf.csams.APP @@ -96,14 +99,14 @@ fun MenuIconButton(_menu: MainMenu,menu: MainMenu,modifier: Modifier,onClick: () } /** - * 底部菜单 + * 主界面底部菜单 * * @param menu * @param nav * @param modifier */ @Composable -fun MainBottomAppBar(menu:MainMenu, nav: NavController, modifier: Modifier=Modifier){ +fun MainBottomAppBar(menu:MainMenu, nav: NavHostController, modifier: Modifier=Modifier){ BottomAppBar(backgroundColor = MaterialTheme.colors.background,modifier=modifier) { //图标宽度平等分 @@ -121,6 +124,49 @@ fun MainBottomAppBar(menu:MainMenu, nav: NavController, modifier: Modifier=Modif } +/** + * 社团菜单 + * + */ +enum class AssociationMenu(val menuName:String){ + member("社团成员"), + main("社团主页"), + list("活动列表") +} + +/** + * 社团顶部菜单 + * + */ +@Composable +fun AssociationAppBar(menu: AssociationMenu,nav: NavHostController,back:()->Unit,dropMenu:()->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) + } + } + } + IconButton(onClick = dropMenu,modifier = Modifier.weight(0.1F)) { + Icon(painter = painterResource(id = R.drawable.ic_configuration), contentDescription = null) + } + } + } +} /** * 跑马灯 * @@ -186,7 +232,7 @@ fun MarqueeText(model: MarqueeViewModel = viewModel(), offset: State) { * @param body 内容 */ @Composable -fun MainFrame( background:@Composable ()->Unit,mainMenu: MainMenu,nav: NavController,body:@Composable ColumnScope.()->Unit){ +fun MainFrame( background:@Composable ()->Unit,mainMenu: MainMenu,nav: NavHostController,body:@Composable ColumnScope.()->Unit){ Box(modifier = Modifier.fillMaxSize()) { background() Column { @@ -289,7 +335,9 @@ enum class BackgroundImage(@DrawableRes val id:Int){ //个人中心 center(R.drawable.mb_bg_fb_28), //注册社团 - reg_association(R.drawable.mb_bg_fb_07) + reg_association(R.drawable.mb_bg_fb_06), + //社团主界面 + association_main(R.drawable.mb_bg_fb_25_180) } /** @@ -313,6 +361,75 @@ fun Background(image: BackgroundImage, alpha:Float= DefaultAlpha){ } } +/** + * + * + * @param content + */ +@Composable +fun Body(content:@Composable (scaffoldState:ScaffoldState)->Unit){ + Surface(color = MaterialTheme.colors.background) { + val scaffoldState = rememberScaffoldState() + + Scaffold(scaffoldState = scaffoldState) { + content(scaffoldState=scaffoldState) + } + } +} + +/** + * 带导航的主体 + * + * @param content + */ +@Composable +fun Body( content:@Composable (nav:NavHostController, scaffoldState:ScaffoldState)->Unit){ + Surface(color = MaterialTheme.colors.background) { + val navController = rememberNavController() + val scaffoldState = rememberScaffoldState() + + Scaffold(scaffoldState = scaffoldState) { + content(nav=navController,scaffoldState=scaffoldState) + } + } +} + +/** + * 介绍卡片 + * + */ +@Composable +fun DescCard(modifier: Modifier){ + 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)) + Text( + text = "文字对任何界面都属于核心内容,而利用 Jetpack Compose 可以更轻松地显示或写入文字。Compose 可以充分利用其构建块的组合,这意味着您无需覆盖各种属性和方法,也无需扩展大型类,即可拥有特定的可组合项设计以及按您期望的方式运行的逻辑。" + .repeat(10), overflow = TextOverflow.Ellipsis, + modifier = Modifier.weight(0.8F) + ) + Spacer(modifier = Modifier.weight(0.1F)) + } + Spacer(modifier = Modifier.weight(0.2F)) + + } + } +} + + @Preview @Composable fun AnimationTextPreview(){ @@ -322,13 +439,7 @@ fun AnimationTextPreview(){ //@Preview @Composable fun MyBottomAppBarPreview(){ - val nav= rememberNavController() CSAMSTheme { - Surface(color = MaterialTheme.colors.background) { - Column() { - } - MainBottomAppBar(menu = MainMenu.Main, nav = nav) - } } } \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_arrow_down.xml b/app/src/main/res/drawable/ic_arrow_down.xml new file mode 100644 index 0000000..c5bf6f6 --- /dev/null +++ b/app/src/main/res/drawable/ic_arrow_down.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_arrow_left.xml b/app/src/main/res/drawable/ic_arrow_left.xml new file mode 100644 index 0000000..1b9112f --- /dev/null +++ b/app/src/main/res/drawable/ic_arrow_left.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/ic_configuration.xml b/app/src/main/res/drawable/ic_configuration.xml new file mode 100644 index 0000000..af06925 --- /dev/null +++ b/app/src/main/res/drawable/ic_configuration.xml @@ -0,0 +1,9 @@ + + +