在SwiftUI中使用AspectRatio的方形文本

时间:2019-06-26 12:53:41

标签: swiftui

我正在尝试使用Swift UI实现以下布局…

enter image description here

struct ContentView : View {
    var body: some View {
        List(1...5) { index  in

            HStack {
                HStack {
                    Text("Item number \(index)")
                    Spacer()
                    }.padding([.leading, .top, .bottom])
                    .background(Color.blue)

                Text("i")
                    .font(.title)
                    .italic()
                    .padding()
                    .aspectRatio(1, contentMode: .fill)
                    .background(Color.pink)

                }.background(Color.yellow)
        }
    }
}

我希望Text("i")是方形的,但是设置.aspectRatio(1, contentMode: .fill)似乎没有任何作用……

enter image description here

我可以设置文本的框架宽度和高度,使其为正方形,但是似乎设置宽高比应该可以更动态地实现我想要的效果。

我想念什么?

4 个答案:

答案 0 :(得分:3)

我认为这就是您要寻找的东西

 <h1 id="h1_title"style="text-align:center;background:linear-gradient(to right,rgb(166, 204, 255),rgb(15, 242, 216));margin-left:2%;margin-right:2%;box-shadow:1px 5px 5px 1px rgb(90,150,100,210);padding:30px;font-weight:bold;">[ Here I want to get that text from page1.html ]</h2>

要说的答案是,我不建议给SwiftUI太大的自由来决定尺寸。目前,SwiftUI最大的问题之一就是它决定如何使视图相互适应的方式。如果某些事情在SwiftUI方面不尽如人意,则可能导致对UIKit的sizeToFit方法的调用过多,这可能会使应用变慢,甚至崩溃。

但是,如果您在几种不同的情况下尝试了该解决方案并且奏效了,则可以假设在您的情况下,让SwiftUI可以选择确定大小没有问题。

答案 1 :(得分:2)

问题是由于左侧/右侧使用了不同的字体,所以填充会产生不同的结果区域。

这是可能的解决方案。这个想法是根据左侧文本的默认视图大小给出右侧矩形(这也可以自动跟踪动态字体大小)。

通过Xcode 12 / iOS 14测试

demo

struct ContentView: View {
    @State private var height = CGFloat.zero
    var body: some View {
        List(1...5, id: \.self) { index  in

            HStack(spacing: 8) {
                HStack {
                    Text("Item number \(index)")
                    Spacer()
                    }
                    .padding([.leading, .top, .bottom])
                    .background(GeometryReader {
                        Color.blue.preference(key: ViewHeightKey.self, value: $0.frame(in: .local).size.height)
                    })


                Text("i")
                    .italic()
                    .font(.title)
                    .frame(width: height, height: height)
                    .background(Color.pink)

                }
                .padding(8)
                .background(Color.yellow)
                .onPreferenceChange(ViewHeightKey.self) {
                    self.height = $0
                }
        }
    }
}

struct ViewHeightKey: PreferenceKey {
    typealias Value = CGFloat
    static var defaultValue = CGFloat.zero
    static func reduce(value: inout Value, nextValue: () -> Value) {
        value += nextValue()
    }
}

答案 2 :(得分:1)

我设法在SwiftUI的第一个屏幕截图中重新创建了视图。我不确定要填充多少,因此我为此值定义了一个private不可变变量

蓝色视图是具有文本内容并且可以更改大小的视图,因此,使用GeometryReader可以获取蓝色视图的大小,然后使用该大小中的高度值来设置粉色视图的宽度和高度。这意味着无论蓝色视图的高度如何,粉红色视图都将遵循相同的长宽比

下面的SizeGetter视图用于使用GeometryReader获取任何视图大小,然后将该值绑定回到@State中的ContentView变量。由于正在使用@State@Binding属性包装器,因此,每当blueViewSize更新时,SwiftUI都会自动刷新视图。

SizeGetter视图可用于任何视图,并使用.background()修饰符实现,如下所示。

struct SizeGetter: View {
    @Binding var size: CGSize;

    var body: some View {

        // Get the size of the view using a GeometryReader
        GeometryReader { geometry in
            Group { () -> ShapeView<Rectangle, Color> in

                // Update the size on the main thread
                DispatchQueue.main.async {
                    self.size = geometry.size;
                }

                return Rectangle()
                    .fill(Color.clear);
            }
        }
    }
}

struct ContentView: View {

    private let padding: Length = 10;
    @State private var blueViewSize: CGSize = .zero;

    var body: some View {

        List(1...5) { index  in

            // The yellow view
            HStack(spacing: self.padding) {

                // The blue view
                HStack(spacing: 0) {
                    VStack(spacing: 0) {
                        Text("Item number \(index)")
                            .padding(self.padding);
                    }
                    Spacer();
                }
                .background(SizeGetter(size: self.$blueViewSize))
                .background(Color.blue);

                // The pink view
                VStack(spacing: 0) {
                    Text("i")
                        .font(.title)
                        .italic();
                }
                .frame(
                    width: self.blueViewSize.height,
                    height: self.blueViewSize.height
                )
                .background(Color.pink);
            }
            .padding(self.padding)
            .background(Color.yellow);
        }
    }
}

我认为最好设置VStackHStack的背景色,而不是直接设置Text视图,因为这样您便可以向堆栈中添加更多文本和其他视图不必为每个背景色设置背景颜色

答案 3 :(得分:1)

我正在搜索非常类似的主题“ SwiftUI中的方形文本”,遇到了您的问题,我想我已经找到了一种非常简单的方法来实现所需的布局,可以使用GeometryProxy从提供的几何体中设置正方形视图的宽度和高度.size。

签出下面的代码,这是一个可以在列表视图上下文中使用的TableCellView示例:

import SwiftUI

struct TableCellView: View {
    var index: Int
    
    var body: some View {
        HStack {
            HStack {
                Text("Item number \(index)")
                    .padding([.top, .leading, .bottom])
                Spacer()
            }
            .background(Color(.systemBlue))
            .layoutPriority(1)
            
            GeometryReader { geometry in
                self.squareView(geometry: geometry)
            }
            .padding(.trailing)
        }
        .background(Color(.systemYellow))
        .padding(.trailing)
    }
    
    func squareView(geometry: GeometryProxy) -> some View {
        Text("i")
            .frame(width: geometry.size.height, height: geometry.size.height)
            .background(Color(.systemPink))
    }
}

enter image description here