界面逻辑封装

增加社团界面
master
pan 4 years ago
parent 014d4ae16c
commit 743486211b
  1. 4
      app/src/main/AndroidManifest.xml
  2. 99
      app/src/main/java/com/gyf/csams/account/ui/AccountActivity.kt
  3. 84
      app/src/main/java/com/gyf/csams/association/model/AssociationViewModel.kt
  4. 263
      app/src/main/java/com/gyf/csams/association/ui/AssociationActivity.kt
  5. 107
      app/src/main/java/com/gyf/csams/association/ui/RegAssociationActivity.kt
  6. 9
      app/src/main/java/com/gyf/csams/main/model/MainViewModel.kt
  7. 108
      app/src/main/java/com/gyf/csams/main/ui/MainActivity.kt
  8. 133
      app/src/main/java/com/gyf/csams/uikit/BaseView.kt
  9. 9
      app/src/main/res/drawable/ic_arrow_down.xml
  10. 9
      app/src/main/res/drawable/ic_arrow_left.xml
  11. 9
      app/src/main/res/drawable/ic_configuration.xml

@ -44,6 +44,10 @@
<activity android:name=".association.ui.RegAssociationActivity" <activity android:name=".association.ui.RegAssociationActivity"
android:exported="true"> android:exported="true">
</activity> </activity>
<activity android:name=".association.ui.AssociationActivity"
android:exported="true">
</activity>
</application> </application>
</manifest> </manifest>

