如何将SwiftUI App窗口UI分为两色区域并固定拆分效果
解决方案:固定文本框周边透明区域,窗口resize时保持不变
核心问题分析
原方案依赖窗口高度的比例值设置颜色区域和透明区域的高度,导致窗口调整大小时,透明区域高度会随窗口比例同步变化,完全违背了“透明区域固定”的需求。
优化方案
将底部透明区域设置为固定高度,上方颜色区域自动填充剩余窗口空间;同时调整布局层级,让文本框始终锚定在固定高度的透明区域内,确保窗口resize时透明区域尺寸完全不变。
优化后的完整代码
import SwiftUI struct ContentView: View { @State private var textFieldContent = "" // 自定义固定透明区域高度,可按需调整 private let transparentAreaHeight: CGFloat = 120 var body: some View { ZStack { VisualEffectView() // 背景区域拆分:上方颜色区 + 底部固定高度透明区 VStack(spacing: 0) { // 上方颜色区:自动填充除底部透明区外的所有空间 Color(red: 0.1, green: 0.1, blue: 0.1) .frame(maxHeight: .infinity) // 底部固定高度的透明区域 Color.clear .frame(height: transparentAreaHeight) } // 文本框与发送按钮:固定在底部透明区域内 HStack { TextField("Send a message", text: $textFieldContent) .textFieldStyle(RoundedBorderTextFieldStyle()) .padding() .background(Color.clear) .cornerRadius(25) .focusable(false) .padding(.leading, 20) Spacer() Button(action: { // 按钮执行逻辑 }) { Text("Send") .foregroundColor(.blue) } .buttonStyle(PlainButtonStyle()) .padding(.trailing, 20) } .frame(maxWidth: .infinity, alignment: .bottom) .padding(.bottom, 20) // 调整文本框在透明区域内的垂直位置 // 设置按钮:固定在右上角 VStack { HStack { Spacer() Button(action: { // 设置按钮执行逻辑 }) { Image(systemName: "gearshape") .foregroundColor(.blue) .padding() } .buttonStyle(PlainButtonStyle()) } Spacer() } .padding(.top, 20) .padding(.trailing, 20) } .edgesIgnoringSafeArea(.all) } } struct ContentView_Previews: PreviewProvider { static var previews: some View { ContentView() } } struct VisualEffectView: NSViewRepresentable { func makeNSView(context: Context) -> NSVisualEffectView { let view = NSVisualEffectView() view.blendingMode = .behindWindow view.state = .active view.material = .underWindowBackground return view } func updateNSView(_ nsView: NSVisualEffectView, context: Context) {} }
关键修改说明
- 移除了原代码中依赖窗口比例的
GeometryReader逻辑,改用固定高度定义透明区域 - 上方颜色区域通过
frame(maxHeight: .infinity)自动填充剩余空间,无需手动计算比例 - 文本框通过
.frame(maxWidth: .infinity, alignment: .bottom)和固定padding,确保始终位于底部透明区域内 - 简化布局层级,去掉冗余嵌套,提升代码可读性与运行性能
补充拓展技巧
如果需要让透明区域的宽度也固定(仅文本框周围保留透明),可将底部区域改为左右颜色区+中间固定宽度透明区,示例如下:
// 底部区域改为左右颜色填充+中间固定宽高透明区 HStack(spacing: 0) { Color(red: 0.1, green: 0.1, blue: 0.1) .frame(maxWidth: .infinity) Color.clear .frame(width: 400, height: transparentAreaHeight) // 固定宽度和高度 Color(red: 0.1, green: 0.1, blue: 0.1) .frame(maxWidth: .infinity) }
内容的提问来源于stack exchange,提问作者P_n
相关产品推荐
相关产品推荐

