Swift UIViewRepresentable及其内容';s固有尺寸

Swift UIViewRepresentable及其内容';s固有尺寸,swift,autolayout,swiftui,Swift,Autolayout,Swiftui,我为UIVisualEffectView创建了一个UIViewRepresentable,以使某些组件充满活力。这是可行的,但它似乎有时会垂直收缩控件,或者只是在运行时随机改变控件的边界。我似乎无法使它可靠地工作。我需要它来处理任何SwiftUI内容,甚至是其他用来代替内容的UIViewRepresentable。将UIVisualEffectView包装在UIView中并使用自动布局似乎有帮助,但其他控件(如包装在uiviewrepresentable中的自定义UILabel会被垂直剪裁) 当

我为
UIVisualEffectView
创建了一个
UIViewRepresentable
,以使某些组件充满活力。这是可行的,但它似乎有时会垂直收缩控件,或者只是在运行时随机改变控件的边界。我似乎无法使它可靠地工作。我需要它来处理任何SwiftUI内容,甚至是其他用来代替内容的
UIViewRepresentable
。将
UIVisualEffectView
包装在
UIView
中并使用自动布局似乎有帮助,但其他控件(如包装在
uiviewrepresentable
中的自定义
UILabel
会被垂直剪裁)

当在设备上运行时,在
VStack
的内部有其他视图,您将看到部分从底部剪裁的“Hello”。在预览中,您将看到“Hello”周围有一个大得多的蓝色矩形(边界),而我希望这是一个拥抱内容的矩形。
VStack
不假定整个视图的完整自然高度

使用
fixedSize()
不起作用,与其他控件一起使用时会产生更奇怪的结果。

为什么这么复杂

试试这个:

struct Blur: UIViewRepresentable {
    #if os(iOS)
    var style: UIBlurEffect.Style = .systemMaterial
    #else
    var style: UIBlurEffect.Style = .light
    #endif

    init(_ style: UIBlurEffect.Style = .dark) {
        self.style = style
    }

    func makeUIView(context: Context) -> UIVisualEffectView {
        return UIVisualEffectView(effect: UIBlurEffect(style: style))
    }
    func updateUIView(_ uiView: UIVisualEffectView, context: Context) {
        uiView.effect = UIBlurEffect(style: style)
    }
}
和使用:

 Text("Great text with prominent")
                    .font(.largeTitle)
                    .padding()
                    .background(Blur(.prominent))
通常,您不应该在UIViewRepresentable->中使用约束,大小将由父视图定义,如本例中的文本或VStack,后者为模糊提供正确的大小。通常情况下,模糊不是孤立的,但典型的是模糊的背景,因为你想在其上放置文本,以便更好地阅读文本。

为什么这么复杂

试试这个:

struct Blur: UIViewRepresentable {
    #if os(iOS)
    var style: UIBlurEffect.Style = .systemMaterial
    #else
    var style: UIBlurEffect.Style = .light
    #endif

    init(_ style: UIBlurEffect.Style = .dark) {
        self.style = style
    }

    func makeUIView(context: Context) -> UIVisualEffectView {
        return UIVisualEffectView(effect: UIBlurEffect(style: style))
    }
    func updateUIView(_ uiView: UIVisualEffectView, context: Context) {
        uiView.effect = UIBlurEffect(style: style)
    }
}
和使用:

 Text("Great text with prominent")
                    .font(.largeTitle)
                    .padding()
                    .background(Blur(.prominent))

通常,您不应该在UIViewRepresentable->中使用约束,大小将由父视图定义,如本例中的文本或VStack,后者为模糊提供正确的大小。通常情况下,模糊不是孤立的,但典型的是模糊的背景,因为您希望在其上放置文本,以便更好地阅读文本。

尝试了各种技术和技巧后,我根本无法让UIKit容器(即
VibrantView
)可靠地容纳其快速UI内容,没有在顶部添加固定大小的
.frame(…)
修改器-这使得它很难与动态大小的
文本一起使用

对我有效的是一点小技巧,可能不适用于所有的通用视图(也可能不适用于几十个视图),但适用于简单的用例,特别是如果您在动态大小的
UITableViewCell
中托管它

想法是使用同一视图的虚拟版本,并在
.overlay(…)
中设置
VibrantView
。这将强制覆盖采用与父SwitUI
视图相同的总体大小。由于要应用的视图修改器是与
VibrantView
包装的视图相同的视图的副本,因此在运行时和Xcode预览中,最终会得到正确的动态大小

