swift 如何获取视图在屏幕上占据的宽度

vlju58qv  于 2023-10-15  发布在  Swift
关注(0)|答案(1)|浏览(153)

我试图得到的宽度一个视图占据一半的屏幕,但我很难想到一种方法来做到这一点
我试着用几何阅读器

HStack{
  Spacer()

  Text(displayedText)
       .background(
           GeometryReader { geometry in
                  Color.clear
                  .preference(key: TextWidthKey.self, value: geometry.size.width)
           }
        )
        .onPreferenceChange(TextWidthKey.self) { width in
             textWidthOnRight = width / 2
        }
  Spacer()

}

struct TextWidthKey: PreferenceKey {
    static var defaultValue: CGFloat = 0
    static func reduce(value: inout CGFloat, nextValue: () -> CGFloat) {
        value = nextValue()
    }
}

但问题是,文本并没有在屏幕的两侧均匀划分,因此计算不准确

zvms9eto

zvms9eto1#

我不太确定,为什么你的问题中的代码不应该提供正确的结果,如果文本是在两个Spacer之间的HStack。我希望它是完全居中的,所以一半的文本宽度将在右手边。
但是,如果两个Spacer中的一个不在那里,那就另当别论了,因为这样文本就会被推到左边或右边。在这种情况下,要找到右侧宽度,您需要参考全视图宽度以及文本框架在全局坐标空间中的位置。
就像这样:

var body: some View {
    GeometryReader { outer in
        HStack{

//            Spacer()
            Text(displayedText)
                .background(
                    GeometryReader { geometry in
                        let fullWidth = outer.size.width
                        let textWidth = geometry.size.width
                        let textFrame = geometry.frame(in: .global)
                        Color.clear
                            .preference(
                                key: TextWidthKey.self,
                                value: textFrame.minX < fullWidth / 2
                                    ? max(0, textWidth + textFrame.minX - (fullWidth / 2))
                                    : textWidth
                            )
                    }
               )
                .onPreferenceChange(TextWidthKey.self) { width in
//                    print("textWidthOnRight = \(width)")
                    textWidthOnRight = width
                }
            Spacer()
        }
        .padding()
    }
}

你会注意到有两种特殊情况正在处理:

  • 如果文本没有到达图幅的中心,可能是因为文本较短并被推到了左侧,则将提供宽度0(而不是负值)。
  • 另一方面,如果文本被推到右边,并在屏幕中心之后开始,则提供完整的文本宽度。视图中心和文本开头之间的前导空格将被忽略。

相关问题