You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SwiftUI Charts垂直方向AxisValueLabel添加padding异常问题

SwiftUI Charts AxisValueLabel 垂直方向拉伸与位置对齐问题解决

问题现象

在SwiftUI Charts开发中遇到两个核心问题:

  • 当AxisValueLabel的orientation设为.horizontal时,添加padding可正常调整标签位置(比如上移让底部对齐网格线);但设为.vertical/.verticalReversed时,文本会出现拉伸变形,且偏离网格线。
  • 即便通过if条件区分水平/垂直场景,不给水平标签加padding,垂直标签依然会出现拉伸问题。

期望实现的效果:

  1. 水平标签:上移指定像素,底部与网格线对齐
  2. 垂直标签:居中显示,无拉伸变形

问题根源

AxisValueLabel在垂直方向布局时,会默认给内部内容视图施加填充整个可用空间的约束,直接返回Text会被强制拉伸;而水平方向的布局约束相对宽松,padding可以正常调整位置。

解决方案

针对两种场景分别处理,通过给垂直标签的文本添加尺寸约束避免拉伸,同时调整水平标签的位置:

修改后的完整代码

struct Workout: Identifiable {
    let id = UUID()
    let day: String
    let minutes: Int
}

extension Workout {
    static let walkWorkout: [Workout] = [
        .init(day: NSLocalizedString("mon", comment: ""), minutes: 23),
        .init(day: "Tue", minutes: 35),
        .init(day: "Wed", minutes: 55),
        .init(day: "Thu", minutes: 30),
        .init(day: "Fri", minutes: 15),
        .init(day: "Sat", minutes: 65),
        .init(day: "Sun", minutes: 81),
    ]
    
    static let runWorkout: [Workout] = [
        .init(day: NSLocalizedString("mon", comment: ""), minutes: 16),
        .init(day: "Tue", minutes: 12),
        .init(day: "Wed", minutes: 55),
        .init(day: "Thu", minutes: 34),
        .init(day: "Fri", minutes: 22),
        .init(day: "Sat", minutes: 43),
        .init(day: "Sun", minutes: 90),
    ]
}

import Charts
import SwiftUI

struct YAxisVerticalLabel: View {
    @State private var isCentered = true
    let workoutData = [
        (workoutType: "Walk", data: Workout.walkWorkout),
        (workoutType: "Run", data: Workout.runWorkout)
    ]
    
    var body: some View {
        VStack {
            Chart {
                ForEach(workoutData, id: \.workoutType) { element in
                    ForEach(element.data) {
                        BarMark(
                            x: .value("Day", $0.day),
                            y: .value("Workout(in minutes)", $0.minutes)
                        )
                    }
                    .foregroundStyle(by: .value("Workout(type)", element.workoutType))
                    .position(by: .value("Workout(type)", element.workoutType))
                }
            }
            .frame(height: 200)
            .chartYAxis {
                AxisMarks(position: .leading) { axis in
                    AxisGridLine()
                    AxisValueLabel(
                        centered: isCentered,
                        orientation: isCentered ? .verticalReversed : .horizontal
                    ) {
                        let labelText = Text("\(axis.index * 25)s")
                            .foregroundStyle(.black)
                        
                        if isCentered {
                            // 垂直标签:固定尺寸避免拉伸,同时居中
                            labelText
                                .fixedSize()
                                .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .center)
                        } else {
                            // 水平标签:添加bottom padding让底部对齐网格线
                            labelText
                                .padding(.bottom, 8)
                        }
                    }
                }
            }
        }
    }
}

关键修改点

  1. 垂直标签处理:

    • 给Text添加.fixedSize(),强制文本保持自身固有尺寸,避免被拉伸
    • 用.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .center)让文本在AxisValueLabel的可用空间内居中显示
  2. 水平标签处理:

    • 保留原有的.padding(.bottom, 8),让标签上移,底部与网格线对齐

效果验证

  • isCentered = false时:水平标签底部对齐网格线,无拉伸
  • isCentered = true时:垂直标签居中显示,文本保持正常尺寸,无拉伸变形

内容的提问来源于stack exchange,提问作者Asif Raza

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 21:37:32