比如说:

  SomeView()
    .frame(minWidth: 0, maxWidth: .infinity)
    .overlay(
      VibrantView(vibrancyBlurEffectStyle: .dark) {
        SomeView()
         .frame(minWidth: 0, maxWidth: .infinity)
      }
  )
  Circle()
    .foregroundColor(.clear)
    .frame(width: 33, height: 33)
    .overlay(
      VibrantView(vibrancyBlurEffectStyle: .systemMaterialDark) {
        Image("some image")
          .resizable()
      }
  )
我可以想象将其转换为一个修饰符,以便在一个调用中封装上述内容,但在我的情况下,为了确保它对图像保持性能,我正在做如下操作:

  SomeView()
    .frame(minWidth: 0, maxWidth: .infinity)
    .overlay(
      VibrantView(vibrancyBlurEffectStyle: .dark) {
        SomeView()
         .frame(minWidth: 0, maxWidth: .infinity)
      }
  )
  Circle()
    .foregroundColor(.clear)
    .frame(width: 33, height: 33)
    .overlay(
      VibrantView(vibrancyBlurEffectStyle: .systemMaterialDark) {
        Image("some image")
          .resizable()
      }
  )

创建一个
可以说比实际图像更轻。我创建了一个透明的圆圈,在那里设置了图像的实际大小,然后将
VibrantView
容器放入
overlay
中,在尝试了各种技术和技巧之后-我根本无法让UIKit容器(即
VibrantView
)可靠地容纳其SwiftUI内容,没有在顶部添加固定大小的
.frame(…)
修改器-这使得它很难与动态大小的
文本一起使用

对我有效的是一点小技巧,可能不适用于所有的通用视图(也可能不适用于几十个视图),但适用于简单的用例,特别是如果您在动态大小的
UITableViewCell
中托管它

想法是使用同一视图的虚拟版本,并在
.overlay(…)
中设置
VibrantView
。这将强制覆盖采用与父SwitUI
视图相同的总体大小。由于要应用的视图修改器是与
VibrantView
包装的视图相同的视图的副本,因此在运行时和Xcode预览中,最终会得到正确的动态大小

比如说:

  SomeView()
    .frame(minWidth: 0, maxWidth: .infinity)
    .overlay(
      VibrantView(vibrancyBlurEffectStyle: .dark) {
        SomeView()
         .frame(minWidth: 0, maxWidth: .infinity)
      }
  )
  Circle()
    .foregroundColor(.clear)
    .frame(width: 33, height: 33)
    .overlay(
      VibrantView(vibrancyBlurEffectStyle: .systemMaterialDark) {
        Image("some image")
          .resizable()
      }
  )
我可以想象将其转换为一个修饰符,以便在一个调用中封装上述内容,但在我的情况下,为了确保它对图像保持性能,我正在做如下操作:

  SomeView()
    .frame(minWidth: 0, maxWidth: .infinity)
    .overlay(
      VibrantView(vibrancyBlurEffectStyle: .dark) {
        SomeView()
         .frame(minWidth: 0, maxWidth: .infinity)
      }
  )
  Circle()
    .foregroundColor(.clear)
    .frame(width: 33, height: 33)
    .overlay(
      VibrantView(vibrancyBlurEffectStyle: .systemMaterialDark) {
        Image("some image")
          .resizable()
      }
  )

创建一个
可以说比实际图像更轻。我创建一个透明的圆圈,在那里设置图像的实际大小,然后将
VibrantView
容器放入
覆盖层

如果你看我的代码-我没有使用模糊,我使用的是vibrance。对于Vibrance,我需要将内容视图添加到vibrant
UIVisualEffectView
contentView
。我不是把它用作背景,我是把它用作容器,所以你的技术不起作用。你说得对……这个怎么样。刚刚尝试过-同样的问题,而且我现在看到一个编译错误,关于@objc layoutSubviews不受泛型类支持_(ツ)_/“如果你看我的代码-我没有使用模糊,我使用的是Vibrance。对于Vibrance,我需要将内容视图添加到vibrant
UIVisualEffectView
contentView
中。我没有将其用作背景,而是将其用作容器,因此你的技术不起作用。你是对的……这是怎么回事。只是尝试了一下-相同。”此外,我现在看到一个编译错误,它与泛型类不支持的@objc layoutSubviews有关_(ツ)_/为什么否决?答案没有帮助,也不适用于我需要使用
ViewBuilder
fo的情况