几何学和.Frame的对齐

发布于 2025-01-29 01:42:15 字数 1099 浏览 4 评论 0原文

我使用的是geometryReader()和.frame()来显示它们的可比性并播放其宽度。 但是,当宽度小于最小值时,包裹在geometryReader()中的对象没有中心对齐。 请参阅随附的GIF进行演示。

你能帮我对齐吗?

理想:

当前:

struct ExampleView: View {
@State private var width: CGFloat = 50

var body: some View {
    VStack {
        SubView()
            .frame(width: self.width, height: 120)
            .border(Color.blue, width: 2)
        
        Text("Offered Width is \(Int(width))")
        Slider(value: $width, in: 0...200, step: 5)
      }
   }
}

struct SubView: View {
    var body: some View {
        GeometryReader { geometry in
            Rectangle()
                .fill(Color.yellow.opacity(0.6))
                .frame(width: max(geometry.size.width, 120), height: max(geometry.size.height, 120))
        }
    }
}

I'm using GeometryReader() and .frame() to show their comparability and playing with their width.
However the object wrapped in GeometryReader() doesn't have center alignment when width is less than minimum.
Please refer to attached gifs for demo.

Could you please help me with alignment?

Ideal:

Ideal

Current:
Current

struct ExampleView: View {
@State private var width: CGFloat = 50

var body: some View {
    VStack {
        SubView()
            .frame(width: self.width, height: 120)
            .border(Color.blue, width: 2)
        
        Text("Offered Width is \(Int(width))")
        Slider(value: $width, in: 0...200, step: 5)
      }
   }
}

struct SubView: View {
    var body: some View {
        GeometryReader { geometry in
            Rectangle()
                .fill(Color.yellow.opacity(0.6))
                .frame(width: max(geometry.size.width, 120), height: max(geometry.size.height, 120))
        }
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

凉城 2025-02-05 01:42:15

那是因为几何读程序不关心孩子。

您必须通过添加.position修改器或.offset来手动定位矩形

.position将相对于父中心的矩形框架的原点。

.offset不会更改框架,而是更改渲染(像cgaffineTransform一样工作,并带有翻译)。

您的矩形的以下修饰符将以视觉上产生相同的结果(尽管在引擎盖下不同):

Rectangle()
    .fill(Color.yellow.opacity(0.6))
    .frame(width: max(geometry.size.width, 120), height: max(geometry.size.height, 120))
    .position(x: geometry.size.width / 2, y: geometry.size.height / 2)

let rectWidth = max(geometry.size.width, 120)
Rectangle()
    .fill(Color.yellow.opacity(0.6))
    .frame(width: rectWidth, height: max(geometry.size.height, 120))
    .offset(x: ((geometry.size.width - rectWidth) / 2), y: 0)

注意您的矩形框架超过了其父级的界限。我建议避免这种情况,因为它将在屏幕上造成各种困难。

您可以以相反的方式构建它(除非您的实际目标是仅了解geometryReader有效):

struct ExampleView: View {
    @State private var width: CGFloat = 50

    var body: some View {
        VStack {
            let minWidth: CGFloat = 120
            let subViewWidth: CGFloat = max(minWidth, width)
            SubView(desiredWidth: width)
                .frame(width: subViewWidth, height: 120)
                .background(.yellow.opacity(0.6))

            Text("Offered Width is \(Int(width))")
            Slider(value: $width, in: 0...200, step: 5)
        }
    }
}

struct SubView: View {
    let desiredWidth: CGFloat
    var body: some View {
        Rectangle()
            .fill(.clear)
            .border(Color.blue, width: 2)
            .frame(width: desiredWidth, height: nil)
    }
}

在此示例中而内部矩形只需在滑块上设置任何宽度。它还不再需要deegomeReader。它的外观和行为相同,但没有任何视图超过其父母的界限。

That's because GeometryReader doesn't center its children.

You have to manually position the Rectangle by adding either a .position modifier or a .offset.

.position will move the origin of the rectangle's frame relative to the parent's center.

.offset will not change the frame, but rather change the rendering (working like a CGAffineTransform with translation).

The following modifiers to your Rectangle will yield the same results visually (though different under the hood):

Rectangle()
    .fill(Color.yellow.opacity(0.6))
    .frame(width: max(geometry.size.width, 120), height: max(geometry.size.height, 120))
    .position(x: geometry.size.width / 2, y: geometry.size.height / 2)

or

let rectWidth = max(geometry.size.width, 120)
Rectangle()
    .fill(Color.yellow.opacity(0.6))
    .frame(width: rectWidth, height: max(geometry.size.height, 120))
    .offset(x: ((geometry.size.width - rectWidth) / 2), y: 0)

Note that your rectangle's frame exceeds the bounds of its parent. I'd suggest to avoid that because it will cause all sorts of difficulties laying out other UI elements on the screen.

You could build it the other way around (unless your practical goal is to just understand how GeometryReader works):

struct ExampleView: View {
    @State private var width: CGFloat = 50

    var body: some View {
        VStack {
            let minWidth: CGFloat = 120
            let subViewWidth: CGFloat = max(minWidth, width)
            SubView(desiredWidth: width)
                .frame(width: subViewWidth, height: 120)
                .background(.yellow.opacity(0.6))

            Text("Offered Width is \(Int(width))")
            Slider(value: $width, in: 0...200, step: 5)
        }
    }
}

struct SubView: View {
    let desiredWidth: CGFloat
    var body: some View {
        Rectangle()
            .fill(.clear)
            .border(Color.blue, width: 2)
            .frame(width: desiredWidth, height: nil)
    }
}

In this example the SubView has a yellow fill and a minimal frame width while the inner rectangle just takes whatever width is set on the slider. It also doesn't need a GeometryReader anymore. It looks and behaves the same but none of the views exceeds its parent's bounds anymore.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文