diff --git a/app/src/main/java/com/bbitcn/f8/pad/MyApp.kt b/app/src/main/java/com/bbitcn/f8/pad/MyApp.kt index 8119da5..fcb05da 100644 --- a/app/src/main/java/com/bbitcn/f8/pad/MyApp.kt +++ b/app/src/main/java/com/bbitcn/f8/pad/MyApp.kt @@ -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 // 是否是调试状态 diff --git a/app/src/main/java/com/bbitcn/f8/pad/base/BaseList.kt b/app/src/main/java/com/bbitcn/f8/pad/base/BaseList.kt index 05632fd..51cf826 100644 --- a/app/src/main/java/com/bbitcn/f8/pad/base/BaseList.kt +++ b/app/src/main/java/com/bbitcn/f8/pad/base/BaseList.kt @@ -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>, 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 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 MyTable2( val lineItem = infos[index] Card( - modifier = MD + modifier = M .pointerInput(Unit) { detectTapGestures( onLongPress = { @@ -508,7 +519,7 @@ fun MyRefreshTable( } LaunchedEffect(info.loadState.refresh) { if (info.loadState.refresh is LoadState.NotLoading && scrollToTopOnRefresh) { - listState.animateScrollToItem(0) + listState.scrollToItem(0) } } @@ -544,11 +555,15 @@ fun 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 MyRefreshTable( } } } - item { + item(contentType = "paging-footer") { when (pagerSate) { is LoadState.NotLoading -> if (pagerSate.endOfPaginationReached) ListNoMore() diff --git a/app/src/main/java/com/bbitcn/f8/pad/base/CustomMaterialComponents.kt b/app/src/main/java/com/bbitcn/f8/pad/base/CustomMaterialComponents.kt index e47fd2a..30809df 100644 --- a/app/src/main/java/com/bbitcn/f8/pad/base/CustomMaterialComponents.kt +++ b/app/src/main/java/com/bbitcn/f8/pad/base/CustomMaterialComponents.kt @@ -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 ) { diff --git a/app/src/main/java/com/bbitcn/f8/pad/ui/MainActivity.kt b/app/src/main/java/com/bbitcn/f8/pad/ui/MainActivity.kt index 79f28a9..7624725 100644 --- a/app/src/main/java/com/bbitcn/f8/pad/ui/MainActivity.kt +++ b/app/src/main/java/com/bbitcn/f8/pad/ui/MainActivity.kt @@ -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") { diff --git a/app/src/main/java/com/bbitcn/f8/pad/ui/screen/TopBar.kt b/app/src/main/java/com/bbitcn/f8/pad/ui/screen/TopBar.kt index 3f628ae..219647e 100644 --- a/app/src/main/java/com/bbitcn/f8/pad/ui/screen/TopBar.kt +++ b/app/src/main/java/com/bbitcn/f8/pad/ui/screen/TopBar.kt @@ -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) { diff --git a/app/src/main/java/com/bbitcn/f8/pad/ui/screen/dialog/AIListenerDialog.kt b/app/src/main/java/com/bbitcn/f8/pad/ui/screen/dialog/AIListenerDialog.kt index 47da3b9..f5daa93 100644 --- a/app/src/main/java/com/bbitcn/f8/pad/ui/screen/dialog/AIListenerDialog.kt +++ b/app/src/main/java/com/bbitcn/f8/pad/ui/screen/dialog/AIListenerDialog.kt @@ -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) { diff --git a/app/src/main/java/com/bbitcn/f8/pad/ui/screen/dialog/ChatDialog.kt b/app/src/main/java/com/bbitcn/f8/pad/ui/screen/dialog/ChatDialog.kt index 145e303..ff5645e 100644 --- a/app/src/main/java/com/bbitcn/f8/pad/ui/screen/dialog/ChatDialog.kt +++ b/app/src/main/java/com/bbitcn/f8/pad/ui/screen/dialog/ChatDialog.kt @@ -226,7 +226,7 @@ fun Messages( enabled = jumpToBottomButtonEnabled, onClicked = { scope.launch { - scrollState.animateScrollToItem(0) + scrollState.scrollToItem(0) } }, modifier = M.align(Alignment.BottomCenter) diff --git a/app/src/main/java/com/bbitcn/f8/pad/ui/screen/dialog/DateRangeSelectDialog.kt b/app/src/main/java/com/bbitcn/f8/pad/ui/screen/dialog/DateRangeSelectDialog.kt index 89c2dc6..f5ee756 100644 --- a/app/src/main/java/com/bbitcn/f8/pad/ui/screen/dialog/DateRangeSelectDialog.kt +++ b/app/src/main/java/com/bbitcn/f8/pad/ui/screen/dialog/DateRangeSelectDialog.kt @@ -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, diff --git a/app/src/main/java/com/bbitcn/f8/pad/ui/screen/dialog/LoadingDialog.kt b/app/src/main/java/com/bbitcn/f8/pad/ui/screen/dialog/LoadingDialog.kt index e819fed..90dbece 100644 --- a/app/src/main/java/com/bbitcn/f8/pad/ui/screen/dialog/LoadingDialog.kt +++ b/app/src/main/java/com/bbitcn/f8/pad/ui/screen/dialog/LoadingDialog.kt @@ -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( } } } -} \ No newline at end of file +} diff --git a/app/src/main/java/com/bbitcn/f8/pad/ui/screen/dialog/TicketMoreDialog.kt b/app/src/main/java/com/bbitcn/f8/pad/ui/screen/dialog/TicketMoreDialog.kt index b333256..340c9be 100644 --- a/app/src/main/java/com/bbitcn/f8/pad/ui/screen/dialog/TicketMoreDialog.kt +++ b/app/src/main/java/com/bbitcn/f8/pad/ui/screen/dialog/TicketMoreDialog.kt @@ -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 { diff --git a/app/src/main/java/com/bbitcn/f8/pad/ui/screen/dialog/WaterCutRecordDialog.kt b/app/src/main/java/com/bbitcn/f8/pad/ui/screen/dialog/WaterCutRecordDialog.kt index 3a59782..0a45039 100644 --- a/app/src/main/java/com/bbitcn/f8/pad/ui/screen/dialog/WaterCutRecordDialog.kt +++ b/app/src/main/java/com/bbitcn/f8/pad/ui/screen/dialog/WaterCutRecordDialog.kt @@ -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) diff --git a/app/src/main/java/com/bbitcn/f8/pad/ui/screen/mainFunc/FundsScreen.kt b/app/src/main/java/com/bbitcn/f8/pad/ui/screen/mainFunc/FundsScreen.kt index 5ab9ce7..316ca23 100644 --- a/app/src/main/java/com/bbitcn/f8/pad/ui/screen/mainFunc/FundsScreen.kt +++ b/app/src/main/java/com/bbitcn/f8/pad/ui/screen/mainFunc/FundsScreen.kt @@ -145,6 +145,7 @@ fun FundsScreen( Pair(tab.total.toString(), 1), Pair(tab.summoney.toString(), 2) ), + enableClick = true, onClick = { fundsViewModel.updateCurSearchState(tab) onFilterLikeChanged(queryInput) diff --git a/app/src/main/java/com/bbitcn/f8/pad/ui/screen/mainFunc/PurchaseScreen.kt b/app/src/main/java/com/bbitcn/f8/pad/ui/screen/mainFunc/PurchaseScreen.kt index b4b7cea..b89acc3 100644 --- a/app/src/main/java/com/bbitcn/f8/pad/ui/screen/mainFunc/PurchaseScreen.kt +++ b/app/src/main/java/com/bbitcn/f8/pad/ui/screen/mainFunc/PurchaseScreen.kt @@ -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, + 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( diff --git a/app/src/main/java/com/bbitcn/f8/pad/ui/screen/mainFunc/setting/SettingBase.kt b/app/src/main/java/com/bbitcn/f8/pad/ui/screen/mainFunc/setting/SettingBase.kt index 6b997d6..c488453 100644 --- a/app/src/main/java/com/bbitcn/f8/pad/ui/screen/mainFunc/setting/SettingBase.kt +++ b/app/src/main/java/com/bbitcn/f8/pad/ui/screen/mainFunc/setting/SettingBase.kt @@ -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 diff --git a/app/src/main/java/com/bbitcn/f8/pad/ui/screen/mainFunc/setting/SettingScreen.kt b/app/src/main/java/com/bbitcn/f8/pad/ui/screen/mainFunc/setting/SettingScreen.kt index cd170c1..0330280 100644 --- a/app/src/main/java/com/bbitcn/f8/pad/ui/screen/mainFunc/setting/SettingScreen.kt +++ b/app/src/main/java/com/bbitcn/f8/pad/ui/screen/mainFunc/setting/SettingScreen.kt @@ -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 diff --git a/app/src/main/java/com/bbitcn/f8/pad/ui/screen/secondFunc/AddUserScreen.kt b/app/src/main/java/com/bbitcn/f8/pad/ui/screen/secondFunc/AddUserScreen.kt index 41c86b4..d1a2f01 100644 --- a/app/src/main/java/com/bbitcn/f8/pad/ui/screen/secondFunc/AddUserScreen.kt +++ b/app/src/main/java/com/bbitcn/f8/pad/ui/screen/secondFunc/AddUserScreen.kt @@ -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 diff --git a/app/src/main/java/com/bbitcn/f8/pad/ui/screen/secondFunc/WeightScreen.kt b/app/src/main/java/com/bbitcn/f8/pad/ui/screen/secondFunc/WeightScreen.kt index bd5bfe3..9026454 100644 --- a/app/src/main/java/com/bbitcn/f8/pad/ui/screen/secondFunc/WeightScreen.kt +++ b/app/src/main/java/com/bbitcn/f8/pad/ui/screen/secondFunc/WeightScreen.kt @@ -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) diff --git a/app/src/main/java/com/bbitcn/f8/pad/ui/screen/view/common/DatePickerRange.kt b/app/src/main/java/com/bbitcn/f8/pad/ui/screen/view/common/DatePickerRange.kt index 2aad6e5..5224147 100644 --- a/app/src/main/java/com/bbitcn/f8/pad/ui/screen/view/common/DatePickerRange.kt +++ b/app/src/main/java/com/bbitcn/f8/pad/ui/screen/view/common/DatePickerRange.kt @@ -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, diff --git a/app/src/main/java/com/bbitcn/f8/pad/ui/screen/view/common/MyBottomSheet.kt b/app/src/main/java/com/bbitcn/f8/pad/ui/screen/view/common/MyBottomSheet.kt index 1191fa0..91c49b7 100644 --- a/app/src/main/java/com/bbitcn/f8/pad/ui/screen/view/common/MyBottomSheet.kt +++ b/app/src/main/java/com/bbitcn/f8/pad/ui/screen/view/common/MyBottomSheet.kt @@ -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 diff --git a/app/src/main/java/com/bbitcn/f8/pad/ui/screen/view/compose/JumpToBottom.kt b/app/src/main/java/com/bbitcn/f8/pad/ui/screen/view/compose/JumpToBottom.kt index 02f9d00..867f6d9 100644 --- a/app/src/main/java/com/bbitcn/f8/pad/ui/screen/view/compose/JumpToBottom.kt +++ b/app/src/main/java/com/bbitcn/f8/pad/ui/screen/view/compose/JumpToBottom.kt @@ -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( diff --git a/app/src/main/java/com/bbitcn/f8/pad/ui/screen/view/deviceManager/scale/MyWeightShow.kt b/app/src/main/java/com/bbitcn/f8/pad/ui/screen/view/deviceManager/scale/MyWeightShow.kt index fd20afa..3855630 100644 --- a/app/src/main/java/com/bbitcn/f8/pad/ui/screen/view/deviceManager/scale/MyWeightShow.kt +++ b/app/src/main/java/com/bbitcn/f8/pad/ui/screen/view/deviceManager/scale/MyWeightShow.kt @@ -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( } } } -} \ No newline at end of file +} diff --git a/app/src/main/java/com/bbitcn/f8/pad/ui/screen/view/drawer/TicketForPurchase.kt b/app/src/main/java/com/bbitcn/f8/pad/ui/screen/view/drawer/TicketForPurchase.kt index 5385969..1358b7e 100644 --- a/app/src/main/java/com/bbitcn/f8/pad/ui/screen/view/drawer/TicketForPurchase.kt +++ b/app/src/main/java/com/bbitcn/f8/pad/ui/screen/view/drawer/TicketForPurchase.kt @@ -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 diff --git a/settings.gradle.kts b/settings.gradle.kts index 7a026f6..f379ba7 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -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") \ No newline at end of file