安卓代码解读

一、UI图

销售概览

一、源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
@Composable
fun HomeManagerSaleTargetView(
vm: HomeViewModel = viewModel()
) {
Column(
verticalArrangement = Arrangement.spacedBy(10.dp),
modifier = Modifier
.background(
brush = Brush.horizontalGradient(
colors = listOf(
Color(0xFFFF4500),
Color(0xFFFD8400)
)
), RoundedCornerShape(10.dp)
)
.padding(10.dp)
.fillMaxWidth()
) {
Row(
verticalAlignment = Alignment.CenterVertically,
) {
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(5.dp),
modifier = Modifier.weight(1f)
) {
Text(text = "本月销售额", fontSize = 16.sp, color = CustomColors.white)
}
Row(
modifier = Modifier
.border(1.dp, CustomColors.white, CircleShape)
.clip(CircleShape)
) {
IdentifierType.entries.forEach { type ->
val select = vm.saleIdentifier == type
//身份类型(1-团队;2-个人);
Text(
text = type.name,
fontSize = 14.sp,
color = if (select) CustomColors.main else CustomColors.white,
modifier = Modifier
.fantasyClick {
vm.saleIdentifier = type
vm.getHomeSalesOverview()
}
.background(if (select) CustomColors.white else Color.Transparent)
.padding(10.dp, 5.dp)
)
}

}
}
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(15.dp),
) {
Text(
text = vm.saleOverview?.monthSalesAmount ?: "0",
style = XMFont.f24.boldMedium.white,
modifier = Modifier.fantasyClick {
routeToPage(RouterPath.ComposeWebview) {
withString(
"url", ProjectConfig.monthSaleUrl(
onlySelf = if (vm.saleIdentifier == IdentifierType.个人) 1 else 0
)
)
}
}
)
}
NDDashLine()
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(10.dp),
modifier = Modifier.fantasyClick {
routeToPage(RouterPath.ComposeWebview) {
withString("url", ProjectConfig.应收账款(responsiblePartyType = vm.saleIdentifier.value))
}
}
) {
Text(
text = "应收账款总额",
fontSize = 14.sp,
color = CustomColors.white
)
Text(
text = vm.saleOverview?.receivableAmount ?: "0",
fontSize = 14.sp,
color = CustomColors.white
)
Spacer(modifier = Modifier.weight(1f))
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(5.dp),
modifier = Modifier.fantasyClick {
routeToPage(RouterPath.ComposeWebview) {
withString(
"url", ProjectConfig.monthSaleUrl(
onlySelf = if (vm.saleIdentifier == IdentifierType.个人) 1 else 0,
isToday = true
)
)
}
}
) {
Text(
text = "今日销售额¥${vm.saleOverview?.todaySalesAmount ?: 0}",
style = XMFont.f14.white
)
Icon(
id = R.drawable.common_filter_arrow_up,
tint = CustomColors.white,
modifier = Modifier
.rotate(90f)
.scale(1.2f)
)
}
}
}
}

二、解读

基本概念

  • Column: 垂直排列元素的容器,子元素从上到下排列
  • Row: 水平排列元素的容器,子元素从左到右排列

UI与代码对应分析

从图片看,这是一个销售数据卡片,橙色渐变背景,包含销售额和应收账款信息。

整体结构

1
2
3
4
5
6
7
8
Column (整个卡片)
├── Row 1 (标题行:左边"本月销售额",右边选择器)
│ ├── Row 1.1 (左侧标题)
│ └── Row 1.2 (右侧身份选择器)
├── Row 2 (销售额数据:左边金额,右边今日数据)
│ └── Row 2.1 (右侧今日数据与箭头)
├── NDDashLine (虚线分隔)
└── Row 3 (应收账款行)

详细解析

  1. 最外层Column:
  • 橙色渐变背景
  • 内部元素垂直排列
  • 包含所有销售数据
  1. 第一行(Row):
  • 左侧文本”本月销售额”
  • 右侧身份切换器(个人/团队)
  1. 第二行(Row):
  • 左侧显示销售额金额
  • 右侧显示今日销售额(内部是另一个Row,包含文本和箭头图标)
  1. 虚线分隔
  2. 第三行(Row):
  • 应收账款信息

嵌套关系实例

以第一行为例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Row(verticalAlignment = Alignment.CenterVertically) {
Row(
// 左侧"本月销售额"
modifier = Modifier.weight(1f)
) {
Text(text = "本月销售额")
}
Row(
// 右侧身份选择器
) {
IdentifierType.entries.forEach { type ->
Text(text = type.name)
}
}
}

这里Row里面嵌套Row的目的是:

  • 外层Row确保左右两部分的布局关系(左侧标题、右侧选择器)
  • 内层Row分别处理各自区域的布局细节
  • weight(1f)使左侧占据所有剩余空间
    从UI看:外层Row水平分为两部分,右侧内层Row再水平排列”个人”和”团队”两个选项。