SwiftUI - 根据文本视图的高度更改卡片的布局

时间:2021-06-03 13:34:44

标签: swift swiftui uitextview geometryreader

基于文本视图的高度,卡片应该显示完整的文本(如果输入文本很短)或显示部分文本和“继续阅读”按钮,该按钮导航到详细视图。

不幸的是,在呈现文本视图后,GeometryReader 不会更新它的高度(或者它会更新,但不会再次呈现卡片视图)。 OnAppear 的 geo.size.height 是 10,因此永远不会执行“继续阅读”代码。

代码:

struct CardView: View {
    
    var title: String = "Title"
    var text: String = "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum."
    
    var body: some View {
        ScrollView { // will be embedded in one on its parentView
        GeometryReader { geo in
            VStack {
                Text(title)
                    .font(.title2)
                Divider()
                    .padding(.top, -4)
                if geo.size.height >= 420 {
                    VStack {
                        Text(text)
                            .frame(height: 340)
                        Divider()
                            .padding(.top, -4)
                        Button(action: {
                            //button for  testing, NavigationLink later
                        }, label: {
                            HStack {
                                Text("Continue reading")
                                Spacer()
                                Image(systemName: "chevron.right")
                            }
                            .padding(.top, -16)
                            .frame(height: 44)
                            .contentShape(Rectangle())
                        })
                        .buttonStyle(PlainButtonStyle())
                    }
                } else {
                    Text(text)
                        .padding(.bottom, 8)
                        .fixedSize(horizontal: false, vertical: true)
                }
            }
            .cornerRadius(10)
            .padding(.horizontal)
            .padding(.top)
            .overlay( RoundedRectangle(cornerRadius: 10)
                        .stroke(Color.gray, lineWidth: 1))
            .padding()
            .onAppear{
                print(geo.size.height)
            }
        }
        }
    }
}

struct CardView_Previews: PreviewProvider {
    static var previews: some View {
        CardView()
    }
}

1 个答案:

答案 0 :(得分:0)

将 GeometryGetter 添加到 Card-view 的 .background{} 就成功了。它在视图呈现后更新 @State 变量,然后可以在 if 语句中使用它来呈现正确的布局。
相当丑陋,但确实有效...

代码:

import SwiftUI

struct NewsCardView: View {
    
    var title: String = "Lorem Ipsum is simply dummy text of the printing and typesetting industry"
    var text: String = "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book."
    
    @State private var rect: CGRect = CGRect()
    
    var body: some View {
        VStack {
            Text(title)
                .font(.title2)
                .fixedSize(horizontal: false, vertical: true)
            Divider()
                .padding(.top, -4)
            if rect.size.height >= 400 {
                VStack {
                    Text(text)
                        .frame(maxHeight: 320)
                    Divider()
                        .padding(.top, -4)
                    NavigationLink(destination:
                        TestView()
                    , label: {
                        HStack {
                            Text("Continue reading")
                            Spacer()
                            Image(systemName: "chevron.right")
                        }
                        .padding(.top, -16)
                        .frame(height: 44)
                        .contentShape(Rectangle())
                    })
                }
            } else {
                Text(text)
                    .padding(.bottom, 8)
                    .fixedSize(horizontal: false, vertical: true)
            }
        }
        .cornerRadius(10)
        .padding(.horizontal)
        .padding(.top)
        .overlay( RoundedRectangle(cornerRadius: 10)
                    .stroke(Color.gray, lineWidth: 1))
        .padding()
        .background(GeometryGetter(rect: $rect))
    }
}

struct NewsCardView_Previews: PreviewProvider {
    static var previews: some View {
        NewsCardView()
    }
}


struct GeometryGetter: View {
    @Binding var rect: CGRect
    
    var body: some View {
        return GeometryReader { geometry in
            self.makeView(geometry: geometry)
        }
    }
    
    func makeView(geometry: GeometryProxy) -> some View {
        DispatchQueue.main.async {
            self.rect = geometry.frame(in: .global)
        }        
        return Rectangle().fill(Color.clear)
    }
}
``
相关问题