SwiftUI - 如何创建具有一些固定元素的水平滚动视图?

问题描述 投票:0回答:2

我正在尝试在 SwiftUI 中创建一个像这样的视图(抱歉它太大了): screen mockup

具体来说,我正在尝试在屏幕的顶部四分之一处构建滚动的标签/条形图栏行。

对我来说,它看起来像一个水平滚动的 ScrollView,包含一定数量的“barGraphItems”,每个“barGraphItems”都是一个 270 度旋转的标签和一个彩色矩形。

这是我到目前为止的代码:

VStack

这是它产生的结果(抱歉它太大了):

swiftui preview 如何让 barGraphItems 靠得更近? 如何添加“预算”行? 如何在不滚动预算行的情况下使整个业务可滚动?

认为

屏幕上的其他元素我可以弄清楚,但我整个下午都在摆弄这个条形图小部件,我被难住了。

swiftui uiscrollview overlay horizontalscrollview
2个回答
2
投票

不同的方法看起来更合适。这个想法是将绘图条作为矩形,其中高度或矩形显示值,而标签是此类矩形的转换覆盖,因此矩形形成布局,并且覆盖不会影响任何内容(几乎)。

使用 Xcode 11.4 / iOS 13.4 进行测试

注意:预算线可以添加到绘图滚动视图上方,方法是将两者都包裹到

import SwiftUI struct ContentView: View { var body: some View { HStack(alignment: .bottom, spacing: 0) { Spacer() VStack(alignment: .leading, spacing: 0) { Text("Demo") .font(.caption) .fontWeight(.bold) Rectangle().foregroundColor(.orange) .frame(width: 84, height: 10) } .rotationEffect(Angle(degrees: 270.0)) VStack(alignment: .leading, spacing: 0) { Text("Demo") .font(.caption) .fontWeight(.bold) Rectangle().foregroundColor(.orange) .frame(width: 84, height: 10) } .rotationEffect(Angle(degrees: 270.0)) VStack(alignment: .leading, spacing: 0) { Text("Demo") .font(.caption) .fontWeight(.bold) Rectangle().foregroundColor(.orange) .frame(width: 84, height: 10) } .rotationEffect(Angle(degrees: 270.0)) VStack(alignment: .leading, spacing: 0) { Text("Demo") .font(.caption) .fontWeight(.bold) Rectangle().foregroundColor(.orange) .frame(width: 84, height: 10) } .rotationEffect(Angle(degrees: 270.0)) VStack(alignment: .leading, spacing: 0) { Text("Demo") .font(.caption) .fontWeight(.bold) Rectangle().foregroundColor(.orange) .frame(width: 84, height: 10) } .rotationEffect(Angle(degrees: 270.0)) } } } struct ContentView_Previews: PreviewProvider { static var previews: some View { ContentView() } } 中。


demo

demo2 ZStack



0
投票

我用这个替换了你的代码: - 这些更改通过向文本添加 .fixedSize() 解决了条形图开始不对齐的问题。

-您可以通过增加或减少 for 循环中的范围来更改条数。这使您无需复制和粘贴相同的代码。

-当您只需要一个时,您正在制作多个 VStack。这解决了间距问题,现在条形将按照定义以 0 间距粘在一起。

希望这有帮助!

struct ContentView_Previews: PreviewProvider { static var previews: some View { VStack(alignment: .leading, spacing: 0) { Text("Title above").font(.largeTitle) ContentView() Text("comment below") } } } struct ContentView: View { var plotHeight: CGFloat = 120 // test with different lenth labels let demos = ["Demo", "Demoos", "Demoooos", "Demooooooos"] var body: some View { ScrollView(.horizontal, showsIndicators: false) { HStack(alignment: .bottom, spacing: 24) { ForEach(0..<20) {_ in Rectangle().foregroundColor(.orange) .frame(width: 14, height: CGFloat.random(in: 0..<self.plotHeight)) // values for demo .overlay( Text(self.demos.randomElement()!) // values for demo .font(.caption) .fontWeight(.bold) .fixedSize() .rotationEffect(Angle(degrees: 270.0), anchor: .leading) .offset(x: -8, y: 6) // align as/if needed here , alignment: .bottomLeading) } } .frame(height: plotHeight, alignment: .bottom) .padding(.leading) // required offset for first label in scrollview } } }

	
© www.soinside.com 2019 - 2024. All rights reserved.