SwiftUI 中文本内容的矩形动态高度

kha*_*ain 5 ios swiftui

我一直在尝试根据标题下方的内容来匹配时间线侧边栏的高度。

但是侧边栏占据了整个高度,有什么方法可以限制它的中间内容的高度。它位于 HStackView 中,如下所示。

            //header
            HStack {
                Circle()
                    .fill(Color.blue)
                    .frame(width: 15, height: 15)
                    .overlay(Circle().inset(by: 2).fill(Color.white))
                
                Text("Headline").font(.headline)
            }.padding(0)

            //content
            HStack {
                VStack {
//                    Text("l").padding(.leading,5)
//                    Text("l").padding(.leading,5)
                    Rectangle().frame(width: 20)
                }
                
                Text("Time Line Content Time Line Content Time Line Content Time Line Content fdfgfuysdgfuydsgfgds fgfyusdfyfdsdfsdfgyusdg fydsufidsfy uyfudsfuydsufysdfsdf dfusdtfoisdtftdsoftsdftsydtfsdtfodstfdstf fgdsygfdsgfuygu").font(.caption)
            }
            
            //footer
            HStack {
                Circle()
                    .fill(Color.orange)
                    .frame(width: 15, height: 15)
                    .overlay(Circle().inset(by: 2).fill(Color.white))
                
                Text("Footer").font(.subheadline)
            }.padding(0)
Run Code Online (Sandbox Code Playgroud)

谢谢。

时间线内容视图

sta*_*Man 5

根据我对你的问题的理解是:

  1. 您有一个HStack,其中最左边的视图是 a Rectangle,最右边的视图是 a Text
  2. 您希望Rectangle与 的高度相同Text

问题是, 的高度HStack基于最高的子视图,而该子视图恰好是 ,RectangleRectangle视图没有任何固有大小Text,并且将占据父级提供的所有空间,或者如果您手动应用框架。
您将宽度设置为 20,但保留高度,因此它会占用它可以获得的整个高度。

这表明我们需要将 的高度设置Rectangle为与动态相同Text,但问题是我们事先不知道高度。

为了解决这个问题:

  1. 首先我们需要知道动态的高度Text
  2. 高度位于子视图中,因此我们需要它来通知父视图其高度值。
  3. 当父视图Rectangle知道高度时Text应该 更新
    • @State现在一个简单的变量就足够了

解决方案:

struct ContentLengthPreference: PreferenceKey {
   static var defaultValue: CGFloat { 0 }
   
   static func reduce(value: inout CGFloat, nextValue: () -> CGFloat) {
      value = nextValue()
   }
}

struct ContentView: View {
   @State var textHeight: CGFloat = 0 // <-- this
   
   var body: some View {
      HStack {
        Rectangle()
           .frame(width: 20, height: textHeight) // <-- this
        
        Text(String(repeating: "lorem ipsum ", count: 25))
           .overlay(
              GeometryReader { proxy in
                Color
                   .clear
                   .preference(key: ContentLengthPreference.self,
                               value: proxy.size.height) // <-- this
              }
           )
      }
      .onPreferenceChange(ContentLengthPreference.self) { value in // <-- this
        DispatchQueue.main.async {
           self.textHeight = value
        }
      }
   }
}
Run Code Online (Sandbox Code Playgroud)
  1. 创建ContentLengthPreference作为我们的PreferenceKey实现
  2. Text; 适用overlay含有GeometryReader
  3. overlay将具有相同的高度Text
  4. GeometryReaderColor.clear只是一个填充不可见视图
  5. anchorPreference修饰符允许我们访问和存储高度
  6. onPreferenceChange父视图上的修饰符HStack可以捕获子视图传递的值
  7. 父级将高度保存到状态属性中textHeight
  8. textHeight可以应用Rectangle并在该值更新时更新视图

学分:https://www.wooji-juice.com/blog/stupid-swiftui-tricks-equal-sizes.html


输出(包括页眉+页脚视图):

输出


编辑:

如果你有多个这样的东西,List那么你不需要做任何事情。每行的大小都会自动调整到高度Text
免费!!!

struct ContentView: View {
   var body: some View {
      List(0..<20) { _ in
        ArticleView()
      }
   }
}

struct ArticleView: View {
   var body: some View {
      VStack(alignment: .leading) {
        HStack {
           Circle()
              .fill(Color.blue)
              .frame(width: 15, height: 15)
              .overlay(Circle().inset(by: 2).fill(Color.white))
           
           Text("Headline").font(.headline)
        }
        
        HStack {
           Rectangle().frame(width: 20)
           
           Text(String(repeating: "lorem ipsum ", count: (5...50).randomElement()!))
        }
        
        HStack {
           Circle()
              .fill(Color.orange)
              .frame(width: 15, height: 15)
              .overlay(Circle().inset(by: 2).fill(Color.white))
           
           Text("Footer").font(.subheadline)
        }
      }
   }
}
Run Code Online (Sandbox Code Playgroud)