You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
781 lines
21 KiB
781 lines
21 KiB
package com.gyf.csams.uikit
|
|
|
|
import android.app.Activity
|
|
import androidx.annotation.DrawableRes
|
|
import androidx.compose.animation.Crossfade
|
|
import androidx.compose.animation.animateColor
|
|
import androidx.compose.animation.core.*
|
|
import androidx.compose.foundation.Image
|
|
import androidx.compose.foundation.border
|
|
import androidx.compose.foundation.clickable
|
|
import androidx.compose.foundation.layout.*
|
|
import androidx.compose.foundation.text.KeyboardActions
|
|
import androidx.compose.foundation.text.KeyboardOptions
|
|
import androidx.compose.material.*
|
|
import androidx.compose.runtime.*
|
|
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.graphics.ImageBitmap
|
|
import androidx.compose.ui.layout.ContentScale
|
|
import androidx.compose.ui.platform.LocalContext
|
|
import androidx.compose.ui.platform.LocalFocusManager
|
|
import androidx.compose.ui.res.painterResource
|
|
import androidx.compose.ui.text.input.ImeAction
|
|
import androidx.compose.ui.text.input.VisualTransformation
|
|
import androidx.compose.ui.text.style.TextOverflow
|
|
import androidx.compose.ui.unit.dp
|
|
import androidx.lifecycle.LiveData
|
|
import androidx.lifecycle.MutableLiveData
|
|
import androidx.lifecycle.viewmodel.compose.viewModel
|
|
import androidx.navigation.NavHostController
|
|
import androidx.navigation.compose.navigate
|
|
import androidx.navigation.compose.rememberNavController
|
|
import com.gyf.csams.APP
|
|
import com.gyf.csams.R
|
|
import com.gyf.csams.main.model.MarqueeViewModel
|
|
import com.orhanobut.logger.Logger
|
|
import kotlinx.coroutines.launch
|
|
|
|
/**
|
|
* 淡入淡出并且颜色变化文本
|
|
*
|
|
* @param text
|
|
*/
|
|
@Composable
|
|
fun AnimationText(text: String) {
|
|
val infiniteTransition = rememberInfiniteTransition()
|
|
val color by infiniteTransition.animateColor(
|
|
initialValue = MaterialTheme.colors.primary,
|
|
targetValue = MaterialTheme.colors.onPrimary,
|
|
animationSpec = infiniteRepeatable(
|
|
animation = tween(1000, easing = LinearEasing),
|
|
repeatMode = RepeatMode.Reverse
|
|
)
|
|
)
|
|
|
|
Text(
|
|
text = text,
|
|
color = color,
|
|
style = MaterialTheme.typography.body1
|
|
)
|
|
}
|
|
|
|
/**
|
|
* 主菜单
|
|
*
|
|
*/
|
|
enum class MainMenu(
|
|
@DrawableRes val selectedIcon: Int,
|
|
@DrawableRes val unSelectedIcon: Int
|
|
) {
|
|
//主页
|
|
Main(R.drawable.ic_home_fill, R.drawable.ic_home),
|
|
|
|
//社团列表
|
|
List(R.drawable.ic_all_fill, R.drawable.ic_all),
|
|
|
|
//个人中心
|
|
Center(R.drawable.ic_account_fill, R.drawable.ic_account)
|
|
}
|
|
|
|
/**
|
|
* 底部菜单按钮
|
|
*
|
|
* @param _menu
|
|
* @param menu
|
|
* @param modifier
|
|
* @param onClick
|
|
*/
|
|
@Composable
|
|
fun MenuIconButton(
|
|
_menu: MainMenu,
|
|
menu: MainMenu,
|
|
modifier: Modifier = Modifier,
|
|
onClick: () -> Unit
|
|
) {
|
|
Row(
|
|
modifier = modifier, horizontalArrangement = Arrangement.Center
|
|
) {
|
|
IconButton(onClick = onClick) {
|
|
Icon(
|
|
painter = painterResource(id = if (_menu == menu) menu.selectedIcon else menu.unSelectedIcon),
|
|
contentDescription = null
|
|
)
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 主界面底部菜单
|
|
*
|
|
* @param menu
|
|
* @param nav
|
|
* @param modifier
|
|
*/
|
|
@Composable
|
|
fun MainBottomAppBar(menu: MainMenu, nav: NavHostController, modifier: Modifier = Modifier) {
|
|
BottomAppBar(backgroundColor = MaterialTheme.colors.background, modifier = modifier) {
|
|
Row(Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween) {
|
|
MenuIconButton(_menu = menu, menu = MainMenu.Main,
|
|
onClick = { nav.navigate(MainMenu.Main.name) })
|
|
MenuIconButton(_menu = menu, menu = MainMenu.List,
|
|
onClick = { nav.navigate(MainMenu.List.name) })
|
|
MenuIconButton(_menu = menu, menu = MainMenu.Center,
|
|
onClick = { nav.navigate(MainMenu.Center.name) })
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
|
|
/**
|
|
* 顶部菜单
|
|
*
|
|
*/
|
|
interface TopMenuInterface<T : TopBarMenu> {
|
|
/**
|
|
* 当前菜单
|
|
*/
|
|
val _currentMenu: MutableLiveData<T>
|
|
val currentMenu: LiveData<T>
|
|
|
|
/**
|
|
* 切换顶部菜单
|
|
*
|
|
* @param menu
|
|
*/
|
|
fun clickMenu(menu: T) {
|
|
_currentMenu.value = menu
|
|
}
|
|
}
|
|
|
|
interface TopBarMenu {
|
|
val menuName: String
|
|
|
|
val name: String
|
|
}
|
|
|
|
|
|
interface StartMenu<T> {
|
|
val startMenu: T
|
|
}
|
|
|
|
/**
|
|
* 社团菜单
|
|
*
|
|
*/
|
|
enum class AssociationMenu(override val menuName: String) : TopBarMenu {
|
|
Member("社团成员"),
|
|
Main("社团主页"),
|
|
ActivityList("活动列表");
|
|
|
|
companion object Menu : StartMenu<AssociationMenu> {
|
|
override val startMenu: AssociationMenu = Main
|
|
}
|
|
}
|
|
|
|
enum class ActivityDetailMenu(override val menuName: String) : TopBarMenu {
|
|
Info("活动信息"),
|
|
Photo("相册"),
|
|
Member("活动成员"),
|
|
BBS("交流区");
|
|
|
|
companion object Menu : StartMenu<ActivityDetailMenu> {
|
|
override val startMenu: ActivityDetailMenu = Info
|
|
}
|
|
}
|
|
|
|
|
|
interface SendInterface {
|
|
/**
|
|
* 弹窗状态
|
|
*/
|
|
val _openDialog: MutableLiveData<Boolean>
|
|
val openDialog: LiveData<Boolean>
|
|
|
|
/**
|
|
* 编辑内容
|
|
*/
|
|
val newContent: StringForm
|
|
|
|
/**
|
|
* 打开弹窗
|
|
*
|
|
*/
|
|
fun openDialog()
|
|
|
|
/**
|
|
* 关闭弹窗
|
|
*
|
|
*/
|
|
fun closeDialog()
|
|
|
|
/**
|
|
* 发送评论
|
|
*
|
|
* @param callback
|
|
*/
|
|
fun send(callback: (message: String) -> Unit)
|
|
}
|
|
|
|
/**
|
|
* 发送评论
|
|
*
|
|
* @param T
|
|
* @param model
|
|
* @param scaffoldModel
|
|
*/
|
|
@Composable
|
|
fun <T : SendInterface> SendComment(model: T, scaffoldModel: ScaffoldModel = viewModel()) {
|
|
val openDialog by model.openDialog.observeAsState()
|
|
if (openDialog == true) {
|
|
AlertDialog(onDismissRequest = { /*TODO*/ },
|
|
buttons = {
|
|
Row(
|
|
modifier = Modifier
|
|
.padding(10.dp)
|
|
.fillMaxWidth(),
|
|
horizontalArrangement = Arrangement.SpaceEvenly
|
|
) {
|
|
OutlinedButton(onClick = {
|
|
model.send { scaffoldModel.update(message = it) }
|
|
}) {
|
|
|
|
Text(text = "发送")
|
|
}
|
|
OutlinedButton(onClick = {
|
|
model.closeDialog()
|
|
}) {
|
|
Text(text = "关闭")
|
|
}
|
|
}
|
|
}, text = {
|
|
Column(modifier = Modifier.padding(10.dp)) {
|
|
Card(
|
|
backgroundColor = MaterialTheme.colors.background,
|
|
modifier = Modifier.padding(10.dp)
|
|
) {
|
|
BaseTextField(
|
|
form = model.newContent, modifier = Modifier
|
|
.fillMaxWidth()
|
|
.height(200.dp)
|
|
)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 只包含返回按钮的顶部菜单
|
|
*
|
|
* @param title
|
|
*/
|
|
@Composable
|
|
fun TextTopAppBar(modifier: Modifier = Modifier, title: String) {
|
|
Row(
|
|
modifier = modifier.fillMaxWidth(),
|
|
verticalAlignment = Alignment.CenterVertically
|
|
) {
|
|
val context = LocalContext.current as Activity
|
|
Row(modifier = Modifier.weight(1F / 3)) {
|
|
IconButton(onClick = {
|
|
context.finish()
|
|
}) {
|
|
Icon(
|
|
painter = painterResource(id = R.drawable.ic_arrow_left),
|
|
contentDescription = null
|
|
)
|
|
}
|
|
}
|
|
Row(modifier = Modifier.weight(1F / 3), horizontalArrangement = Arrangement.Center) {
|
|
Text(text = title, style = MaterialTheme.typography.h5)
|
|
}
|
|
Spacer(modifier = Modifier.weight(1F / 3))
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 顶部菜单
|
|
*
|
|
*/
|
|
@Composable
|
|
fun TextTopAppBar(
|
|
nav: NavHostController,
|
|
currentMenuName: String,
|
|
menuNames: Array<out TopBarMenu>,
|
|
iconMenu: (() -> Unit)? = null,
|
|
@DrawableRes icon: Int = R.drawable.ic_configuration,
|
|
dropMenuContent: @Composable () -> Unit = {},
|
|
) {
|
|
TopAppBar(backgroundColor = MaterialTheme.colors.secondary) {
|
|
Row(modifier = Modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically) {
|
|
val context = LocalContext.current as Activity
|
|
IconButton(onClick = { context.finish() }, 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.SpaceAround,
|
|
verticalAlignment = Alignment.CenterVertically
|
|
) {
|
|
menuNames.forEach {
|
|
Row(
|
|
modifier = Modifier
|
|
.weight(1F / menuNames.size)
|
|
.clickable(onClick = { nav.navigate(it.name) }),
|
|
horizontalArrangement = Arrangement.Center
|
|
) {
|
|
Text(
|
|
text = it.menuName,
|
|
color = if (currentMenuName == it.menuName) MaterialTheme.colors.primary else MaterialTheme.colors.onBackground
|
|
)
|
|
}
|
|
}
|
|
}
|
|
if (iconMenu != null) {
|
|
IconButton(onClick = iconMenu, modifier = Modifier.weight(0.1F)) {
|
|
Icon(
|
|
painter = painterResource(id = icon),
|
|
contentDescription = null
|
|
)
|
|
}
|
|
} else {
|
|
Spacer(modifier = Modifier.weight(0.1F))
|
|
}
|
|
}
|
|
if (iconMenu != null) dropMenuContent()
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 跑马灯
|
|
*
|
|
* @param model
|
|
* @param content
|
|
*/
|
|
@Composable
|
|
fun Marquee(
|
|
model: MarqueeViewModel = viewModel(), content: @Composable BoxScope.(
|
|
model: MarqueeViewModel,
|
|
value: State<Float>
|
|
) -> Unit
|
|
) {
|
|
|
|
val delayMillis = 2000
|
|
Column {
|
|
BoxWithConstraints {
|
|
val transition = rememberInfiniteTransition()
|
|
val maxWidth = maxWidth + 30.dp
|
|
val offset = transition.animateFloat(
|
|
initialValue = 0F,
|
|
targetValue = maxWidth.value,
|
|
animationSpec = infiniteRepeatable(
|
|
animation = tween(durationMillis = 3000, delayMillis = delayMillis),
|
|
repeatMode = RepeatMode.Restart
|
|
)
|
|
)
|
|
Box(modifier = Modifier.fillMaxWidth()) {
|
|
content(model = model, value = offset)
|
|
}
|
|
|
|
if (offset.value.toInt() == maxWidth.value.toInt()) {
|
|
model.addAsync(delayMillis = delayMillis)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 跑马灯布局
|
|
*
|
|
* @param model
|
|
* @param offset
|
|
*/
|
|
@Composable
|
|
fun MarqueeText(model: MarqueeViewModel = viewModel(), offset: State<Float>) {
|
|
val poetryIndex: Int by model.marqueeIndex.observeAsState(0)
|
|
|
|
// Text(text = "$poetryIndex")
|
|
// Text(text = "offset.value=${offset.value}")
|
|
Text(
|
|
text = model.marqueeTexts[poetryIndex % model.marqueeTexts.size],
|
|
modifier = Modifier.offset(x = offset.value.dp),
|
|
maxLines = 1,
|
|
overflow = TextOverflow.Ellipsis
|
|
)
|
|
|
|
}
|
|
|
|
/**
|
|
* 导航界面框架
|
|
*
|
|
* @param background 背景
|
|
* @param mainMenu 菜单
|
|
* @param nav 导航
|
|
* @param body 内容
|
|
*/
|
|
@Composable
|
|
fun MainFrame(
|
|
background: @Composable () -> Unit,
|
|
mainMenu: MainMenu,
|
|
nav: NavHostController,
|
|
body: @Composable ColumnScope.() -> Unit
|
|
) {
|
|
Box(modifier = Modifier.fillMaxSize()) {
|
|
background()
|
|
Column {
|
|
Column(modifier = Modifier.weight(0.9F), content = body)
|
|
MainBottomAppBar(
|
|
menu = mainMenu,
|
|
nav = nav
|
|
)
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 界面框架
|
|
*
|
|
* @param background
|
|
* @param body
|
|
*/
|
|
@Composable
|
|
fun MainFrame(background: @Composable () -> Unit, body: @Composable ColumnScope.() -> Unit) {
|
|
Box(modifier = Modifier.fillMaxSize()) {
|
|
background()
|
|
Column(content = body)
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 图片轮播
|
|
*
|
|
*/
|
|
@Composable
|
|
fun Carousel(
|
|
imageBitmap: LiveData<ImageBitmap>,
|
|
durationMillis: Int = 2000,
|
|
content: @Composable (imageBitmap: ImageBitmap?) -> Unit
|
|
) {
|
|
val data by imageBitmap.observeAsState()
|
|
|
|
Crossfade(targetState = data, animationSpec = tween(durationMillis = durationMillis)) {
|
|
content(imageBitmap = it)
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 通用文本输入框
|
|
*
|
|
* @param T
|
|
* @param modifier
|
|
* @param form
|
|
* @param singeLine
|
|
*/
|
|
@Composable
|
|
fun <T : StringForm> BaseTextField(
|
|
modifier: Modifier = Modifier,
|
|
form: T,
|
|
singeLine: Boolean = false,
|
|
keyboardOptions: KeyboardOptions = KeyboardOptions.Default.copy(imeAction = ImeAction.Done),
|
|
isError: Boolean = false,
|
|
visualTransformation: VisualTransformation = VisualTransformation.None
|
|
) {
|
|
val name: String by form.formValue.observeAsState("")
|
|
val focusManager = LocalFocusManager.current
|
|
OutlinedTextField(
|
|
modifier = modifier,
|
|
value = name,
|
|
onValueChange = { form.onChange(it) },
|
|
label = { Text(text = form.formDesc) },
|
|
placeholder = { Text(text = form.formPlaceholder) },
|
|
singleLine = singeLine,
|
|
keyboardActions = KeyboardActions(onDone = { focusManager.clearFocus() }),
|
|
keyboardOptions = keyboardOptions,
|
|
trailingIcon = { Text(text = "${name.length}/${form.textLength}") },
|
|
isError = isError,
|
|
visualTransformation = visualTransformation
|
|
)
|
|
}
|
|
|
|
/**
|
|
* 底部提示
|
|
*
|
|
* @param model
|
|
* @param scaffoldState
|
|
*/
|
|
@Composable
|
|
fun ShowSnackbar(model: ScaffoldModel = viewModel(), scaffoldState: ScaffoldState) {
|
|
val snackBar: SnackBar? by model.data.observeAsState()
|
|
snackBar?.apply {
|
|
if (message != null) {
|
|
LaunchedEffect(scaffoldState) {
|
|
launch {
|
|
if (actionLabel != null) {
|
|
val result = scaffoldState.snackbarHostState.showSnackbar(
|
|
message = message, actionLabel = actionLabel,
|
|
duration = duration
|
|
|
|
)
|
|
when (result) {
|
|
SnackbarResult.ActionPerformed -> {
|
|
Logger.i("点击操作按钮")
|
|
callback()
|
|
}
|
|
SnackbarResult.Dismissed -> {
|
|
Logger.d("窗口消失")
|
|
}
|
|
}
|
|
} else {
|
|
scaffoldState.snackbarHostState.showSnackbar(message = message)
|
|
}
|
|
model.update()
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* 界面背景
|
|
*
|
|
* @property id 资源id
|
|
*/
|
|
enum class BackgroundImage(@DrawableRes val id: Int) {
|
|
//主页
|
|
Main(R.drawable.mb_bg_fb_08),
|
|
|
|
//社团列表
|
|
AssociationList(R.drawable.mb_bg_fb_07),
|
|
|
|
//个人中心
|
|
Center(R.drawable.mb_bg_fb_28),
|
|
|
|
//注册社团
|
|
RegAssociation(R.drawable.mb_bg_fb_06),
|
|
|
|
//社团主界面
|
|
AssociationMain(R.drawable.mb_bg_fb_25_180),
|
|
|
|
//社团重命名
|
|
Rename(R.drawable.mb_bg_fb_27),
|
|
|
|
//社团题库管理
|
|
Exam(R.drawable.mb_bg_fb_09),
|
|
|
|
//活动信息
|
|
ActivityInfo(R.drawable.mb_bg_fb_01),
|
|
|
|
//活动相册
|
|
ActivityPhoto(R.drawable.mb_bg_fb_02),
|
|
|
|
//活动成员
|
|
ActivityMember(R.drawable.mb_bg_fb_03),
|
|
|
|
//交流区
|
|
ActivityBBS(R.drawable.mb_bg_fb_04),
|
|
|
|
//系统通知
|
|
ActivityMessage(R.drawable.mb_bg_fb_26)
|
|
|
|
|
|
}
|
|
|
|
/**
|
|
* 界面背景图
|
|
*
|
|
* @param image
|
|
* @param alpha
|
|
*/
|
|
@Composable
|
|
fun Background(image: BackgroundImage, alpha: Float = DefaultAlpha) {
|
|
val app = LocalContext.current.applicationContext as APP
|
|
var i: ImageBitmap? by remember {
|
|
mutableStateOf(null)
|
|
}
|
|
LaunchedEffect(image) {
|
|
i = app.getImage(image = image)
|
|
}
|
|
i?.let {
|
|
Image(
|
|
bitmap = it,
|
|
contentDescription = null,
|
|
contentScale = ContentScale.FillBounds,
|
|
alpha = alpha,
|
|
modifier = Modifier.fillMaxSize()
|
|
)
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
*
|
|
*
|
|
* @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 Poster(modifier: Modifier = Modifier, imageBitmap: ImageBitmap? = null) {
|
|
Card(
|
|
modifier = modifier,
|
|
backgroundColor = Color.Transparent
|
|
) {
|
|
Box(contentAlignment = Alignment.Center) {
|
|
Image(
|
|
painter = painterResource(id = R.drawable.hot_activity_background),
|
|
contentDescription = null,
|
|
modifier = Modifier.fillMaxSize()
|
|
)
|
|
if (imageBitmap != null) {
|
|
Image(
|
|
bitmap = imageBitmap,
|
|
contentDescription = null,
|
|
modifier = Modifier.fillMaxSize()
|
|
)
|
|
} else {
|
|
Image(
|
|
painter = painterResource(id = R.drawable.ic_launcher_foreground),
|
|
contentDescription = null
|
|
)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 介绍卡片
|
|
*
|
|
*/
|
|
@Composable
|
|
fun DescCard(modifier: Modifier, content: String) {
|
|
Card(
|
|
modifier = modifier,
|
|
backgroundColor = Color.Transparent
|
|
) {
|
|
Box {
|
|
Image(
|
|
painter = painterResource(id = R.drawable.hot_activity_desc_background),
|
|
contentDescription = null,
|
|
contentScale = ContentScale.FillBounds,
|
|
modifier = Modifier.fillMaxSize()
|
|
)
|
|
Column(
|
|
modifier = Modifier
|
|
.fillMaxSize()
|
|
.padding(horizontal = 10.dp)
|
|
) {
|
|
Spacer(modifier = Modifier.weight(0.15F))
|
|
Text(
|
|
modifier = Modifier.weight(0.65F),
|
|
text = content,
|
|
overflow = TextOverflow.Ellipsis
|
|
)
|
|
Spacer(modifier = Modifier.weight(0.15F))
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
//@Preview
|
|
@Composable
|
|
fun AnimationTextPreview() {
|
|
AnimationText(text = "6666")
|
|
}
|
|
|
|
//@Preview
|
|
@Composable
|
|
fun MyBottomAppBarPreview() {
|
|
val arr: List<Arrangement.Horizontal> = listOf(
|
|
Arrangement.Start,
|
|
Arrangement.End,
|
|
Arrangement.Center,
|
|
Arrangement.SpaceBetween,
|
|
Arrangement.SpaceAround,
|
|
Arrangement.SpaceEvenly
|
|
)
|
|
var i by remember {
|
|
mutableStateOf(3)
|
|
}
|
|
Column(modifier = Modifier.fillMaxSize()) {
|
|
Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceEvenly) {
|
|
OutlinedButton(onClick = { i += 1 }) {
|
|
Text(text = "添加元素")
|
|
}
|
|
if (i > 1) {
|
|
OutlinedButton(onClick = { i -= 1 }) {
|
|
Text(text = "删除元素")
|
|
}
|
|
}
|
|
}
|
|
arr.forEach {
|
|
Column(
|
|
modifier = Modifier
|
|
.weight(1F / arr.size)
|
|
.border(width = 1.dp, color = MaterialTheme.colors.background)
|
|
) {
|
|
Row(
|
|
modifier = Modifier.fillMaxWidth(),
|
|
horizontalArrangement = Arrangement.Center
|
|
) {
|
|
Text(text = "$it", style = MaterialTheme.typography.h5)
|
|
}
|
|
Row(
|
|
modifier = Modifier.fillMaxSize(),
|
|
horizontalArrangement = it,
|
|
verticalAlignment = Alignment.CenterVertically
|
|
) {
|
|
repeat(i) {
|
|
Text(text = "$it", style = MaterialTheme.typography.h3)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
fun TestPreview() {
|
|
|
|
} |