根据SwiftUI中位于该视图内的GeometryReader设置视图框架

时间:2019-11-28 07:11:38

标签: ios swift swiftui

作为学习新技术的一部分,我试图在SwiftUI中实现我正在开发的应用程序的屏幕之一。我的布局很粗糙:

enter image description here

此元素应伸展以适应容器的大小(不同宽度的设备),并将在ScrollView中使用。

这是经过一番摸索之后我想到的初步解决方案:

enter image description here

这对于第一次尝试来说已经足够好了,但是我想通过将所有相关部分移动到单独的View中来重构View。除此之外,我希望新视图能够自动考虑到填充和以后可能添加的其他尺寸修改。

所以,这是一个幼稚的重写:

enter image description here

您可以很容易地发现,ScrollView中的GeometryReader假定了父级提供的大小,有效地隐藏了大多数View。

有几种针对这种情况的“肮脏”解决方案:为View设置固定的框架高度,设置近似于正确大小的纵横比(考虑到存在具有固定高度的Text视图,这有点棘手),保留GeometryReader作为主视图的最外层元素,并将宽度作为初始化参数传递给子视图。

我正在为这种特定的布局寻找一种“干净”的解决方案,也许是为了更深入地了解Views SwiftUI如何调节其尺寸–在WWDC视频中,据说父级View提出了尺寸,然后是子级视图返回它自己的大小;是否有办法以某种方式干扰该过程,或者全部通过私有API完成?

谢谢!

–Baglan

p.s。我以为UI预览之外的代码屏幕截图将是最具说明性的,但是请告诉我是否也应该提供代码段!

2 个答案:

答案 0 :(得分:2)

我相信我的答案应该是评论,但是由于篇幅太长,我将其发布为答案。我回答similar question是否可以带来更多的启发。

使用 string baseUrl = System.Web.Hosting.HostingEnvironment.ApplicationPhysicalPath+ "ExcelReports\\ReportLogo.png"; string data_1 = string.Empty; HttpContext.Current.Response.Clear(); HttpContext.Current.Response.ClearContent(); HttpContext.Current.Response.ClearHeaders(); HttpContext.Current.Response.Buffer = true; HttpContext.Current.Response.ContentType = "application/vnd.ms-excel"; // HttpContext.Current.Response.Write(@"<!DOCTYPE HTML PUBLIC ""-//W3C//DTD HTML 4.0 Transitional//EN"">"); HttpContext.Current.Response.AddHeader("Content-Disposition", "attachment;filename=" + reportname + ".xls"); HttpContext.Current.Response.Charset = "utf-8"; data_1 = "<font style='font-size:10.0pt; font-family:Calibri;'><BR><BR><BR><Table><tr><td><img src="+baseUrl+" alt='Red dot' /></td></tr></Table><BR><BR><BR><BR><Table><tr><td>Created By : " + createdby + "</td><td></td><td></td><td></td><td>Created DateTime : " + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "</td></Table><BR><Table border='1' bgColor='#ffffff' " + "borderColor='#000000' cellSpacing='0' cellPadding='0' " + "style='font-size:10.0pt; font-family:Calibri; background:white;'> <TR>"; int columnscount = table.Columns.Count; string data_2 = string.Empty; for (int j = 0; j < columnscount; j++) { data_2 += "<Td>"; data_2 += "<B>"; data_2 += table.Columns[j].ToString(); data_2 += "<B>"; data_2 += "</Td>"; } 的哪个View组件很重要。

  • 如果您位于跨过屏幕尺寸的典型GeometryReader内,则会得到屏幕本身的Viewwidth

  • 如果您处于height环境中,则会得到

    • ScrollView的容器,以进行height对齐
    • .horizontal的容器,以进行width对齐

通常,.vertical未明确指定对齐方式默认为ScrollView


我想,设计决定是正确的。因为如果您从.vertical中调用UIScrollView,则在滚动视图中有一个 Content View 。在添加一些内容之前,您不会事先知道内容视图的大小。在UIKit中,SwiftUI内部的GeometryReader模仿了ScrollView Content View 的数学原理。这就是原因,您没有从几何读取器获得实际尺寸。

答案 1 :(得分:0)

此代码可以正常工作:

struct GeometryReaderExperiment: View {
    var body: some View {

        GeometryReader { geometry in

            ScrollView {

                Text("First")

                DesignedFancy(parentGeometry: geometry, rectangleColor: .red)

                Text("Second")

                DesignedFancy(parentGeometry: geometry, rectangleColor: .green)

                Text("Third")

                DesignedFancy(parentGeometry: geometry, rectangleColor: .blue)

            }

        }

    }
}

struct DesignedFancy: View {

    var parentGeometry: GeometryProxy
    var rectangleColor: Color

    var body: some View {

        HStack(alignment: .bottom) {
            VStack {
                Rectangle()
                    .aspectRatio(1, contentMode: .fit)
                    .foregroundColor(rectangleColor)

                Text("One")
            }
            .frame(width: parentGeometry.size.width * 2/3)

            VStack {
                Rectangle()
                    .aspectRatio(contentMode: .fit)
                    .foregroundColor(rectangleColor)
                Text("Two")
            }

        }

    }

}

我认为问题在于DesignedFancy不知道它有多少空间。因此,您必须通过变量提供此信息。结果是:

enter image description here