@ -27,11 +27,11 @@ 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 androidx.navigation.compose.navigate import androidx.navigation.compose.navigate
import androidx.navigation.compose.rememberNavController
import com.gyf.csams.BuildConfig import com.gyf.csams.BuildConfig
import com.gyf.csams.account.model.AccountViewModel import com.gyf.csams.account.model.AccountViewModel
import com.gyf.csams.account.model.DialogMessage import com.gyf.csams.account.model.DialogMessage
import com.gyf.csams.uikit.AnimationText import com.gyf.csams.uikit.AnimationText
import com.gyf.csams.uikit.Body
import com.gyf.csams.uikit.theme.CSAMSTheme import com.gyf.csams.uikit.theme.CSAMSTheme
@ -46,62 +46,57 @@ class AccountActivity: ComponentActivity() {
setContent { setContent {
CSAMSTheme { CSAMSTheme {
// A surface container using the 'background' color from the theme Body {
Surface(color = MaterialTheme.colors.background) { nav, scaffoldState ->
val navController = rememberNavController() NavHost(navController = nav, startDestination = AccountRoute.login.name) {
val scaffoldState = rememberScaffoldState() composable(AccountRoute.login.name) {
Account(scaffoldState=scaffoldState,route = AccountRoute.login) { isValidForm: Boolean, accountViewModel: AccountViewModel ->
Scaffold(scaffoldState=scaffoldState) { Spacer(modifier = Modifier.height(10.dp))
NavHost(navController, startDestination = AccountRoute.login.name) {
composable(AccountRoute.login.name) { OutlinedButton(onClick = {accountViewModel.login()},
Account(scaffoldState=scaffoldState,route = AccountRoute.login) { isValidForm: Boolean, accountViewModel: AccountViewModel -> enabled = isValidForm,
Spacer(modifier = Modifier.height(10.dp)) modifier = Modifier
.fillMaxWidth()
OutlinedButton(onClick = {accountViewModel.login()}, .padding(bottom = 10.dp)) {
enabled = isValidForm,
modifier = Modifier Text(text = accountViewModel.loginDesc)
.fillMaxWidth() }
.padding(bottom = 10.dp)) {
val finishLogin:Boolean? by accountViewModel.finishLogin.observeAsState()
Text(text = accountViewModel.loginDesc) if(finishLogin==true){
} finish()
}
val finishLogin:Boolean? by accountViewModel.finishLogin.observeAsState()
if(finishLogin==true){ OutlinedButton(onClick = { nav.navigate(AccountRoute.register.name)},
finish() modifier = Modifier.fillMaxWidth(),
} colors = ButtonDefaults.outlinedButtonColors(
contentColor = MaterialTheme.colors.onBackground)) {
OutlinedButton(onClick = { navController.navigate(AccountRoute.register.name)}, Text(text = accountViewModel.goRegister)
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) { OutlinedButton(onClick = { nav.navigate(AccountRoute.login.name)},
Account(scaffoldState=scaffoldState,route = AccountRoute.register) { isValidForm: Boolean, accountViewModel: AccountViewModel -> modifier = Modifier.fillMaxWidth(),
Spacer(modifier = Modifier.height(10.dp)) colors = ButtonDefaults.outlinedButtonColors(
contentColor = MaterialTheme.colors.onBackground)) {
OutlinedButton(onClick = { accountViewModel.register()}, Text(text = accountViewModel.backLogin)
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)
}
}
} }
} }
}
} }
} }
} }

@ -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<AssociationMenu>()
val currentMenu:LiveData<AssociationMenu> = _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<MutableList<MemberVo>>(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<MemberVo>()
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("功能尚未实现,敬请期待")
}
}

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

@ -2,7 +2,6 @@ package com.gyf.csams.association.ui
import android.Manifest import android.Manifest
import android.app.Activity import android.app.Activity
import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.pm.PackageManager import android.content.pm.PackageManager
import android.graphics.BitmapFactory import android.graphics.BitmapFactory
@ -12,13 +11,15 @@ import android.provider.MediaStore
import androidx.activity.ComponentActivity import androidx.activity.ComponentActivity
import androidx.activity.compose.rememberLauncherForActivityResult import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.compose.setContent import androidx.activity.compose.setContent
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.foundation.Image import androidx.compose.foundation.Image
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.border import androidx.compose.foundation.border
import androidx.compose.foundation.layout.* 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.Composable
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.livedata.observeAsState 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.graphics.asImageBitmap
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.unit.dp import androidx.compose.ui.unit.dp
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.lifecycle.viewmodel.compose.viewModel import androidx.lifecycle.viewmodel.compose.viewModel
@ -48,63 +48,37 @@ class RegAssociationActivity: ComponentActivity(){
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContent { setContent {
CSAMSTheme { CSAMSTheme {
Body() Body {
} scaffoldState ->
} MainFrame(background = { Background(BackgroundImage.reg_association,alpha = 0.5F) }) {
} Spacer(
modifier = Modifier
} .weight(0.1F)
)
@Composable Title()
fun Body(model:RegAssociationViewModel= viewModel()){ Name()
val scaffoldState = rememberScaffoldState() Desc(
Scaffold(scaffoldState = scaffoldState) { modifier = Modifier
Surface(color = MaterialTheme.colors.background) { .weight(0.1F)
MainFrame(background = { Background(BackgroundImage.reg_association,alpha = 0.7F) }) { .fillMaxWidth()
Spacer( )
modifier = Modifier Spacer(modifier = Modifier.weight(0.05F))
.weight(0.1F) Logo(
) modifier = Modifier
Title(model = model) .weight(0.2F)
Name(model = model) .fillMaxWidth()
Desc( )
model = model, modifier = Modifier Spacer(modifier = Modifier.weight(0.05F))
.weight(0.1F) BottomButton(modifier = Modifier.fillMaxWidth())
.fillMaxWidth() Spacer(modifier = Modifier.weight(0.05F))
)
Spacer(modifier = Modifier.weight(0.05F)) ShowSnackbar(scaffoldState = scaffoldState)
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<String>,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)
}
}
} }
/** /**
@ -113,7 +87,7 @@ fun PermissionHandle(context: Context, launcher: ActivityResultLauncher<String>,
* @param modifier * @param modifier
*/ */
@Composable @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) val photoIntent=Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI)
photoIntent.type = "image/*" photoIntent.type = "image/*"
val uri:Uri? by model.picture.observeAsState() val uri:Uri? by model.picture.observeAsState()
@ -201,7 +175,7 @@ fun Logo(model:RegAssociationViewModel= viewModel(),modifier: Modifier) {
} }
@Composable @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 val context= LocalContext.current as RegAssociationActivity
Row(modifier = modifier,horizontalArrangement = Arrangement.Center) { Row(modifier = modifier,horizontalArrangement = Arrangement.Center) {
OutlinedButton(onClick = { OutlinedButton(onClick = {
@ -224,7 +198,7 @@ fun BottomButton(modifier: Modifier=Modifier,scaffoldModel: ScaffoldModel= viewM
* *
*/ */
@Composable @Composable
fun Title(model:RegAssociationViewModel= viewModel()){ private fun Title(model:RegAssociationViewModel= viewModel()){
Row(modifier = Modifier.fillMaxWidth(),horizontalArrangement = Arrangement.Center) { Row(modifier = Modifier.fillMaxWidth(),horizontalArrangement = Arrangement.Center) {
Text(text = model.frameDesc,style = MaterialTheme.typography.h4) Text(text = model.frameDesc,style = MaterialTheme.typography.h4)
} }
@ -235,7 +209,7 @@ fun Title(model:RegAssociationViewModel= viewModel()){
* @param model * @param model
*/ */
@Composable @Composable
fun Name(model:RegAssociationViewModel= viewModel()){ private fun Name(model:RegAssociationViewModel= viewModel()){
BaseTextField(form = model.name,singeLine = true,modifier = Modifier.fillMaxWidth()) BaseTextField(form = model.name,singeLine = true,modifier = Modifier.fillMaxWidth())
} }
@ -244,15 +218,6 @@ fun Name(model:RegAssociationViewModel= viewModel()){
* @param model * @param model
*/ */
@Composable @Composable
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)
} }
@Preview
@Composable
fun NamePreview(){
val model=RegAssociationViewModel()
Body(model=model)
}

@ -183,13 +183,4 @@ class ListViewModel:ViewModel(){
*/ */
class CenterViewModel:ViewModel(){ class CenterViewModel:ViewModel(){
val myAssociationDesc="我的社团" val myAssociationDesc="我的社团"
/**
* TODO 打开我的社团
*
* @param callback
*/
fun openMyAssociation(callback: (value: String) -> Unit){
callback("功能尚未实现,敬请期待")
}
} }

@ -24,11 +24,11 @@ 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.viewmodel.compose.viewModel import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.NavController import androidx.navigation.NavHostController
import androidx.navigation.compose.NavHost import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController
import com.gyf.csams.R import com.gyf.csams.R
import com.gyf.csams.association.ui.AssociationActivity
import com.gyf.csams.association.ui.RegAssociationActivity 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.*
@ -45,38 +45,27 @@ class MainActivity : ComponentActivity() {
setContent { setContent {
CSAMSTheme { 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 @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) { 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) {
Card(backgroundColor = MaterialTheme.colors.background) { Card(backgroundColor = MaterialTheme.colors.background) {
val context= LocalContext.current
Row(modifier = Modifier Row(modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.clickable(onClick = { .clickable(onClick = {
model.openMyAssociation { scaffoldModel.update(it) } context.startActivity(Intent(context, AssociationActivity::class.java))
}),verticalAlignment = Alignment.CenterVertically) { }),verticalAlignment = Alignment.CenterVertically) {
Spacer(modifier = Modifier.weight(0.33F)) Spacer(modifier = Modifier.weight(0.33F))
Row(modifier = Modifier.weight(0.33F),horizontalArrangement = Arrangement.Center) { Row(modifier = Modifier.weight(0.33F),horizontalArrangement = Arrangement.Center) {
@ -121,7 +111,7 @@ fun Center(model:CenterViewModel= viewModel(), scaffoldModel: ScaffoldModel= vie
* 主界面 * 主界面
*/ */
@Composable @Composable
fun Main(navController: NavController) { 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()
@ -143,7 +133,7 @@ fun Main(navController: NavController) {
* @param navController * @param navController
*/ */
@Composable @Composable
fun AssociationList(navController: NavController) { private fun AssociationList(navController: NavHostController) {
MainFrame( MainFrame(
background = { Background(image = BackgroundImage.list) }, background = { Background(image = BackgroundImage.list) },
mainMenu = MainMenu.List, mainMenu = MainMenu.List,
@ -160,7 +150,7 @@ fun AssociationList(navController: NavController) {
* *
*/ */
@Composable @Composable
fun RegisterAssociation() { private fun RegisterAssociation() {
val context= LocalContext.current val context= LocalContext.current
Row( Row(
horizontalArrangement = Arrangement.End, horizontalArrangement = Arrangement.End,
@ -185,7 +175,7 @@ fun RegisterAssociation() {
* *
*/ */
@Composable @Composable
fun AssociationListBody(model: ListViewModel = viewModel(),scaffoldModel: ScaffoldModel= viewModel()) { private fun AssociationListBody(model: ListViewModel = viewModel(),scaffoldModel: ScaffoldModel= viewModel()) {
val associationList: MutableList<AssociationDto>? by model.associationDto.observeAsState() val associationList: MutableList<AssociationDto>? by model.associationDto.observeAsState()
val listState = rememberLazyListState() val listState = rememberLazyListState()
@ -222,8 +212,9 @@ fun AssociationListBody(model: ListViewModel = viewModel(),scaffoldModel: Scaffo
} }
@Composable @Composable
fun Association(associationDto: AssociationDto) { private fun Association(associationDto: AssociationDto) {
Card { val context= LocalContext.current
Card(modifier = Modifier.clickable(onClick = { context.startActivity(Intent(context,AssociationActivity::class.java)) })) {
Image( Image(
painter = painterResource(id = R.drawable.association_list_border), painter = painterResource(id = R.drawable.association_list_border),
contentDescription = null contentDescription = null
@ -242,7 +233,7 @@ fun Association(associationDto: AssociationDto) {
* *
*/ */
@Composable @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)) { Card(modifier = Modifier.padding(horizontal = 50.dp, vertical = 10.dp)) {
Column { Column {
@ -271,7 +262,7 @@ fun AssociationSearch(model: ListViewModel = viewModel(),scaffoldModel: Scaffold
* *
*/ */
@Composable @Composable
fun Notification(mainViewModel: MainViewModel= viewModel(),scaffoldModel: ScaffoldModel= viewModel()) { private fun Notification(mainViewModel: MainViewModel= viewModel(),scaffoldModel: ScaffoldModel= viewModel()) {
Row( Row(
horizontalArrangement = Arrangement.End, horizontalArrangement = Arrangement.End,
modifier = Modifier modifier = Modifier
@ -295,7 +286,7 @@ fun Notification(mainViewModel: MainViewModel= viewModel(),scaffoldModel: Scaffo
* *
*/ */
@Composable @Composable
fun MyBorder(content: @Composable BoxScope.() -> Unit) { private fun MyBorder(content: @Composable BoxScope.() -> Unit) {
Box(modifier = Modifier.padding(horizontal = 15.dp)) { Box(modifier = Modifier.padding(horizontal = 15.dp)) {
Box( Box(
modifier = Modifier modifier = Modifier
@ -315,7 +306,7 @@ fun MyBorder(content: @Composable BoxScope.() -> Unit) {
* *
*/ */
@Composable @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 { MyBorder {
Row( Row(
verticalAlignment = Alignment.CenterVertically verticalAlignment = Alignment.CenterVertically
@ -350,7 +341,7 @@ fun MessageBoard(model: MarqueeViewModel = viewModel(),mainViewModel:MainViewMod
* *
*/ */
@Composable @Composable
fun ClubActivitiesTitle() { private fun ClubActivitiesTitle() {
MyBorder { MyBorder {
Row( Row(
modifier = Modifier modifier = Modifier
@ -369,12 +360,13 @@ fun ClubActivitiesTitle() {
} }
} }
/** /**
* 活动海报 * 活动海报
* *
*/ */
@Composable @Composable
fun ClubActivitiesImage(model: CarouselViewModel = viewModel()) { private fun ClubActivitiesImage(model: CarouselViewModel = viewModel()) {
Carousel(model = model) { Carousel(model = model) {
Column { Column {
Card( Card(
@ -393,35 +385,11 @@ fun ClubActivitiesImage(model: CarouselViewModel = viewModel()) {
contentDescription = null contentDescription = null
) )
} }
Card( DescCard(
modifier = Modifier modifier = Modifier
.weight(0.4F) .weight(0.4F)
.fillMaxWidth(), .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))
}
}
} }
} }
} }

@ -5,6 +5,7 @@ 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.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
@ -14,7 +15,9 @@ import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.State import androidx.compose.runtime.State
import androidx.compose.runtime.getValue 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.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.DefaultAlpha import androidx.compose.ui.graphics.DefaultAlpha
import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalContext 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.tooling.preview.Preview
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.lifecycle.viewmodel.compose.viewModel import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.NavController import androidx.navigation.NavHostController
import androidx.navigation.compose.navigate import androidx.navigation.compose.navigate
import androidx.navigation.compose.rememberNavController import androidx.navigation.compose.rememberNavController
import com.gyf.csams.APP import com.gyf.csams.APP
@ -96,14 +99,14 @@ fun MenuIconButton(_menu: MainMenu,menu: MainMenu,modifier: Modifier,onClick: ()
} }
/** /**
* 底部菜单 * 主界面底部菜单
* *
* @param menu * @param menu
* @param nav * @param nav
* @param modifier * @param modifier
*/ */
@Composable @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) { 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<Float>) {
* @param body 内容 * @param body 内容
*/ */
@Composable @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()) { Box(modifier = Modifier.fillMaxSize()) {
background() background()
Column { Column {
@ -289,7 +335,9 @@ enum class BackgroundImage(@DrawableRes val id:Int){
//个人中心 //个人中心
center(R.drawable.mb_bg_fb_28), 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 @Preview
@Composable @Composable
fun AnimationTextPreview(){ fun AnimationTextPreview(){
@ -322,13 +439,7 @@ fun AnimationTextPreview(){
//@Preview //@Preview
@Composable @Composable
fun MyBottomAppBarPreview(){ fun MyBottomAppBarPreview(){
val nav= rememberNavController()
CSAMSTheme { CSAMSTheme {
Surface(color = MaterialTheme.colors.background) {
Column() {
}
MainBottomAppBar(menu = MainMenu.Main, nav = nav)
}
} }
} }

@ -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="M500.8,604.78L267.31,371.39l-45.23,45.27 278.74,278.61L779.31,416.66l-45.25,-45.25z"/>
</vector>

@ -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="M641.28,278.61l-45.23,-45.23 -278.63,278.76 278.61,278.49 45.25,-45.27 -233.37,-233.24z"/>
</vector>

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="211.71875dp"
android:height="200dp"
android:viewportWidth="1084"
android:viewportHeight="1024">
<path
android:fillColor="#FF000000"
android:pathData="M825.22,90.35c-18.07,-36.14 -60.24,-60.24 -102.4,-60.24s-84.33,24.09 -102.4,60.24H0v120.47h620.42c18.07,36.14 60.24,60.24 102.4,60.24s84.33,-24.09 102.4,-60.24H1084.24v-120.47h-259.01zM542.12,391.53c-42.16,0 -78.31,24.09 -102.4,54.21H0v120.47h433.69c18.07,36.14 60.24,66.26 108.42,66.26s84.33,-24.09 108.42,-66.26H1084.24v-120.47h-439.72c-24.09,-30.12 -60.24,-54.21 -102.4,-54.21zM783.06,752.94c-42.16,0 -72.28,18.07 -96.38,48.19H0v120.47h674.64c18.07,42.16 60.24,72.28 108.42,72.28s90.35,-30.12 108.42,-72.28H1084.24v-120.47h-204.8c-24.09,-30.12 -54.21,-48.19 -96.38,-48.19z"/>
</vector>
Loading…
Cancel
Save