| | |
| | | position = XAxis.XAxisPosition.BOTTOM |
| | | setDrawGridLines(false) |
| | | granularity = 1f |
| | | labelRotationAngle = -45f |
| | | textSize = 10f |
| | | labelRotationAngle = 0f |
| | | textSize = 12f |
| | | setExtraBottomOffset(15f) |
| | | } |
| | | |
| | | // Y轴设置 |
| | | axisLeft.apply { |
| | | setDrawGridLines(true) |
| | | axisMinimum = 0f |
| | | granularity = 0.5f // 将刻度间隔设为0.5 |
| | | granularity = 1f |
| | | valueFormatter = object : ValueFormatter() { |
| | | override fun getFormattedValue(value: Float): String { |
| | | // 只有整数时才显示标签 |
| | | return if (value % 1 == 0f) { |
| | | value.toInt().toString() |
| | | } else { |
| | | "" |
| | | } |
| | | return if (value > 0) value.toInt().toString() else "" |
| | | } |
| | | } |
| | | } |
| | |
| | | setTouchEnabled(true) |
| | | isDragEnabled = true |
| | | setScaleEnabled(true) |
| | | |
| | | // 设置边距 |
| | | setExtraOffsets(10f, 10f, 10f, 20f) |
| | | } |
| | | |
| | | updateBarChartData() |
| | |
| | | if (stats.isEmpty()) return@observe |
| | | |
| | | val entries = stats.mapIndexed { index, stat -> |
| | | BarEntry(index.toFloat(), stat.count.toFloat()) |
| | | val entry = BarEntry(index.toFloat(), stat.count.toFloat()) |
| | | if (stat.count == 0) { |
| | | entry.data = "hide_label" |
| | | } |
| | | entry |
| | | } |
| | | |
| | | val dataSet = BarDataSet(entries, "包裹数量") |
| | |
| | | valueTextSize = 12f |
| | | valueFormatter = object : ValueFormatter() { |
| | | override fun getFormattedValue(value: Float): String { |
| | | return value.toInt().toString() |
| | | return if (value > 0) value.toInt().toString() else "" |
| | | } |
| | | } |
| | | } |
| | |
| | | return when(currentDateType) { |
| | | DateType.WEEK -> { |
| | | val weekStat = stats[position] |
| | | val calendar = Calendar.getInstance() |
| | | calendar.timeInMillis = weekStat.weekStart!! |
| | | SimpleDateFormat("MM/dd", Locale.getDefault()).format(calendar.time) |
| | | try { |
| | | // 解析日期字符串 |
| | | val sdf = SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()) |
| | | val date = sdf.parse(weekStat.date) |
| | | val calendar = Calendar.getInstance() |
| | | calendar.time = date |
| | | |
| | | // 获取年份和周数 |
| | | val weekOfYear = calendar.get(Calendar.WEEK_OF_YEAR) |
| | | val year = calendar.get(Calendar.YEAR) |
| | | |
| | | // 显示格式:第X周 |
| | | // "第${weekOfYear}周" |
| | | "${weekOfYear}" |
| | | } catch (e: Exception) { |
| | | weekStat.date |
| | | } |
| | | } |
| | | // DateType.MONTH -> "${stats[position].date}月" |
| | | DateType.MONTH -> { |
| | | // 显示月份标签(1-12月) |
| | | "${position + 1}月" |
| | | stats[position].date.replaceFirst("^0+".toRegex(), "") |
| | | } |
| | | else -> "" |
| | | } |
| | |
| | | return "" |
| | | } |
| | | } |
| | | position = XAxis.XAxisPosition.BOTTOM |
| | | setDrawGridLines(false) |
| | | labelCount = stats.size |
| | | granularity = 1f |
| | | labelRotationAngle = -45f |
| | | textSize = 10f |
| | | setAvoidFirstLastClipping(true) |
| | | labelRotationAngle = 0f |
| | | |
| | | // 增加标签间距 |
| | | // setExtraBottomOffset(20f) |
| | | textSize = 11f // 稍微调小字体 |
| | | } |
| | | |
| | | // 高亮当前月份 |
| | | // 高亮显示 |
| | | if (currentDateType == DateType.MONTH) { |
| | | val currentMonth = currentDate.get(Calendar.MONTH) |
| | | dataSet.setColors(List(stats.size) { index -> |
| | |
| | | else resources.getColor(R.color.purple_200) |
| | | }) |
| | | } else if (currentDateType == DateType.WEEK) { |
| | | // 保持周视图的高亮逻辑 |
| | | val highlightIndex = 3f |
| | | val highlightIndex = 3 // 当前周在第4个位置 |
| | | dataSet.setColors(List(stats.size) { index -> |
| | | if (index == 3) resources.getColor(R.color.purple_500) |
| | | if (index == highlightIndex) resources.getColor(R.color.purple_500) |
| | | else resources.getColor(R.color.purple_200) |
| | | }) |
| | | } |
| | | |
| | | // 刷新图表 |
| | | barChart.notifyDataSetChanged() |
| | | barChart.invalidate() |
| | | } |
| | | } |
| | | private fun setupPieChart() { |
| | | pieChart.apply { |
| | | // 隐藏图表描述(右下角默认文字) |
| | | description.isEnabled = false |
| | | // 显示实际值而非百分比 |
| | | setUsePercentValues(false) |
| | | // 隐藏饼图区块上的标签(如数值或名称) |
| | | setDrawEntryLabels(false) |
| | | |
| | | // 调整饼图边距 |
| | | setExtraOffsets(20f, 10f, 60f, 10f) |
| | | |
| | | |
| | | // 设置饼图与容器的边距,参数顺序:左、上、右、下 |
| | | // 右侧留出 80f 空间,可能为图例腾出位置 |
| | | setExtraOffsets(20f, 20f, 20f, 20f) |
| | | |
| | | |
| | | |
| | | // 配置图例 |
| | | legend.apply { |
| | | isEnabled = true |
| | | verticalAlignment = Legend.LegendVerticalAlignment.CENTER |
| | | horizontalAlignment = Legend.LegendHorizontalAlignment.RIGHT |
| | | orientation = Legend.LegendOrientation.VERTICAL |
| | | setDrawInside(false) |
| | | xEntrySpace = 10f |
| | | yEntrySpace = 5f |
| | | yOffset = 0f |
| | | textSize = 14f |
| | | isEnabled = true // 启用图例 |
| | | verticalAlignment = Legend.LegendVerticalAlignment.CENTER // 垂直居中 |
| | | horizontalAlignment = Legend.LegendHorizontalAlignment.RIGHT // 水平靠右对齐 |
| | | orientation = Legend.LegendOrientation.VERTICAL // 图例项垂直排列 |
| | | setDrawInside(false) // 图例绘制在图表外部(而非覆盖在图上) |
| | | xEntrySpace = 10f // 图例项水平间距 |
| | | yEntrySpace = 5f // 图例项垂直间距 |
| | | yOffset = 0f // 图例整体 Y 轴无偏移 |
| | | textSize = 12f // 图例文字大小 |
| | | } |
| | | |
| | | // 设置中心空白 |
| | | holeRadius = 45f |
| | | transparentCircleRadius = 50f |
| | | // 调整中心空白区域大小 |
| | | holeRadius = 20f // 中间空心圆的半径(占饼图比例) |
| | | transparentCircleRadius = 25f // 透明圆圈的半径(可能用于边框效果) |
| | | |
| | | } |
| | | |
| | | updatePieChartData() |