去除所有动画,优化性能

This commit is contained in:
BBIT-Kai
2026-05-28 15:21:38 +08:00
parent fa53a69d2b
commit 4eeeaaa3bc
23 changed files with 291 additions and 287 deletions
+1 -9
View File
@@ -3,9 +3,6 @@ package com.bbitcn.f8.pad
import android.app.Application
import android.content.Context
import android.provider.Settings
import androidx.compose.animation.animateContentSize
import androidx.compose.animation.core.Spring
import androidx.compose.animation.core.spring
import androidx.compose.ui.Modifier
import com.bbitcn.f8.pad.utils.MMKVUtil
import com.bbitcn.f8.pad.utils.TTSManager
@@ -25,13 +22,8 @@ import timber.log.Timber
* @Author DuanKaiji
* @CreateTime 2024年03月27日 13:43
*/
// Keep MD as the project-wide animated modifier hook, but keep it instant for smooth lists.
val MD = Modifier
.animateContentSize(
animationSpec = spring(
dampingRatio = Spring.DampingRatioLowBouncy,
stiffness = Spring.StiffnessLow
)
)
val M = Modifier
val IS_DEBUG_DRYCOCOON = false // 是否是调试状态
@@ -1,12 +1,6 @@
package com.bbitcn.f8.pad.base
import android.R.attr.onClick
import androidx.compose.animation.AnimatedContent
import androidx.compose.animation.animateContentSize
import androidx.compose.animation.core.tween
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.animation.togetherWith
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
@@ -69,9 +63,9 @@ import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.paging.LoadState
import androidx.paging.compose.LazyPagingItems
import androidx.paging.compose.itemContentType
import androidx.paging.compose.itemKey
import com.bbitcn.f8.pad.M
import com.bbitcn.f8.pad.MD
import com.bbitcn.f8.pad.R
import com.bbitcn.f8.pad.ui.theme.MyColors
import com.cyberecho.ui.screen.JumpToBottomThreshold
@@ -147,20 +141,33 @@ fun TableContent(
backgroundDeepColor: Boolean,
list: List<Pair<String, Int>>,
verticalPadding: Dp = 5.dp,
enableClick: Boolean = false,
enableLongClick: Boolean = false,
onLongClick: () -> Unit = {},
onClick: () -> Unit = {}
) {
val cardModifier =
if (enableClick || enableLongClick) {
modifier.pointerInput(enableClick, enableLongClick, onClick, onLongClick) {
detectTapGestures(
onLongPress = {
if (enableLongClick) {
onLongClick()
}
},
onTap = {
if (enableClick) {
onClick()
}
}
)
}
} else {
modifier
}
Card(
modifier = modifier.pointerInput(Unit) {
detectTapGestures(
onLongPress = {
onLongClick()
},
onTap = {
onClick()
}
)
},
modifier = cardModifier,
colors = CardDefaults.cardColors(
containerColor = if (backgroundDeepColor) Color(0xFFF3F7FD) else Color.White
)
@@ -271,14 +278,18 @@ fun <T : Any> MyRefreshTableForCard(
horizontalArrangement = Arrangement.spacedBy(10.dp),
verticalArrangement = Arrangement.spacedBy(10.dp)
) {
items(count = info.itemCount, key = info.itemKey { key(it) }) { index ->
items(
count = info.itemCount,
key = info.itemKey { key(it) },
contentType = info.itemContentType { "paging-card" }
) { index ->
info[index]?.let { lineItem ->
Box {
item(lineItem, index)
}
}
}
item {
item(contentType = "paging-footer") {
when (pagerSate) {
is LoadState.NotLoading -> if (pagerSate.endOfPaginationReached)
ListNoMore()
@@ -419,7 +430,7 @@ fun <T : Any> MyTable2(
val lineItem = infos[index]
Card(
modifier = MD
modifier = M
.pointerInput(Unit) {
detectTapGestures(
onLongPress = {
@@ -508,7 +519,7 @@ fun <T : Any> MyRefreshTable(
}
LaunchedEffect(info.loadState.refresh) {
if (info.loadState.refresh is LoadState.NotLoading && scrollToTopOnRefresh) {
listState.animateScrollToItem(0)
listState.scrollToItem(0)
}
}
@@ -544,11 +555,15 @@ fun <T : Any> MyRefreshTable(
) {
var selectIndex by rememberSaveable { mutableStateOf(-1) }
LazyColumn(state = listState) {
items(count = info.itemCount, key = info.itemKey { key(it) }) { index ->
items(
count = info.itemCount,
key = info.itemKey { key(it) },
contentType = info.itemContentType { "paging-row" }
) { index ->
// // 每行
val lineItem = info[index] ?: return@items
Card(
modifier = MD
modifier = M
.pointerInput(Unit) {
detectTapGestures(
onLongPress = {
@@ -623,7 +638,7 @@ fun <T : Any> MyRefreshTable(
}
}
}
item {
item(contentType = "paging-footer") {
when (pagerSate) {
is LoadState.NotLoading -> if (pagerSate.endOfPaginationReached)
ListNoMore()
@@ -6,9 +6,6 @@ import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.AnimatedVisibilityScope
import androidx.compose.animation.EnterTransition
import androidx.compose.animation.ExitTransition
import androidx.compose.animation.expandVertically
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
@@ -403,8 +400,8 @@ fun RedPointBadge(content: @Composable () -> Unit) {
fun MyAnimatedVisibility(
visible: Boolean,
modifier: Modifier = M,
enter: EnterTransition = fadeIn(),
exit: ExitTransition = fadeOut(),
enter: EnterTransition = EnterTransition.None,
exit: ExitTransition = ExitTransition.None,
label: String = "AnimatedVisibility",
content: @Composable AnimatedVisibilityScope.() -> Unit
) {
@@ -422,8 +419,8 @@ fun MyAnimatedVisibility(
fun MyAnimatedVisibilityFromDownToUp(
visible: Boolean,
modifier: Modifier = M,
enter: EnterTransition = expandVertically(expandFrom = Alignment.Bottom),
exit: ExitTransition = fadeOut(),
enter: EnterTransition = EnterTransition.None,
exit: ExitTransition = ExitTransition.None,
label: String = "AnimatedVisibility",
content: @Composable AnimatedVisibilityScope.() -> Unit
) {
@@ -5,30 +5,20 @@ import android.view.View
import android.view.WindowManager
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.animation.AnimatedContentTransitionScope
import androidx.compose.animation.core.EaseIn
import androidx.compose.animation.core.EaseOut
import androidx.compose.animation.core.LinearEasing
import androidx.compose.animation.core.tween
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.animation.slideInHorizontally
import androidx.compose.animation.slideOutHorizontally
import androidx.compose.animation.EnterTransition
import androidx.compose.animation.ExitTransition
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.DrawerValue
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.ModalBottomSheet
import androidx.compose.material3.ModalNavigationDrawer
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Snackbar
import androidx.compose.material3.SnackbarHost
import androidx.compose.material3.Surface
import androidx.compose.material3.rememberDrawerState
import androidx.compose.material3.rememberModalBottomSheetState
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.SideEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
@@ -167,22 +157,10 @@ class MainActivity : ComponentActivity() {
navController = navController,
startDestination = startDestination, // 设置起始页面
enterTransition = {
slideInHorizontally(initialOffsetX = { it }) + fadeIn(
initialAlpha = 0f,
animationSpec = tween(
durationMillis = 400,
easing = LinearEasing
)
)
EnterTransition.None
},
exitTransition = {
slideOutHorizontally(targetOffsetX = { -it }) + fadeOut(
targetAlpha = 0f,
animationSpec = tween(
durationMillis = 400,
easing = LinearEasing
)
)
ExitTransition.None
}
) {
composable("test") {
@@ -1,12 +1,8 @@
package com.bbitcn.f8.pad.ui.screen
import androidx.compose.animation.AnimatedContent
import androidx.compose.animation.SizeTransform
import androidx.compose.animation.core.tween
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.animation.slideInVertically
import androidx.compose.animation.slideOutVertically
import androidx.compose.animation.EnterTransition
import androidx.compose.animation.ExitTransition
import androidx.compose.animation.togetherWith
import androidx.compose.foundation.Canvas
import androidx.compose.foundation.Image
@@ -107,9 +103,7 @@ fun MyTopBar(
AnimatedContent(
logoState,
transitionSpec = {
fadeIn(
animationSpec = tween(1000)
) togetherWith fadeOut(animationSpec = tween(1000))
EnterTransition.None togetherWith ExitTransition.None
},
modifier = M.clickable(
interactionSource = remember { MutableInteractionSource() },
@@ -135,22 +129,7 @@ fun MyTopBar(
AnimatedContent(
targetState = logoState,
transitionSpec = {
// Compare the incoming number with the previous number.
if (targetState.second > initialState.second) {
// If the target number is larger, it slides up and fades in
// while the initial (smaller) number slides up and fades out.
slideInVertically { height -> height } + fadeIn() togetherWith
slideOutVertically { height -> -height } + fadeOut()
} else {
// If the target number is smaller, it slides down and fades in
// while the initial number slides down and fades out.
slideInVertically { height -> -height } + fadeIn() togetherWith
slideOutVertically { height -> height } + fadeOut()
}.using(
// Disable clipping since the faded slide-in/out should
// be displayed out of bounds.
SizeTransform(clip = false)
)
EnterTransition.None togetherWith ExitTransition.None
}, label = "animated content"
) { value ->
Row(verticalAlignment = Alignment.Bottom) {
@@ -1,10 +1,5 @@
package com.bbitcn.f8.pad.ui.screen.dialog
import androidx.compose.animation.animateColor
import androidx.compose.animation.core.RepeatMode
import androidx.compose.animation.core.infiniteRepeatable
import androidx.compose.animation.core.rememberInfiniteTransition
import androidx.compose.animation.core.tween
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.layout.Arrangement
@@ -36,22 +31,8 @@ fun AIDialogPreview() {
@Composable
fun AIListenerDialog(userSaid:String = "") {
val infiniteTransition = rememberInfiniteTransition(label = "infinite transition")
// 动态颜色动画
val animatedColor by infiniteTransition.animateColor(
initialValue = Color(0xFF60DDAD),
targetValue = Color(0xFF4285F4),
animationSpec = infiniteRepeatable(tween(1000), RepeatMode.Reverse),
label = "background color"
)
// 动态边框颜色动画
val borderColor by infiniteTransition.animateColor(
initialValue = Color(0x80FF4081),
targetValue = Color(0x803F51B5),
animationSpec = infiniteRepeatable(tween(1000), RepeatMode.Reverse),
label = "border color"
)
val animatedColor = Color(0xFF60DDAD)
val borderColor = Color(0x80FF4081)
// 实现包含动态边框的外框
Box(modifier = M.fillMaxSize()
.border(10.dp, borderColor) , contentAlignment = Alignment.Center) {
@@ -226,7 +226,7 @@ fun Messages(
enabled = jumpToBottomButtonEnabled,
onClicked = {
scope.launch {
scrollState.animateScrollToItem(0)
scrollState.scrollToItem(0)
}
},
modifier = M.align(Alignment.BottomCenter)
@@ -1,6 +1,5 @@
package com.bbitcn.f8.pad.ui.screen.dialog
import androidx.compose.animation.animateColorAsState
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
@@ -261,10 +260,7 @@ fun CalTextS(
},
contentAlignment = Alignment.Center
) {
val animatedColor by animateColorAsState(
if (isSelect) MyColors.White else if (isCurMonth) MyColors.Black else MyColors.Gray,
label = "color"
)
val animatedColor = if (isSelect) MyColors.White else if (isCurMonth) MyColors.Black else MyColors.Gray
Text(
text = day,
fontSize = MaterialTheme.typography.bodyMedium.fontSize,
@@ -1,11 +1,5 @@
package com.bbitcn.f8.pad.ui.screen.dialog
import androidx.compose.animation.core.FastOutSlowInEasing
import androidx.compose.animation.core.LinearEasing
import androidx.compose.animation.core.LinearOutSlowInEasing
import androidx.compose.animation.core.tween
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource
@@ -62,21 +56,7 @@ fun LoadingDialogPreview() {
fun LoadingDialog(
loadingDialogData: LoadingDialogData
) {
MyAnimatedVisibility(
loadingDialogData.showDialog,
enter = fadeIn(
animationSpec = tween(
durationMillis = 500,
easing = FastOutSlowInEasing
)
),
exit = fadeOut(
animationSpec = tween(
durationMillis = 300,
easing = LinearOutSlowInEasing
)
)
) {
MyAnimatedVisibility(loadingDialogData.showDialog) {
Box(
modifier = M
.fillMaxSize()
@@ -125,4 +105,4 @@ fun LoadingDialog(
}
}
}
}
}
@@ -1,10 +1,6 @@
package com.bbitcn.f8.pad.ui.screen.dialog
import android.content.res.Configuration
import androidx.compose.animation.slideInHorizontally
import androidx.compose.animation.slideInVertically
import androidx.compose.animation.slideOutHorizontally
import androidx.compose.animation.slideOutVertically
import androidx.compose.foundation.Image
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
@@ -116,20 +112,12 @@ fun TicketMoreDialog(
)
}
MyAnimatedVisibility(
isTranslated,
enter = slideInVertically(
initialOffsetY = { fullHeight -> fullHeight }),
exit = slideOutVertically(
targetOffsetY = { fullHeight -> fullHeight })
isTranslated
) {
CocoonTypeTranslate(info, viewModel = viewModel)
}
MyAnimatedVisibility(
!isTranslated,
enter = slideInVertically(
initialOffsetY = { fullHeight -> -fullHeight }),
exit = slideOutVertically(
targetOffsetY = { fullHeight -> -fullHeight })
!isTranslated
) {
LazyVerticalGrid(modifier = M.fillMaxSize(), columns = GridCells.Fixed(columns)) {
item {
@@ -117,6 +117,7 @@ fun WaterCutRecordDialog(info: WaterCutRecordDialogData) {
backgroundDeepColor = it % 2 == 0,
list = items[it].map { it.toString() }.zip(ratio.map { it.toInt() }),
verticalPadding = 15.dp,
enableLongClick = true,
onLongClick = {
Toasty.showConfirmDialog("是否删除该记录?") {
info.deleteRecordById(it + 1)
@@ -145,6 +145,7 @@ fun FundsScreen(
Pair(tab.total.toString(), 1),
Pair(tab.summoney.toString(), 2)
),
enableClick = true,
onClick = {
fundsViewModel.updateCurSearchState(tab)
onFilterLikeChanged(queryInput)
@@ -1,23 +1,22 @@
package com.bbitcn.f8.pad.ui.screen.mainFunc
import android.content.res.Configuration
import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.Image
import androidx.compose.foundation.Canvas
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.layout.widthIn
import androidx.compose.foundation.layout.wrapContentWidth
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Card
import androidx.compose.material3.DatePickerDefaults
import androidx.compose.material3.DatePickerDialog
import androidx.compose.material3.DateRangePicker
@@ -33,6 +32,7 @@ import androidx.compose.material3.rememberDateRangePickerState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
@@ -40,12 +40,19 @@ import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.draw.clip
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.drawText
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.text.rememberTextMeasurer
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.Constraints
import androidx.compose.ui.unit.dp
import com.bbitcn.f8.pad.M
import com.bbitcn.f8.pad.base.MainFuncFrame
@@ -54,15 +61,12 @@ import androidx.navigation.NavController
import androidx.navigation.compose.rememberNavController
import androidx.paging.compose.LazyPagingItems
import androidx.paging.compose.collectAsLazyPagingItems
import com.bbitcn.f8.pad.R
import com.bbitcn.f8.pad.base.DateRangePickTextFiled
import com.bbitcn.f8.pad.base.MyAnimatedVisibility
import com.bbitcn.f8.pad.base.MyButton
import com.bbitcn.f8.pad.base.MyCard
import com.bbitcn.f8.pad.base.MyRefreshTableForCard
import com.bbitcn.f8.pad.base.QueryTextField
import com.bbitcn.f8.pad.base.TableContent
import com.bbitcn.f8.pad.base.TableHeadLineCard
import com.bbitcn.f8.pad.base.isLandscape
import com.bbitcn.f8.pad.model.net.response.PurchaseDataResponse
import com.bbitcn.f8.pad.ui.screen.dialog.AddTicketDialog
@@ -102,15 +106,12 @@ fun PurchaseScreen(
purchaseViewModel: PurchaseViewModel = viewModel(),
drawerViewModel: DrawerViewModel
) {
val tabs = listOf(
"全部单据", "待定价扣皮", "待确认销售", "待支付", "已电子支付",
"已现金支付", "已弃售", "已混合支付", "已仪评", "不仪评"
)
val addTicketDialog by purchaseViewModel.addTicketDialog.collectAsState()
val ticketMoreDialogData by purchaseViewModel.ticketMoreDialogData.collectAsState()
val priceDialogData by purchaseViewModel.priceDialogData.collectAsState()
val tareDialogData by purchaseViewModel.tareDialogData.collectAsState()
val dateRangeSelectDialogData by purchaseViewModel.dateRangeSelectDialogData.collectAsState()
val tabs = remember {
listOf(
"全部单据", "待定价扣皮", "待确认销售", "待支付", "已电子支付",
"已现金支付", "已弃售", "已混合支付", "已仪评", "不仪评"
)
}
// 筛选条件1:时间范围
val queryDateRange by purchaseViewModel.dateRange.collectAsState()
@@ -266,14 +267,24 @@ fun PurchaseScreen(
}
}
}
PurchaseDialogs(purchaseViewModel)
}
@Composable
private fun PurchaseDialogs(purchaseViewModel: PurchaseViewModel) {
val addTicketDialog by purchaseViewModel.addTicketDialog.collectAsState()
val ticketMoreDialogData by purchaseViewModel.ticketMoreDialogData.collectAsState()
val priceDialogData by purchaseViewModel.priceDialogData.collectAsState()
val tareDialogData by purchaseViewModel.tareDialogData.collectAsState()
val scanDialogData by purchaseViewModel.scanDialogData.collectAsState()
val ocrDialogData by purchaseViewModel.ocrDialogData.collectAsState()
val faceDialogData by purchaseViewModel.faceDialogData.collectAsState()
val dateRangeSelectDialogData by purchaseViewModel.dateRangeSelectDialogData.collectAsState()
AddTicketDialog(addTicketDialog)
PriceDialog(priceDialogData)
TareDialog(tareDialogData)
TicketMoreDialog(ticketMoreDialogData)
val scanDialogData by purchaseViewModel.scanDialogData.collectAsState()
val ocrDialogData by purchaseViewModel.ocrDialogData.collectAsState()
val faceDialogData by purchaseViewModel.faceDialogData.collectAsState()
ScanDialog(scanDialogData)
OCRDialog(ocrDialogData)
FaceDialog(faceDialogData)
@@ -342,7 +353,7 @@ fun InfoList(
}
val myPager = purchaseViewModel.infoMyPager
val isRefreshing by myPager.listIsRefreshing.collectAsState()
var selectId by rememberSaveable { mutableStateOf("") }
val selectedId = rememberSaveable { mutableStateOf("") }
MyRefreshTableForCard(
modifier = M
.fillMaxWidth()
@@ -355,9 +366,12 @@ fun InfoList(
},
columns = columns,
item = { data, index ->
InfoItem(isSelect = data.czSysid == selectId, data = data) {
val isSelected by remember(data.czSysid) {
derivedStateOf { data.czSysid == selectedId.value }
}
InfoItem(isSelect = isSelected, data = data) {
selectedId.value = data.czSysid
onClick(data)
selectId = data.czSysid
}
}
)
@@ -373,15 +387,26 @@ fun InfoItem(
data.chengZhongItemSumList.take(2)
}
val hiddenCount = data.chengZhongItemSumList.size - visibleItems.size
MyCard(
radius = 7.dp,
elevation = 0.dp,
border = BorderStroke(width = 1.dp, color = MyColors.LightGray)
val cardShape = RoundedCornerShape(7.dp)
Column(
modifier = M
.fillMaxWidth()
.height(158.dp)
.clip(cardShape)
.background(MyColors.White)
.border(
width = 1.dp,
color = if (isSelect) MyColors.BlueGreen else MyColors.LightGray,
shape = cardShape
)
.clickable(onClick = onClick)
) {
Column(modifier = M.clickable(onClick = onClick)) {
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = M.background(color = if (isSelect) MyColors.BlueGreen else MyColors.White)
modifier = M
.fillMaxWidth()
.height(32.dp)
.background(color = if (isSelect) MyColors.BlueGreen else MyColors.White)
) {
Text(
text = data.nhName,
@@ -398,66 +423,157 @@ fun InfoItem(
Text(
text = data.billCode.toString(),
fontSize = MaterialTheme.typography.bodyMedium.fontSize,
modifier = M.padding(start = 4.dp),
color = if (isSelect) MyColors.White else MyColors.Black,
fontWeight = FontWeight.Bold
fontWeight = FontWeight.Bold,
maxLines = 1,
overflow = TextOverflow.Ellipsis
)
Card(
shape = RoundedCornerShape(topEnd = 7.dp, bottomStart = 7.dp),
modifier = M.padding(bottom = 5.dp)
Box(
modifier = M
.padding(start = 6.dp)
.height(32.dp)
.wrapContentWidth()
.background(
color = MyColors.Orange,
shape = RoundedCornerShape(bottomStart = 7.dp)
),
contentAlignment = Alignment.Center
) {
Text(
text = data.billState,
modifier = M
.background(color = MyColors.Orange)
.padding(5.dp),
modifier = M.padding(horizontal = 6.dp),
color = MyColors.White,
fontSize = MaterialTheme.typography.bodyMedium.fontSize,
maxLines = 1,
overflow = TextOverflow.Ellipsis
)
}
}
TableHeadLineCard(
modifier = M.fillMaxWidth(),
listOf(
Pair("茧别", 1), Pair("毛重", 1), Pair("皮重", 1), Pair("扣重", 1),
Pair("净重", 1), Pair("单价", 1)
), isSelect
PurchaseSummaryTable(
visibleItems = visibleItems,
hiddenCount = hiddenCount
)
Column(modifier = M.height(60.dp)) {
visibleItems.forEach { item ->
TableContent(
M.fillMaxWidth(), isSelect,
listOf(
Pair(item.sgTypeName, 1),
Pair(item.mweightSum.toString(), 1),
Pair(item.pweightSum.toString(), 1),
Pair(item.kweightSum.toString(), 1),
Pair(item.jweightSum.toString(), 1),
Pair(item.price.toString(), 1)
), 3.5.dp
)
}
if (hiddenCount > 0) {
Text(
text = "+$hiddenCount",
modifier = M
.fillMaxWidth()
.padding(top = 2.dp, end = 8.dp),
color = if (isSelect) MyColors.BlueGreen else MyColors.Gray,
fontSize = MaterialTheme.typography.labelSmall.fontSize
)
}
}
StateList(
data.ispPicing, data.isKouPiing,
data.billStateValue == 2, data.payStateValue == 3
)
}
}
@Composable
private fun PurchaseSummaryTable(
visibleItems: List<PurchaseDataResponse.Data.ChengZhongItemSum>,
hiddenCount: Int
) {
val textMeasurer = rememberTextMeasurer()
val bodyFontSize = MaterialTheme.typography.bodyMedium.fontSize
val labelFontSize = MaterialTheme.typography.labelSmall.fontSize
val headerBackground = MyColors.White
val headerTextColor = MyColors.Black
val rowBackground = MyColors.White
val moreTextColor = MyColors.Gray
val headers = remember {
listOf("茧别", "毛重", "皮重", "扣重", "净重", "单价")
}
val rows = remember(visibleItems) {
visibleItems.map { item ->
listOf(
item.sgTypeName,
item.mweightSum.toString(),
item.pweightSum.toString(),
item.kweightSum.toString(),
item.jweightSum.toString(),
item.price.toString()
)
}
}
val headerStyle = TextStyle(
color = headerTextColor,
fontSize = bodyFontSize,
fontWeight = FontWeight.Bold,
textAlign = TextAlign.Center
)
val rowStyle = TextStyle(
color = MyColors.Black,
fontSize = bodyFontSize,
textAlign = TextAlign.Center
)
val moreStyle = TextStyle(
color = moreTextColor,
fontSize = labelFontSize
)
Canvas(
modifier = M
.fillMaxWidth()
.height(88.dp)
) {
val headerHeight = 28.dp.toPx()
val rowHeight = 24.dp.toPx()
val cellWidth = size.width / headers.size
val cellConstraints = Constraints.fixedWidth(cellWidth.toInt().coerceAtLeast(1))
fun drawCell(text: String, column: Int, top: Float, height: Float, style: TextStyle) {
val result = textMeasurer.measure(
text = AnnotatedString(text),
style = style,
overflow = TextOverflow.Ellipsis,
maxLines = 1,
constraints = cellConstraints
)
drawText(
textLayoutResult = result,
topLeft = Offset(
x = column * cellWidth,
y = top + (height - result.size.height) / 2f
)
)
}
drawRect(color = headerBackground, topLeft = Offset.Zero)
headers.forEachIndexed { index, text ->
drawCell(text, index, 0f, headerHeight, headerStyle)
}
rows.forEachIndexed { rowIndex, row ->
val rowTop = headerHeight + rowIndex * rowHeight
drawRect(
color = rowBackground,
topLeft = Offset(0f, rowTop),
size = androidx.compose.ui.geometry.Size(size.width, rowHeight)
)
row.forEachIndexed { columnIndex, text ->
drawCell(text, columnIndex, rowTop, rowHeight, rowStyle)
}
}
if (hiddenCount > 0) {
val moreTop = headerHeight + rows.size * rowHeight + 2.dp.toPx()
val result = textMeasurer.measure(
text = AnnotatedString("+$hiddenCount"),
style = moreStyle,
overflow = TextOverflow.Ellipsis,
maxLines = 1,
constraints = Constraints(maxWidth = size.width.toInt().coerceAtLeast(1))
)
drawText(
textLayoutResult = result,
topLeft = Offset(8.dp.toPx(), moreTop)
)
}
}
}
@Composable
fun StateList(hasPrice: Boolean, hasTare: Boolean, hasConfirm: Boolean, hasPay: Boolean) {
Row(modifier = M.fillMaxSize()) {
Row(
modifier = M
.fillMaxWidth()
.height(38.dp)
.padding(horizontal = 4.dp, vertical = 3.dp),
verticalAlignment = Alignment.CenterVertically
) {
StateItem("定价", hasPrice, M.weight(1f))
StateItem("扣皮", hasTare, M.weight(1f))
StateItem(if (hasConfirm) "确认" else "确认售", hasConfirm, M.weight(1f))
@@ -467,19 +583,24 @@ fun StateList(hasPrice: Boolean, hasTare: Boolean, hasConfirm: Boolean, hasPay:
@Composable
fun StateItem(text: String, isSelect: Boolean, modifier: Modifier) {
Box(modifier = modifier, contentAlignment = Alignment.Center) {
Image(
painter = painterResource(if (isSelect) R.drawable.bg_state_sel else R.drawable.bg_state),
contentDescription = null,
contentScale = ContentScale.Fit,
modifier = M.fillMaxWidth()
)
Row(verticalAlignment = Alignment.CenterVertically, modifier = M.padding(start = 7.dp)) {
val backgroundColor = if (isSelect) MyColors.LightLightBlueGreen else Color(0xFFF4F6F8)
val borderColor = if (isSelect) MyColors.BlueGreen else MyColors.LightGray
Box(
modifier = modifier
.height(28.dp)
.padding(horizontal = 2.dp)
.background(backgroundColor, RoundedCornerShape(50))
.padding(horizontal = 6.dp, vertical = 4.dp),
contentAlignment = Alignment.Center
) {
Row(verticalAlignment = Alignment.CenterVertically) {
if (isSelect) {
Image(
painter = painterResource(R.drawable.state_sel),
contentDescription = null,
modifier = M.size(10.dp)
Box(
modifier = M
.padding(end = 4.dp)
.width(6.dp)
.height(6.dp)
.background(borderColor, CircleShape)
)
}
Text(
@@ -1,6 +1,5 @@
package com.bbitcn.f8.pad.ui.screen.mainFunc.setting
import androidx.compose.animation.animateContentSize
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.padding
@@ -1,6 +1,5 @@
package com.bbitcn.f8.pad.ui.screen.mainFunc.setting
import androidx.compose.animation.animateContentSize
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
@@ -3,7 +3,6 @@ package com.bbitcn.f8.pad.ui.screen.secondFunc
import android.graphics.Bitmap
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.animation.animateContentSize
import androidx.compose.foundation.Image
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
@@ -1,6 +1,5 @@
package com.bbitcn.f8.pad.ui.screen.secondFunc
import androidx.compose.animation.animateContentSize
import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
@@ -275,6 +274,7 @@ fun WeightList(weightViewModel: WeightViewModel) {
item.time to 2
),
verticalPadding = 20.dp,
enableLongClick = true,
onLongClick = {
Toasty.showConfirmDialog("是否删除第${item.weighingTimes}磅次记录?") {
weightViewModel.deleteDetail(item.sysid)
@@ -1,6 +1,5 @@
package com.bbitcn.f8.pad.ui.screen.view.common
import androidx.compose.animation.animateColorAsState
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
@@ -235,10 +234,7 @@ fun CalText(
},
contentAlignment = Alignment.Center
) {
val animatedColor by animateColorAsState(
if (isSelect) MyColors.White else MyColors.Black,
label = "color"
)
val animatedColor = if (isSelect) MyColors.White else MyColors.Black
Text(
text = day,
fontSize = MaterialTheme.typography.bodyMedium.fontSize,
@@ -1,7 +1,5 @@
package com.bbitcn.f8.pad.ui.screen.view.common
import androidx.compose.animation.slideInVertically
import androidx.compose.animation.slideOutVertically
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
@@ -1,7 +1,5 @@
package com.cyberecho.ui.view
import androidx.compose.animation.core.animateDp
import androidx.compose.animation.core.updateTransition
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.offset
import androidx.compose.material.icons.Icons
@@ -12,18 +10,12 @@ import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import com.bbitcn.f8.pad.M
private enum class Visibility {
VISIBLE,
GONE
}
/**
* 公共组件:跳转按钮(可用于顶部/底部)
*/
@@ -36,16 +28,7 @@ private fun JumpTo(
text: String,
bottomOffsetWhenVisible: Dp = 32.dp // 可配置偏移
) {
val transition = updateTransition(
targetState = if (enabled) Visibility.VISIBLE else Visibility.GONE,
label = "JumpToButton visibility"
)
val bottomOffset by transition.animateDp(
label = "JumpToButton offset"
) { state ->
if (state == Visibility.GONE) -bottomOffsetWhenVisible else bottomOffsetWhenVisible
}
val bottomOffset = if (enabled) bottomOffsetWhenVisible else -bottomOffsetWhenVisible
if (bottomOffset > 0.dp) {
ExtendedFloatingActionButton(
@@ -1,12 +1,5 @@
package com.bbitcn.f8.pad.ui.screen.view.deviceManager.scale
import androidx.compose.animation.AnimatedContent
import androidx.compose.animation.SizeTransform
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.animation.slideInVertically
import androidx.compose.animation.slideOutVertically
import androidx.compose.animation.togetherWith
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
@@ -105,4 +98,4 @@ fun MyWeightShow(
}
}
}
}
}
@@ -1,6 +1,5 @@
package com.bbitcn.f8.pad.ui.screen.view.drawer
import androidx.compose.animation.animateContentSize
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
+21 -12
View File
@@ -1,26 +1,35 @@
pluginManagement {
repositories {
google {
content {
includeGroupByRegex("com\\.android.*")
includeGroupByRegex("com\\.google.*")
includeGroupByRegex("androidx.*")
}
}
// 国内环境优先
maven { url = uri("https://maven.aliyun.com/repository/google") }
maven { url = uri("https://maven.aliyun.com/repository/gradle-plugin") }
maven { url = uri("https://maven.aliyun.com/repository/public") }
// 官方兜底
google()
mavenCentral()
gradlePluginPortal()
}
}
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
mavenCentral()
google()
maven { url = uri("https://maven.aliyun.com/repository/gradle-plugin") }
// AndroidX / Compose / Google 相关依赖
maven { url = uri("https://maven.aliyun.com/repository/google") }
// Maven Central 镜像
maven { url = uri("https://maven.aliyun.com/repository/public") }
maven { url = uri("https://jitpack.io") } // 保留一次 jitpack.io
// 官方兜底
google()
mavenCentral()
// 你的 com.github.* 依赖需要它
maven { url = uri("https://jitpack.io") }
}
}
rootProject.name = "f8"
include(":app")
include(":app")