SwiftUI Chart嵌套ScrollView时SectorMark位置滚动偏移问题
SwiftUI Chart饼图嵌套ScrollView滚动时偏移问题修复
在SwiftUI中使用新版Chart组件实现饼图并嵌套在ScrollView内时,会出现滚动界面导致SectorMark位置偏移的问题——哪怕仅沿Y轴滚动1像素,饼图内容都会移位,带来怪异的用户体验。
问题代码
enum Gender: String { case male case female case notSet } extension Gender: Plottable { var primitivePlottable: String { rawValue } } struct Stats { let city: String let population: Int let gender: Gender } struct ContentView: View { let stats: [Stats] var body: some View { ScrollView() { Chart { ForEach(stats, id: \.city) { stat in SectorMark( angle: .value("Gender", stat.population), innerRadius: .ratio(0.618), angularInset: 1.5 ) .cornerRadius(5) .foregroundStyle(by: .value("Gender", stat.gender)) } } .chartLegend(alignment: .center, spacing: 18) .scaledToFit() } } }
修复方案
这个问题源于ScrollView滚动时,Chart的动态布局计算出现异常。通过给Chart设置确定的尺寸即可解决:
方案1:固定尺寸Frame
替换原有的.scaledToFit()为明确的宽高frame,让Chart布局稳定:
struct ContentView: View { let stats: [Stats] var body: some View { ScrollView() { Chart { ForEach(stats, id: \.city) { stat in SectorMark( angle: .value("Gender", stat.population), innerRadius: .ratio(0.618), angularInset: 1.5 ) .cornerRadius(5) .foregroundStyle(by: .value("Gender", stat.gender)) } } .chartLegend(alignment: .center, spacing: 18) .frame(width: 300, height: 300) // 固定饼图尺寸 .padding() } } }
方案2:自适应父容器尺寸
使用GeometryReader获取父容器宽度,设置宽高比为1:1的自适应尺寸:
struct ContentView: View { let stats: [Stats] var body: some View { ScrollView() { GeometryReader { geo in Chart { ForEach(stats, id: \.city) { stat in SectorMark( angle: .value("Gender", stat.population), innerRadius: .ratio(0.618), angularInset: 1.5 ) .cornerRadius(5) .foregroundStyle(by: .value("Gender", stat.gender)) } } .chartLegend(alignment: .center, spacing: 18) .frame(width: geo.size.width, height: geo.size.width) // 保持正方形比例 } .padding() } } }
原理:给Chart设置确定尺寸后,ScrollView滚动时不会触发Chart的动态重计算,SectorMark的位置便不会随滚动偏移。
内容的提问来源于stack exchange,提问作者RileyDev
相关产品推荐
相关产品推荐

