首页 > 解决方案 > SwiftUI 获取对象以响应另一个对象的大小

问题描述

我正在设计一个音乐播放器,并从故事板界面转移到 SwiftUI。我希望将时间显示为沿着轨道图稿底部边缘的进度条(那条白线)。在大尺寸的画布上,它们排成一行,因为它们都可以伸展减去两边的 20 填充。但是,对于较小的画布,会发生以下问题。艺术品变小以适应所有其他视图,而进度条(高度为 2 的矩形)保持较大。如何设置该矩形,以便如果我的作品变小,条形也会变小?

这是我的代码:

struct PlayerArtwork: View {
    var body: some View {
        VStack {
            ZStack(alignment: .bottom) {
                        Image("Pumpy Artwork")
                                .resizable()
                            .aspectRatio(contentMode: .fit)
                        ProgressBar()
            }
            .padding([.top, .leading, .trailing], 20.0)
            HStack {
                Text("0:00")
                .foregroundColor(Color.white)
                Spacer()
                Text("3:52")
                .foregroundColor(Color.white)
            }
            .padding([.leading, .bottom, .trailing], 20.0)
        }
    }
}

struct ProgressBar: View {
    var body: some View {
        ZStack {
            Rectangle()
                .fill(Color.gray)
            .frame(height: 2)

            Rectangle()
                .fill(Color.white)
                .frame(height: 2)
        }
    }
}

标签: swiftui

解决方案


这是使用的可能方法alignmentGuide。这个想法是更新一个视图的宽度,在您的情况下ProgressBar,是从可用于对齐指南的尺寸中获取的宽度。

注意:也许你应该为时间标签做同样的事情,但这取决于你

struct PlayerArtwork: View {
    @State private var boundWidth: CGFloat = 10.0 // any initial value
    var body: some View {
        VStack {
            ZStack(alignment: .bottom) {
                Image("Pumpy Artwork")
                    .resizable()
                    .aspectRatio(contentMode: .fit)
                    .alignmentGuide(.bottom, computeValue: { d in
                        DispatchQueue.main.async {
                            self.boundWidth = d.width // avoid change state during update
                        }
                        return d[.bottom]
                    })
                ProgressBar()
                    .frame(width: self.boundWidth)
            }
            .padding([.top, .leading, .trailing], 20.0)
            HStack {
                Text("0:00")
                    .foregroundColor(Color.white)
                Spacer()
                Text("3:52")
                    .foregroundColor(Color.white)
            }
            .padding([.leading, .bottom, .trailing], 20.0)
        }
    }
}

推荐阅读