View 如何将视图传递到结构中,同时获取其高度?
我正在尝试创建一个视图,在iPhone布局的底部放置一个Blur(),尊重安全区域,并且可以轻松重用 大概是这样的:View 如何将视图传递到结构中,同时获取其高度?,view,swiftui,var,View,Swiftui,Var,我正在尝试创建一个视图,在iPhone布局的底部放置一个Blur(),尊重安全区域,并且可以轻松重用 大概是这样的: import SwiftUI struct SafeBottomBlurContainer: View { @Environment(\.colorScheme) var colorScheme var body: some View { GeometryReader { geometry in VStack {
import SwiftUI
struct SafeBottomBlurContainer: View {
@Environment(\.colorScheme) var colorScheme
var body: some View {
GeometryReader { geometry in
VStack {
Spacer()
ZStack {
Blur(style: self.colorScheme == .dark ? .systemThinMaterialDark : .systemThinMaterialLight)
.frame(
width: geometry.size.width,
height: geometry.safeAreaInsets.bottom + 50
)
Holder()
.padding(.bottom, geometry.safeAreaInsets.bottom)
}
}
.edgesIgnoringSafeArea(.bottom)
}
}
}
struct Holder: View {
var body: some View {
Rectangle().opacity(0.5)
.frame(height: 50)
}
}
struct SafeBottomBlurContainer_Previews: PreviewProvider {
static var previews: some View {
SafeBottomBlurContainer()
}
}
顺便说一下,这是~~蓝色~~模糊的扩展名:
import SwiftUI
struct Blur: UIViewRepresentable {
var style: UIBlurEffect.Style = .systemMaterial
func makeUIView(context: Context) -> UIVisualEffectView {
return UIVisualEffectView(effect: UIBlurEffect(style: style))
}
func updateUIView(_ uiView: UIVisualEffectView, context: Context) {
uiView.effect = UIBlurEffect(style: style)
}
}
现在,我想做的是以某种方式传入Holder()
,以便调整模糊的高度(这里是+50)。我觉得我应该以某种方式使用AnyView,但我无法理解它。那可能是我走错了路
下面是我想在ContentView()示例中使用它的方式:
这里有一种可能的方法,它提供了使用类似容器的可能性
struct ContentView: View {
var body: some View {
ZStack {
Color.pink.edgesIgnoringSafeArea(.all)
// holder is not needed, because you can pass any view directly
SafeBottomBlurContainer(containedView: Text("Demo"))
}
}
}
和通用模糊容器
struct SafeBottomBlurContainer<V: View>: View {
@Environment(\.colorScheme) var colorScheme
var containedView: V
var body: some View {
GeometryReader { geometry in
VStack {
Spacer()
ZStack {
Blur(style: self.colorScheme == .dark ? .systemThinMaterialDark : .systemThinMaterialLight)
.frame(
width: geometry.size.width,
height: geometry.safeAreaInsets.bottom + 50
)
containedView
.padding(.bottom, geometry.safeAreaInsets.bottom)
}
}
.edgesIgnoringSafeArea(.bottom)
}
}
}
struct安全容器:视图{
@环境(\.colorScheme)变量colorScheme
var-containedView:V
var body:一些观点{
GeometryReader{中的几何体
VStack{
垫片()
ZStack{
模糊(样式:self.colorScheme==.dark?.systemthinnmaterialdark:.systemthinnmateriallight)
.框架(
宽度:geometry.size.width,
高度:geometry.safeAreaInsets.bottom+50
)
包含视图
.padding(.bottom,geometry.safeAreaInsets.bottom)
}
}
.edgesIgnoringSafeArea(.bottom)
}
}
}
从@Asperi开始,他真正让我走上了正确的道路,我现在有了这个,我还试图了解这个Blur()
视图应该在屏幕的顶部还是底部:
import SwiftUI
struct SafeEdgesBlurContainer<V: View>: View {
@Environment(\.colorScheme) var colorScheme
@State var containedViewSize: CGSize = .zero
var containedView: V
var isPlacedAtTop: Bool
var body: some View {
GeometryReader { geometry in
VStack {
if !isPlacedAtTop {
Spacer()
}
ZStack {
Blur(style: self.colorScheme == .dark ? .systemThinMaterialDark : .systemThinMaterialLight)
.frame(
width: geometry.size.width + geometry.safeAreaInsets.leading + geometry.safeAreaInsets.trailing,
height: (isPlacedAtTop ? geometry.safeAreaInsets.top : geometry.safeAreaInsets.bottom ) + containedViewSize.height
)
.edgesIgnoringSafeArea([.leading])
HStack {
ChildSizeReader(size: $containedViewSize) {
containedView
}
.frame(width: geometry.size.width) // ADDED This line to keep the ContainedView centered in Landscape
.padding(isPlacedAtTop ? .top : .bottom, isPlacedAtTop ? geometry.safeAreaInsets.top : geometry.safeAreaInsets.bottom)
}
}
if isPlacedAtTop {
Spacer()
}
}
.edgesIgnoringSafeArea(isPlacedAtTop ? .top : .bottom)
}
}
}
导入快捷界面
结构SafeEdgesBlurContainer:视图{
@环境(\.colorScheme)变量colorScheme
@状态变量containedViewSize:CGSize=.0
var-containedView:V
变量isPlacedAtTop:Bool
var body:一些观点{
GeometryReader{中的几何体
VStack{
如果!isPlacedAtTop{
垫片()
}
ZStack{
模糊(样式:self.colorScheme==.dark?.systemthinnmaterialdark:.systemthinnmateriallight)
.框架(
宽度:geometry.size.width+geometry.SafeAreaInsetts.leading+geometry.SafeAreaInsetts.Training,
高度:(isPlacedAtTop?geometry.SafeAreaInsetts.top:geometry.SafeAreaInsetts.bottom)+包含的视图大小.height
)
.edgesIgnoringSafeArea([.leading])
HStack{
ChildSizeReader(大小:$containedViewSize){
包含视图
}
.frame(宽度:geometry.size.width)//添加了这一行以使ContainedView在横向视图中居中
.padding(isPlacedAtTop?.top:.底部,isPlacedAtTop?geometry.SafeAreaInsetts.top:geometry.SafeAreaInsetts.bottom)
}
}
如果我放在上面{
垫片()
}
}
.edgesIgnoringSafeArea(isPlacedAtTop?.top:.底部)
}
}
}
事实证明,获取ContainedView()的高度并不难。我从这里找到了这个解决方案:
struct ChildSizeReader:视图{
@绑定变量大小:CGSize
让内容:()->内容
var body:一些观点{
ZStack{
内容()
.背景(
GeometryReader{中的代理
颜色。清晰
.preference(键:SizePreferenceKey.self,值:proxy.size)
}
)
}
.onPreferenceChange(SizePreferenceKey.self){中的首选项
self.size=首选项
}
}
}
结构SizePreferenceKey:PreferenceKey{
typealias值=CGSize
静态变量defaultValue:值=.0
静态函数reduce(值quot:inout值,nextValue:()->值){
_=下一个值()
}
}
我看到的其余问题是ContainedView()没有在横向视图中居中。但我希望,我能很快回来,编辑一个解决方案
编辑:这可能就是解决方案:
.frame(宽度:geometry.size.width)
在HStack上。哇,太好了,谢谢!我在哪里可以了解更多关于该
?它叫什么?那只是泛型,对吗?
import SwiftUI
struct SafeEdgesBlurContainer<V: View>: View {
@Environment(\.colorScheme) var colorScheme
@State var containedViewSize: CGSize = .zero
var containedView: V
var isPlacedAtTop: Bool
var body: some View {
GeometryReader { geometry in
VStack {
if !isPlacedAtTop {
Spacer()
}
ZStack {
Blur(style: self.colorScheme == .dark ? .systemThinMaterialDark : .systemThinMaterialLight)
.frame(
width: geometry.size.width + geometry.safeAreaInsets.leading + geometry.safeAreaInsets.trailing,
height: (isPlacedAtTop ? geometry.safeAreaInsets.top : geometry.safeAreaInsets.bottom ) + containedViewSize.height
)
.edgesIgnoringSafeArea([.leading])
HStack {
ChildSizeReader(size: $containedViewSize) {
containedView
}
.frame(width: geometry.size.width) // ADDED This line to keep the ContainedView centered in Landscape
.padding(isPlacedAtTop ? .top : .bottom, isPlacedAtTop ? geometry.safeAreaInsets.top : geometry.safeAreaInsets.bottom)
}
}
if isPlacedAtTop {
Spacer()
}
}
.edgesIgnoringSafeArea(isPlacedAtTop ? .top : .bottom)
}
}
}
struct ChildSizeReader<Content: View>: View {
@Binding var size: CGSize
let content: () -> Content
var body: some View {
ZStack {
content()
.background(
GeometryReader { proxy in
Color.clear
.preference(key: SizePreferenceKey.self, value: proxy.size)
}
)
}
.onPreferenceChange(SizePreferenceKey.self) { preferences in
self.size = preferences
}
}
}
struct SizePreferenceKey: PreferenceKey {
typealias Value = CGSize
static var defaultValue: Value = .zero
static func reduce(value _: inout Value, nextValue: () -> Value) {
_ = nextValue()
}
}