当前位置:网站首页>Kotlin Compose 完善toDo项目 Surface 渲染背景 与阴影
Kotlin Compose 完善toDo项目 Surface 渲染背景 与阴影
2022-06-25 04:01:00 【安果移不动】
我们的todo 只能添加随机的todo 非常的不智能。下面来完善他。让他支持到可以进行添加自定义的项目
这里的阴影还没开始使用。
TodoComponents.kt
package com.anguomob.jecpack.activity.compose.todo.one
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.animateContentSize
import androidx.compose.animation.core.*
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material.*
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.RectangleShape
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.platform.LocalSoftwareKeyboardController
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.unit.dp
import com.anguomob.jecpack.activity.compose.todo.bean.ToDoIcon
import com.anguomob.jecpack.activity.compose.todo.bean.TodoItem
@Composable
fun ToDoItemInputBackground(
modifier: Modifier = Modifier,
content: @Composable RowScope.() -> Unit,
elevatioon: Boolean
) {
//帧动画形式展示Surface底部的阴影
val animatedElevation by animateDpAsState(
targetValue = if (elevatioon) 1.dp else 0.dp,
TweenSpec(300)
)
Surface(
color = MaterialTheme.colors.onSurface.copy(alpha = 0.05f),
shape = RectangleShape,
elevation = animatedElevation
) {
Row(modifier = modifier.animateContentSize(animationSpec = TweenSpec(300))) {
content()
}
}
}
@OptIn(ExperimentalComposeUiApi::class)
@Composable
fun TodoInputText(
text: String,
onTextChanged: (String) -> Unit,
onImeAction: () -> Unit,
modifier: Modifier = Modifier,
) {
val keyboardController = LocalSoftwareKeyboardController.current
TextField(
value = text,
onValueChange = onTextChanged,
modifier = modifier,
colors = TextFieldDefaults.textFieldColors(backgroundColor = Color.Transparent),
maxLines = 1,
//配置软键盘
keyboardOptions = KeyboardOptions.Default.copy(imeAction = ImeAction.Done),
keyboardActions = KeyboardActions(onDone = {
onImeAction()
//点击完成之后 隐藏键盘
keyboardController?.hide()
})
)
}
@Composable()
fun TodoEditButton(
onClick: () -> Unit,
text: String,
modifier: Modifier = Modifier,
enable: Boolean = true
) {
TextButton(
onClick = onClick,
shape = CircleShape,
colors = ButtonDefaults.buttonColors(),
modifier = modifier,
enabled = enable
) {
Text(text)
}
}
@Composable
fun TodoItemEntryInput(onItemComplete: (TodoItem) -> Unit) {
val (text, setText) = remember {
mutableStateOf("")
}
val (icon, setIcon) = remember {
mutableStateOf(ToDoIcon.Default)
}
//icon是否可一件取决于文本是否有内容
val iconsVisible = text.isNotBlank()
//点击add
val submit = {
onItemComplete(TodoItem(text, icon))
setText("")
setIcon(ToDoIcon.Default)
}
TodoItemInput(
text = text,
onTextChange = setText,
icon = icon,
onIconChange = setIcon,
iconsVisible = iconsVisible,
submit = submit,
)
}
@Composable
fun TodoItemInput(
text: String,
onTextChange: (String) -> Unit,
icon: ToDoIcon,
onIconChange: (ToDoIcon) -> Unit,
iconsVisible: Boolean,
submit: () -> Unit
) {
Column {
Row(
Modifier
.padding(horizontal = 16.dp)
.padding(top = 16.dp)
) {
TodoInputText(
text = text,
modifier = Modifier
.weight(1f)
.padding(end = 8.dp),
onTextChanged = onTextChange,
onImeAction = submit
)
TodoEditButton(
onClick = submit,
text = "Add",
modifier = Modifier.align(Alignment.CenterVertically),
enable = text.isNotBlank()
)
}
AnimatedIconRow(
visible = iconsVisible,
icon = icon,
onIconChange = onIconChange,
modifier = Modifier.padding(8.dp)
)
}
}
//一排图标 根据文本框是否有内容 自动弹起收缩
@Composable
fun AnimatedIconRow(
modifier: Modifier = Modifier,
visible: Boolean,
icon: ToDoIcon,
onIconChange: (ToDoIcon) -> Unit
) {
val enter = remember {
fadeIn(animationSpec = TweenSpec(300, easing = FastOutLinearInEasing))
}
val exit = remember {
fadeOut(animationSpec = TweenSpec(100, easing = FastOutSlowInEasing))
}
//最小高度16dp
AnimatedVisibility(visible = visible, enter = enter, exit = exit, modifier = modifier) {
IconRow(icon = icon, onIconChange = onIconChange)
}
}
@Composable
fun IconRow(icon: ToDoIcon, onIconChange: (ToDoIcon) -> Unit, modifier: Modifier = Modifier) {
Row(modifier = modifier) {
for (todoIcon in ToDoIcon.values()) {
SelectableIconButton(
icon = todoIcon.imageVector,
iconContentDescription = todoIcon.contentDescription,
onIconSelect = { onIconChange(todoIcon) },
isSelected = todoIcon == icon
)
}
}
}
@Composable
fun SelectableIconButton(
icon: ImageVector,
iconContentDescription: Int,
onIconSelect: () -> Unit,
isSelected: Boolean,
modifier: Modifier = Modifier
) {
//图标选中和未选中 颜色不一样
val tint = if (isSelected) {
MaterialTheme.colors.primary
} else {
MaterialTheme.colors.onSurface.copy(alpha = 0.6f)
}
val enter = remember {
fadeIn(animationSpec = TweenSpec(300, easing = FastOutLinearInEasing))
}
val exit = remember {
fadeOut(animationSpec = TweenSpec(100, easing = FastOutSlowInEasing))
}
TextButton(onClick = onIconSelect, modifier = modifier) {
Column {
Icon(
imageVector = icon,
tint = tint,
contentDescription = stringResource(id = iconContentDescription)
)
//最小高度16dp
AnimatedVisibility(visible = isSelected, enter = enter, exit = exit) {
Box(
Modifier
.padding(top = 3.dp)
.width(icon.defaultWidth)
.height(1.dp)
.background(tint)
)
}
}
}
}
TodoScreen.kt
package com.anguomob.jecpack.activity.compose.todo.one
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material.*
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.painter.Painter
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.lifecycle.ViewModel
import com.anguomob.jecpack.R
import com.anguomob.jecpack.activity.compose.todo.bean.ToDoIcon
import com.anguomob.jecpack.activity.compose.todo.bean.TodoItem
import com.anguomob.jecpack.activity.compose.todo.viewmodel.TodoViewModel
import generateRandomTodoItem
import java.util.*
import kotlin.random.Random
@Composable
fun TodoActivityScreen(todoViewModel: TodoViewModel ) {
// val items = listOf(
// TodoItem("Learn compose", ToDoIcon.Event),
// TodoItem("Take a CodeLab"),
// TodoItem("Apply state", ToDoIcon.Done),
// odoItem("Build dynamic UIs", ToDoIcon.Square),
val items: List<TodoItem> by todoViewModel.todoItems.observeAsState(listOf())
TodoScreen(items = items, onAddItem = {
todoViewModel.addItem(it)
}, onItemClick = {
todoViewModel.removeItem(it)
})
}
@Composable
fun TodoScreen(
items: List<TodoItem>,
onAddItem: (TodoItem) -> Unit,
onItemClick: (TodoItem) -> Unit
) {
Column() {
//输入框 外加一个灰色背景
ToDoItemInputBackground(content = {
TodoItemEntryInput(onItemComplete = onAddItem)
}, elevatioon = true)
LazyColumn(
modifier = Modifier
.weight(1f)
) {
items(items) {
TodoRow(it, modifier = Modifier.fillParentMaxWidth(), onItemClick = onItemClick)
}
}
Button(
onClick = {
onAddItem(generateRandomTodoItem())
},
modifier = Modifier
.padding(16.dp)
.fillMaxWidth()
) {
Text("新建TODO")
}
}
}
@Composable
fun TodoRow(todo: TodoItem, modifier: Modifier = Modifier, onItemClick: (TodoItem) -> Unit) {
Row(
modifier = modifier
.padding(horizontal = 16.dp, vertical = 8.dp)
.clickable { onItemClick(todo) },
//子元素水平均匀分发
horizontalArrangement = Arrangement.SpaceBetween
) {
Text(todo.task)
val iconAlpha = remember(todo.id) {
randomTint()
}
Icon(
imageVector = todo.icon.imageVector,
tint = LocalContentColor.current.copy(alpha = iconAlpha),
contentDescription = stringResource(id = todo.icon.contentDescription)
)
}
}
private fun randomTint(): Float {
val number = Random.nextFloat().coerceIn(0.3f, 0.9f)
return number
}
数据bean等类容在这里
Kotlin Compose Todo小项目 删除添加项目 ,认识状态提升_安果移不动的博客-CSDN博客
效果就是通过点击
add之后可以选择图标和文案来进行写todo项目
关于阴影 可以重点关注这个
边栏推荐
- ThinkPHP is integrated with esaywechat. What's wrong with wechat payment callback without callback?
- Machine learning deep learning -- Vectorization
- 我的IC之旅——资深芯片设计验证工程师成长——“胡”说IC工程师完美进阶
- GBASE 8s存儲過程語法結構
- Data view for gbase 8s
- The yii2 debug toolbar is missing
- [untitled]
- Synchronous and asynchronous functions (callback function, promise, generator, async/await)
- CTF_ Web: Changan cup-2021 old but a little new & asuka
- JS arguments
猜你喜欢
The solution of wechat applet switchtab unable to take parameters
Xiaobai learns MySQL - Statistical 'opportunism'
2.0springmvc uses restful
Upgrade PHP to php7 The impact of X (2), the obsolescence of mcrypt decryption
GBASE 8s 索引R树
Anaconda安装+TensorFlow安装+Keras安装+numpy安装(包含镜像和版本信息兼容问题)
哪个编程语言实现hello world最烦琐?
单元测试覆盖率
Code scanning payment flow chart of Alipay payment function developed by PHP
为什么TCP握手刚刚好是3次呢?
随机推荐
PHP encapsulates curl to send get and post request methods, and uses
Concat() in JS
Join() in JSZ
Data view for gbase 8s
CTF_ Web:php weak type bypass and MD5 collision
JS' sort() function
三角形类(构造与析构)
A detailed summary of four handshakes (or four waves) over TCP connections
第九章 APP项目测试(2) 测试工具
Blob page in gbase 8s
Detailed explanation of flex attributes in flex layout
GBase 8s的封锁技术的基本介绍
【esp32学习之路6——flash加密】
「 每日一练,快乐水题 」1108. IP 地址无效化
记录小知识点
Gbase 8s overall architecture
2021.4.15 note the difference between let, const and VaR in ES6
GBASE 8s的触发器
Vscode 设置clang-format
Le chemin de l'apprentissage immutable - - Adieu à la copie traditionnelle