SwiftUI ScrollView 不会将内容与 GeometryReader 居中
SwiftUI ScrollView won't center content with GeometryReader
我在 SwiftUI 中有一个水平滚动视图,我想 'dynamically' 居中。滚动视图中的内容将是一个动态图表,用户可以通过改变年份来改变它的宽度(5、10、15 年图表水平增长)。
无论如何我有两个问题:
我在水平滚动视图中的内容似乎是左对齐的,任何使用填充将其居中的尝试只会使其偏离居中,并且难以考虑各种屏幕尺寸。
当我尝试使用 GeometryReader 时,底部图表的 'legend' 被推到页面底部,Spacer() 无法修复它。
struct ChartView: View {
var body: some View {
VStack(alignment: .center) {
GeometryReader { geo in
ScrollView(.horizontal, showsIndicators: false) {
HStack {
ForEach(0..<self.chartSettings.getChartYears(), id:\.self) { index in
ColumnView()
}
}
}
.background(Color.gray)
.frame(maxHeight: geo.size.height/2)
}
//Chart Legend
HStack{
Rectangle()
.frame(width: 10, height: 10)
.foregroundColor(Color.init(#colorLiteral(red: 0.4666666687, green: 0.7647058964, blue: 0.2666666806, alpha: 1)))
Text("First Value")
.font(.system(size: 12))
Rectangle()
.frame(width: 10, height: 10)
.foregroundColor(Color.init(#colorLiteral(red: 0.2263821661, green: 0.4659538441, blue: 0.08977641062, alpha: 1)))
Text("Second Value")
.font(.system(size: 12))
}
}
}
}
Left 是当前代码的样子,right 是我希望的样子,不管屏幕如何 size/iPhone型号。
注意这就是我使用滚动视图的原因:
<iframe src='https://gfycat.com/ifr/DeficientNiceInchworm' frameborder='0' scrolling='no' allowfullscreen width='400' height='210'></iframe>
将 GeometryReader
移到 VStack
之外:
struct ChartView: View {
var body: some View {
GeometryReader { geo in
VStack(alignment: .center) {
ScrollView(.horizontal, showsIndicators: false) {
HStack {
ForEach(0..<self.chartSettings.getChartYears(), id:\.self) { index in
ColumnView()
}
}
}
.background(Color.gray)
.frame(maxHeight: geo.size.height/2)
//Chart Legend
HStack{
Rectangle()
.frame(width: 10, height: 10)
.foregroundColor(Color.init(#colorLiteral(red: 0.4666666687, green: 0.7647058964, blue: 0.2666666806, alpha: 1)))
Text("First Value")
.font(.system(size: 12))
Rectangle()
.frame(width: 10, height: 10)
.foregroundColor(Color.init(#colorLiteral(red: 0.2263821661, green: 0.4659538441, blue: 0.08977641062, alpha: 1)))
Text("Second Value")
.font(.system(size: 12))
}
}
}
}
}
注意:水平滚动视图内容总是从左边开始(不是对齐方式)。如果您只想在屏幕上居中 HStack
- 删除 ScrollView
.
为了使您的图表在 ScrollView
中正确居中,请将内容的最小宽度设置为与 ScrollView
本身的宽度相同。为此,请在 ScrollView
内的 HStack
上调用 .frame(minWidth: geo.size.width)
。可以找到此解决方案的完整解释 .
图例被推到屏幕底部的原因是 GeometryReader
本身就是一个视图,可以扩展以填充所有可用的 space。我可以想到两种解决方案来解决这个问题。
解决方案 1 - 静态图表高度
如果图表的高度是静态的,或者如果您在呈现视图之前知道高度,则可以使用该已知尺寸来设置 GeometryReader
.
struct ChartView: View {
private let chartHeight: CGFloat = 300 // declare a height parameter
var body: some View {
VStack(alignment: .center) {
GeometryReader { geo in
ScrollView(.horizontal, showsIndicators: false) {
HStack {
ForEach(0..<self.chartSettings.getChartYears(), id:\.self) { index in
ColumnView()
}
}
.frame(minWidth: geo.size.width)
}
.background(Color.gray)
}
.frame(height: chartHeight) // set the height of the GeometryReader
//Chart Legend
HStack{
Rectangle()
.frame(width: 10, height: 10)
.foregroundColor(Color.init(#colorLiteral(red: 0.4666666687, green: 0.7647058964, blue: 0.2666666806, alpha: 1)))
Text("First Value")
.font(.system(size: 12))
Rectangle()
.frame(width: 10, height: 10)
.foregroundColor(Color.init(#colorLiteral(red: 0.2263821661, green: 0.4659538441, blue: 0.08977641062, alpha: 1)))
Text("Second Value")
.font(.system(size: 12))
}
}
}
}
解决方案 2 - 动态图表高度
如果你想让图表的高度是动态的,让ScrollView
根据内容来决定它的高度,你可以使用Spacers()
并调用.layoutPriority(0)
方法在他们上面,以便 GeometryReader
和 spacers 在展示他们的观点时得到同等的优先权。使用此解决方案,GeometryReader
只会在 ScrollView
.
周围放置一个小的默认填充
如果您希望图例更接近 ScrollView
,您可以选择使用负填充值。
struct ChartView: View {
var body: some View {
VStack(alignment: .center) {
Spacer().layoutPriority(0) // add a spacer above
GeometryReader { geo in
ScrollView(.horizontal, showsIndicators: false) {
HStack {
ForEach(0..<self.chartSettings.getChartYears(), id:\.self) { index in
ColumnView()
}
}
.frame(minWidth: geo.size.width)
}
.background(Color.gray)
}
//Chart Legend
HStack{
Rectangle()
.frame(width: 10, height: 10)
.foregroundColor(Color.init(#colorLiteral(red: 0.4666666687, green: 0.7647058964, blue: 0.2666666806, alpha: 1)))
Text("First Value")
.font(.system(size: 12))
Rectangle()
.frame(width: 10, height: 10)
.foregroundColor(Color.init(#colorLiteral(red: 0.2263821661, green: 0.4659538441, blue: 0.08977641062, alpha: 1)))
Text("Second Value")
.font(.system(size: 12))
}
.padding(.top, -20) // optionally move the legend closer to the ScrollView
Spacer().layoutPriority(0) // add a spacer below
}
}
}
我在 SwiftUI 中有一个水平滚动视图,我想 'dynamically' 居中。滚动视图中的内容将是一个动态图表,用户可以通过改变年份来改变它的宽度(5、10、15 年图表水平增长)。
无论如何我有两个问题:
我在水平滚动视图中的内容似乎是左对齐的,任何使用填充将其居中的尝试只会使其偏离居中,并且难以考虑各种屏幕尺寸。
当我尝试使用 GeometryReader 时,底部图表的 'legend' 被推到页面底部,Spacer() 无法修复它。
struct ChartView: View {
var body: some View {
VStack(alignment: .center) {
GeometryReader { geo in
ScrollView(.horizontal, showsIndicators: false) {
HStack {
ForEach(0..<self.chartSettings.getChartYears(), id:\.self) { index in
ColumnView()
}
}
}
.background(Color.gray)
.frame(maxHeight: geo.size.height/2)
}
//Chart Legend
HStack{
Rectangle()
.frame(width: 10, height: 10)
.foregroundColor(Color.init(#colorLiteral(red: 0.4666666687, green: 0.7647058964, blue: 0.2666666806, alpha: 1)))
Text("First Value")
.font(.system(size: 12))
Rectangle()
.frame(width: 10, height: 10)
.foregroundColor(Color.init(#colorLiteral(red: 0.2263821661, green: 0.4659538441, blue: 0.08977641062, alpha: 1)))
Text("Second Value")
.font(.system(size: 12))
}
}
}
}
Left 是当前代码的样子,right 是我希望的样子,不管屏幕如何 size/iPhone型号。
注意这就是我使用滚动视图的原因:
<iframe src='https://gfycat.com/ifr/DeficientNiceInchworm' frameborder='0' scrolling='no' allowfullscreen width='400' height='210'></iframe>
将 GeometryReader
移到 VStack
之外:
struct ChartView: View {
var body: some View {
GeometryReader { geo in
VStack(alignment: .center) {
ScrollView(.horizontal, showsIndicators: false) {
HStack {
ForEach(0..<self.chartSettings.getChartYears(), id:\.self) { index in
ColumnView()
}
}
}
.background(Color.gray)
.frame(maxHeight: geo.size.height/2)
//Chart Legend
HStack{
Rectangle()
.frame(width: 10, height: 10)
.foregroundColor(Color.init(#colorLiteral(red: 0.4666666687, green: 0.7647058964, blue: 0.2666666806, alpha: 1)))
Text("First Value")
.font(.system(size: 12))
Rectangle()
.frame(width: 10, height: 10)
.foregroundColor(Color.init(#colorLiteral(red: 0.2263821661, green: 0.4659538441, blue: 0.08977641062, alpha: 1)))
Text("Second Value")
.font(.system(size: 12))
}
}
}
}
}
注意:水平滚动视图内容总是从左边开始(不是对齐方式)。如果您只想在屏幕上居中 HStack
- 删除 ScrollView
.
为了使您的图表在 ScrollView
中正确居中,请将内容的最小宽度设置为与 ScrollView
本身的宽度相同。为此,请在 ScrollView
内的 HStack
上调用 .frame(minWidth: geo.size.width)
。可以找到此解决方案的完整解释
图例被推到屏幕底部的原因是 GeometryReader
本身就是一个视图,可以扩展以填充所有可用的 space。我可以想到两种解决方案来解决这个问题。
解决方案 1 - 静态图表高度
如果图表的高度是静态的,或者如果您在呈现视图之前知道高度,则可以使用该已知尺寸来设置 GeometryReader
.
struct ChartView: View {
private let chartHeight: CGFloat = 300 // declare a height parameter
var body: some View {
VStack(alignment: .center) {
GeometryReader { geo in
ScrollView(.horizontal, showsIndicators: false) {
HStack {
ForEach(0..<self.chartSettings.getChartYears(), id:\.self) { index in
ColumnView()
}
}
.frame(minWidth: geo.size.width)
}
.background(Color.gray)
}
.frame(height: chartHeight) // set the height of the GeometryReader
//Chart Legend
HStack{
Rectangle()
.frame(width: 10, height: 10)
.foregroundColor(Color.init(#colorLiteral(red: 0.4666666687, green: 0.7647058964, blue: 0.2666666806, alpha: 1)))
Text("First Value")
.font(.system(size: 12))
Rectangle()
.frame(width: 10, height: 10)
.foregroundColor(Color.init(#colorLiteral(red: 0.2263821661, green: 0.4659538441, blue: 0.08977641062, alpha: 1)))
Text("Second Value")
.font(.system(size: 12))
}
}
}
}
解决方案 2 - 动态图表高度
如果你想让图表的高度是动态的,让ScrollView
根据内容来决定它的高度,你可以使用Spacers()
并调用.layoutPriority(0)
方法在他们上面,以便 GeometryReader
和 spacers 在展示他们的观点时得到同等的优先权。使用此解决方案,GeometryReader
只会在 ScrollView
.
如果您希望图例更接近 ScrollView
,您可以选择使用负填充值。
struct ChartView: View {
var body: some View {
VStack(alignment: .center) {
Spacer().layoutPriority(0) // add a spacer above
GeometryReader { geo in
ScrollView(.horizontal, showsIndicators: false) {
HStack {
ForEach(0..<self.chartSettings.getChartYears(), id:\.self) { index in
ColumnView()
}
}
.frame(minWidth: geo.size.width)
}
.background(Color.gray)
}
//Chart Legend
HStack{
Rectangle()
.frame(width: 10, height: 10)
.foregroundColor(Color.init(#colorLiteral(red: 0.4666666687, green: 0.7647058964, blue: 0.2666666806, alpha: 1)))
Text("First Value")
.font(.system(size: 12))
Rectangle()
.frame(width: 10, height: 10)
.foregroundColor(Color.init(#colorLiteral(red: 0.2263821661, green: 0.4659538441, blue: 0.08977641062, alpha: 1)))
Text("Second Value")
.font(.system(size: 12))
}
.padding(.top, -20) // optionally move the legend closer to the ScrollView
Spacer().layoutPriority(0) // add a spacer below
}
}
}