ios - SwiftUI 视图大小(父/子关系)
问题描述
我正在通过一些示例来熟悉 SwiftUI,但我遇到了大小问题。
我已经习惯了 UIKit 处理调整视图大小的方式,使用 AutoLayout 你基本上可以为其子级设置父级大小。SwiftUI 似乎并非如此。
我读过的所有内容都显示了如何在孩子身上使用 GeometryReader 来获取其父母的大小,这表明孩子可以选择自己的大小,但我还没有看到如何从父母那里获得孩子的大小.
假设我有以下代码:
struct ContentView: View {
var body: some View {
Text("This is Text").ripple(rippleColor: .lightGray, rippleOpacity: 0.5)
}
}
ripple()
是一个扩展函数,它添加了一个自定义ViewModifier
,将内容覆盖到UIViewRepresentable
视图上,以便在点击时创建材质波纹效果。
struct RippleModifier: ViewModifier {
let rippleColor: UIColor
let rippleOpacity: Float
func body(content: Content) -> some View {
RippleView(
rippleColor: rippleColor,
rippleOpacity: rippleOpacity
)
.overlay(content)
}
}
extension View {
func ripple(rippleColor: UIColor, rippleOpacity: Float) -> some View {
modifier(
RippleModifier(
rippleColor: rippleColor,
rippleOpacity: rippleOpacity
)
)
}
}
我遇到的问题是,当我只有 时Text
,它会将其框架设置为适合其内容(字符串)。当我向它添加.ripple()
修改器时,框架就变成了整个屏幕。
使用 UIKit,我只需添加一些约束来将 UILabel 固定到父级,我会让它决定父级的大小。
有没有办法使用 SwiftUI?
奖金问题:
相关但不相关,我如何让点击进入Text
它覆盖的视图?当点击视图框架内的任何位置时,波纹将激活并正确动画,但直接点击文本本身除外。
编辑:
这是 UIViewRepresentable 视图的部分代码。
struct RippleView: UIViewRepresentable {
var rippleColor: UIColor = .systemGray
var rippleOpacity: Float = 0.5
func makeUIView(context: Context) -> UIRippleView {
UIRippleView()
}
func updateUIView(
_ uiView: UIRippleView,
context: UIViewRepresentableContext<RippleView>
) {
uiView.rippleColor = rippleColor
uiView.rippleOpacity = rippleOpacity
}
}
open class UIRippleView: UIView {
open var rippleColor: UIColor = .systemGray {
didSet {
rippleLayer.fillColor = rippleColor.cgColor
}
}
open var rippleOpacity: Float = 0.5 {
didSet {
rippleLayer.opacity = rippleOpacity
}
}
private lazy var rippleLayer: CAShapeLayer = {
let layer = CAShapeLayer()
layer.opacity = 0.0
self.layer.insertSublayer(layer, at: 0)
return layer
}()
public override init(frame: CGRect) {
super.init(frame: frame)
clipsToBounds = true
}
public required init?(coder: NSCoder) {
super.init(coder: coder)
clipsToBounds = true
}
}
该视图有一个扩展,它覆盖了触摸函数来计算点击发生的位置并执行动画,但这只是修改path
了rippleLayer
.
解决方案
你可以改成overlay
这样background
:
struct RippleModifier: ViewModifier {
let rippleColor: UIColor
let rippleOpacity: Float
func body(content: Content) -> some View {
content.background(
RippleView(
rippleColor: rippleColor,
rippleOpacity: rippleOpacity
))
}
}
因此,从而不是相反的方式RippleView
获取大小约束。content
推荐阅读
- tsql - 添加新列只是为了拥有聚簇表
- android - 使用 Android Studio 的开发人员将如何从 Material Theme Editor 中受益?
- game-maker - 未添加高分
- typescript - 如何使用来自外部 .d.ts 文件的导出类型?
- xslt - 在 XSLT 1.0 中应用多个模板,例如 XSLT 2.0
- apache-spark - 基于 sorted-based shuffle 的数据文件是什么样的?
- r - 打印一些 HEX 颜色以查看它们
- ejb - javax.naming.ConfigurationException:NamingManager.getURLContext 找不到此方案的工厂:java
- node.js - 我如何在 node.js 中使用 mxGraph 实例
- oracle - 存储过程中的查询调优