.leftbar.open
如何在夹紧另一维时调整其理想尺寸?
例如,View
表现出这种行为。如果通过Text
进行了限制,并且在一个维度上的空间太小,则另一维度的理想尺寸会相应地增大(如果可能)。
使用 .fixedSize
使用 .fixedSize(horizontal: false, vertical: false)
使用 .fixedSize(horizontal: false, vertical: true)
在前两种情况下,.fixedSize(horizontal: true, vertical: false)
似乎已经将其理想大小定义为Text
。但是,令我感到困惑的部分是,它似乎在第三种情况下将其修改为.frame(idealWidth: 400, idealHeight: 20)
之类的东西。
我们如何像.frame(idealWidth: 80, idealHeight: 100)
一样,允许我们的Text
更新其理想尺寸,以响应被夹紧的尺寸?
以下是我在上面描述的View
中显示此行为的一些代码:
Text
使用这种字体并重复“ o”内容,VStack(spacing: 100) {
Group {
Text("ooooooooooooooooooooooooooooooooooo")
.fixedSize(horizontal: false, vertical: false)
Text("ooooooooooooooooooooooooooooooooooo")
.fixedSize(horizontal: true, vertical: false)
Text("ooooooooooooooooooooooooooooooooooo")
.fixedSize(horizontal: false, vertical: true)
}
.background(Color.green)
.frame(width: 75, height: 75)
.background(Color.blue)
}
希望基本具有等于7,000点的正方形空间(情况2的理想尺寸为338x20,情况3的68x108)。
如何在自定义Text
中复制它? View
和minHeight
不是静态的;它们取决于父级是否已确定尺寸。作为孩子,我们怎么能知道我们已经夹紧了哪些尺寸(如果有)?在每个示例中,父级建议的尺寸仍为75x75,那么子级视图可以访问其理想尺寸的基础是什么? minWidth
如何做到这一点?
要使答案更具体,请考虑如何用自定义类的实例替换Text
实例,该实例的行为与Text("oooooo")
类似。即。尝试保持7,000点的面积,且最小高度为20点,宁愿先水平生长。
答案 0 :(得分:2)
由于fixedSize
的工作性质,这是有问题的:
min
和ideal
的{{1}}提供max
,width
和height
值。min <= ideal <= max
值会有所不同。注释的代码不言自明。
ideal
import SwiftUI
extension View {
func frame(size: CGSize) -> some View {
self.frame(width: size.width, height: size.height)
}
}
struct TextLike: View {
// It's like text, how much space we'd like to occupy
var squareArea: CGFloat
// Text() draws at least one line of text, we'll do the same
private let preferredHeight: CGFloat = 20
// Preferred/Max width in case of one line of text
private let preferredWidth: CGFloat
init(squareArea: CGFloat) {
self.squareArea = squareArea
self.preferredWidth = squareArea / preferredHeight
}
var body: some View {
GeometryReader { proxy in
// Let's say that this is the text
Color.green.opacity(0.5)
.frame(size: self.size(withProxy: proxy))
}
.frame(
// Ideally we'd like to draw it as one line of text
idealWidth: preferredWidth,
// Maximum width equals to ideal width (one line of text)
maxWidth: preferredWidth,
// At least one line of text
minHeight: preferredHeight,
// Ideally we'd like to draw it as one line of text
idealHeight: preferredHeight
)
}
private func size(withProxy proxy: GeometryProxy) -> CGSize {
//
// Good enough for the demonstration, but you should get PhD & read:
//
// https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
// https://stackoverflow.com/a/10335601/581190
// https://stackoverflow.com/a/10334868/581190
//
// Also it must be generic enough to cover different devices, ...
//
// proxy.size.width on iPhone SE (2nd) = 350.0
// proxy.size.width on iPhone 11 Pro Max = 350.3333...
//
// Just be aware of this and provide proper logic.
//
let horizontalFix = abs(proxy.size.width.distance(to: preferredWidth)).isLessThanOrEqualTo(1.0)
let verticalFix = abs(proxy.size.height.distance(to: preferredHeight)).isLessThanOrEqualTo(1.0)
switch (horizontalFix, verticalFix) {
case (true, _):
// Horizontal fix -> use preferred (= max) width -> one line of text
// Vertical is irrelevant, because we do prefer horizontal grow
return CGSize(width: preferredWidth, height: preferredHeight)
case (false, false):
// Use the offered size -> fits container, possible truncation
return proxy.size
case (false, true):
// Vertical fix -> use offered width & calculate height
return CGSize(width: proxy.size.width, height: squareArea / proxy.size.width)
}
}
}
struct ContentView: View {
var body: some View {
VStack(spacing: 50) {
Group {
TextLike(squareArea: 7000)
.fixedSize(horizontal: false, vertical: false)
TextLike(squareArea: 7000)
.fixedSize(horizontal: true, vertical: false)
TextLike(squareArea: 7000)
.fixedSize(horizontal: false, vertical: true)
TextLike(squareArea: 7000)
.fixedSize(horizontal: true, vertical: true)
}
.frame(width: 75, height: 75)
.background(Color.blue)
}
}
}
充当包装器,并且其中包含实际视图(另外一层)。TextLike
修饰符。让我们像以前一样在background
级别上修改代码并使用background
修饰符。
TextLike
这是发生了什么
坦白地说,这不是理想且不错的选择,但是我现在可以得到最接近的