我正在尝试在 SwiftUI 中创建一个像这样的视图(抱歉它太大了):
具体来说,我正在尝试在屏幕的顶部四分之一处构建滚动的标签/条形图栏行。
对我来说,它看起来像一个水平滚动的 ScrollView,包含一定数量的“barGraphItems”,每个“barGraphItems”都是一个 270 度旋转的标签和一个彩色矩形。
这是我到目前为止的代码:VStack
这是它产生的结果(抱歉它太大了):
如何让 barGraphItems 靠得更近? 如何添加“预算”行? 如何在不滚动预算行的情况下使整个业务可滚动?
我
认为屏幕上的其他元素我可以弄清楚,但我整个下午都在摆弄这个条形图小部件,我被难住了。
不同的方法看起来更合适。这个想法是将绘图条作为矩形,其中高度或矩形显示值,而标签是此类矩形的转换覆盖,因此矩形形成布局,并且覆盖不会影响任何内容(几乎)。
使用 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()
}
}
中。
我用这个替换了你的代码: - 这些更改通过向文本添加 .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
}
}
}