首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >使用SwiftUI调整DragGesture视图的框架将使其在所有维度上调整大小。

使用SwiftUI调整DragGesture视图的框架将使其在所有维度上调整大小。
EN

Stack Overflow用户
提问于 2022-04-16 01:37:35
回答 1查看 864关注 0票数 0

我试图在SwiftUI中实现一个简单的视图,它可以通过放置在左下角的拖动手柄来调整大小。可调整大小视图的尺寸是通过控制宽度和高度的两个@State变量来设置的。这些变量在拖动句柄捕获的DragGesture的onChanged处理程序中发生变异。

这有点管用,但不是我所期望的那样。当我对拖动手柄执行拖动手势时,视图在所有维度上都会被调整大小。我希望调整大小的工作方式与桌面窗口一样;拖动不应该调整视图的所有方向的大小。

下面是来自iOS模拟器的记录,显示错误的行为:

我知道SwiftUI视图的中心被认为是它的起源,这可能就是导致这种行为的原因。我不知道该怎么解决这个问题。

这是我的密码:

代码语言:javascript
代码运行次数:0
运行
复制
import SwiftUI

struct ContentView: View {
    // Initialise to a size proportional to the screen dimensions.
    @State private var width = UIScreen.main.bounds.size.width / 3.5
    @State private var height = UIScreen.main.bounds.size.height / 1.5
    
    var body: some View {
        // This is the view that's going to be resized.
        ZStack(alignment: .bottomTrailing) {
            Text("Hello, world!")
                .frame(width: width, height: height)
            // This is the "drag handle" positioned on the lower-left corner of this stack.
            Text("")
                .frame(width: 30, height: 30)
                .background(.red)
                .gesture(
                    DragGesture()
                        .onChanged { value in
                            // Enforce minimum dimensions.
                            width = max(100, width + value.translation.width)
                            height = max(100, height + value.translation.height)
                        }
                )
        }
        .frame(width: width, height: height, alignment: .center)
        .border(.red, width: 5)
        .background(.yellow)
        .padding()
    }
}

编辑:对于上面的最小示例,我删除的内容太自由了。下面的代码片段在position上添加了一个ZStack约束,该约束用于另一个手势(未显示),这样视图就可以被拖动。

我猜这是有问题的,因为position指定了从ZStack中心到父VStack的相对坐标,并且当ZStack被调整大小时,它将被“移动”以保持位置约束。

代码语言:javascript
代码运行次数:0
运行
复制
import SwiftUI

struct ContentView: View {
    // Initialise to a size proportional to the screen dimensions.
    @State private var width = UIScreen.main.bounds.size.width / 3.5
    @State private var height = UIScreen.main.bounds.size.height / 1.5
    
    var body: some View {
        VStack {
            // This is the view that's going to be resized.
            ZStack(alignment: .bottomTrailing) {
                Text("Hello, world!")
                    .frame(width: width, height: height)
                // This is the "drag handle" positioned on the lower-left corner of this stack.
                Text("")
                    .frame(width: 30, height: 30)
                    .background(.red)
                    .gesture(
                        DragGesture()
                            .onChanged { value in
                                // Enforce minimum dimensions.
                                width = max(100, width + value.translation.width)
                                height = max(100, height + value.translation.height)
                            }
                    )
            }
            .frame(width: width, height: height)
            .border(.red, width: 5)
            .background(.yellow)
            .padding()
            // This position constraint causes the ZStack to grow/shrink in all dimensions
            // when resized.
            .position(x: 400, y: 400)
        }
        .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topLeading)
    }
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-04-16 09:16:56

你说得对,这个问题是由你的观点中心对齐引起的。

要解决这个问题,可以使用不同的对齐方式将视图封装在VStack中,例如,如果您希望视图对齐到左上角,则使用.topLeading

您还必须确保此VStack占用视图的可用空间。否则,它将缩小到可调整大小框的大小,导致视图保持中心对齐。您可以通过.frame(maxWidth: .infinity, maxHeight: .infinity)实现这一点。

TL;DR

将您的可调整大小框放在带有VStack修饰符的.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topLeading)中。

代码语言:javascript
代码运行次数:0
运行
复制
VStack { // <-- Wrapping VStack with alignment modifier
    // This is the view that's going to be resized.
    ZStack(alignment: .bottomTrailing) {
        Text("Hello, world!")
            .frame(width: width, height: height)
        // This is the "drag handle" positioned on the lower-left corner of this stack.
        Text("")
            .frame(width: 30, height: 30)
            .background(.red)
            .gesture(
                DragGesture()
                    .onChanged { value in
                        // Enforce minimum dimensions.
                        width = max(100, width + value.translation.width)
                        height = max(100, height + value.translation.height)
                    }
            )
    }
    .frame(width: width, height: height, alignment: .topLeading)
    .border(.red, width: 5)
    .background(.yellow)
    .padding()
}
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .topLeading)

编辑

在ZStack上添加一个附加的ZStack修饰符,尝试将xy值减去widthheight的一半,相对于ZStack的左上角位置:

代码语言:javascript
代码运行次数:0
运行
复制
.position(x: 400 + width / 2, y: 400 + height / 2)
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71890404

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档