You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何创建适配背景内容的液态玻璃效果工具栏按钮

如何创建适配背景内容的液态玻璃效果工具栏按钮

我完全懂你想要的效果——就是iOS Safari那种双层玻璃质感的工具栏,按钮图标能跟着下方滚动的背景自动切换明暗,而且整个工具栏共享一块平滑的玻璃面板,不会每个按钮都冒出单独的小气泡对吧?我来帮你调整代码,解决这个核心问题。

核心问题拆解

你之前的问题主要出在两个地方:

  • 按钮没用到自适应前景样式,导致颜色固定死,不会随背景明暗变化
  • 玻璃效果的应用层级不对,要么每个按钮单独生成气泡,要么没让整个工具栏共享同一块玻璃面板

修复后的完整代码

我把你的代码调整后,既保留了两行工具栏的布局,又解决了颜色适配和玻璃气泡的问题:

import SwiftUI

@main
struct GlassToolbarDemoApp: App {
    var body: some Scene {
        WindowGroup {
            DemoView()
        }
    }
}

struct DemoView: View {
    @State private var query: String = ""
    
    var body: some View {
        ZStack {
            // 保留你用来测试的滚动背景
            SampleBackgroundScroll()
                .ignoresSafeArea() // 让背景延伸到安全区外,增强玻璃沉浸感
        }
        // 把工具栏固定在底部(改成.top就能放到顶部)
        .safeAreaInset(edge: .bottom) {
            // 整个工具栏的外层玻璃容器——共享同一块玻璃面板
            VStack(spacing: 8) {
                // 第一行:搜索栏
                HStack(spacing: 10) {
                    HStack(spacing: 8) {
                        Image(systemName: "magnifyingglass")
                            .foregroundStyle(.secondary)
                        TextField("Search…", text: $query)
                            .textInputAutocapitalization(.never)
                    }
                    .padding(.horizontal, 12)
                    .padding(.vertical, 10)
                    .background(
                        RoundedRectangle(cornerRadius: 14, style: .continuous)
                            .fill(.thinMaterial) // 搜索栏单独的薄玻璃效果
                    )
                }
                .frame(maxWidth: .infinity, alignment: .leading)
                .padding(.horizontal, 2)
                
                Divider().opacity(0.25)
                
                // 第二行:工具栏按钮(核心修改在这里!)
                HStack(spacing: 20) {
                    // 改成Button还能加点击事件,不影响颜色适配
                    Button(action: { /* 首页点击逻辑 */ }) {
                        Image(systemName: "house.fill")
                            .font(.system(size:36))
                            .frame(width: 40, height: 40)
                    }
                    .foregroundStyle(.primary) // 关键:自动随背景切换明暗
                    
                    Button(action: { /* 搜索点击逻辑 */ }) {
                        Image(systemName: "text.magnifyingglass")
                            .font(.system(size:36))
                            .frame(width: 40, height: 40)
                    }
                    .foregroundStyle(.primary)
                    
                    Button(action: { /* 新增点击逻辑 */ }) {
                        Image(systemName: "plus.circle.fill")
                            .font(.system(size:36))
                            .frame(width: 40, height: 40)
                    }
                    .foregroundStyle(.primary)
                }
            }
            .padding(.horizontal, 14)
            .padding(.vertical, 10)
            .frame(maxWidth: .infinity)
            .background(.ultraThinMaterial) // 整个工具栏的玻璃背景,统一面板
            .shadow(color: .black.opacity(0.12), radius: 20, y: 10)
            .padding(.horizontal)
            .padding(.top, 6)
        }
    }
}

// MARK: - 测试用的滚动背景(保留你的原代码,用来验证适配效果)
struct SampleBackgroundScroll: View {
    var body: some View {
        ScrollView {
            LazyVStack(spacing: 0) {
                demoBlock(.light, title: "Sunny Paper")
                demoBlock(.dark, title: "Night Slate")
                demoBlock(.light, title: "Porcelain")
                demoBlock(.colorful, title: "Aurora Cyan")
                demoBlock(.dark, title: "Graphite")
                demoBlock(.colorfulAlt, title: "Sunset Blend")
                demoBlock(.light, title: "Foggy White")
                demoBlock(.dark, title: "Charcoal")
            }
        }
    }
    
    @ViewBuilder
    func demoBlock(_ style: BlockStyle, title: String) -> some View {
        ZStack {
            switch style {
            case .light:
                LinearGradient(colors: [Color.white, Color(white: 0.93)], startPoint: .topLeading, endPoint: .bottomTrailing)
            case .dark:
                LinearGradient(colors: [Color.black, Color(white: 0.15)], startPoint: .top, endPoint: .bottom)
            case .colorful:
                LinearGradient(colors: [Color.cyan.opacity(0.7), Color.blue.opacity(0.4)], startPoint: .topLeading, endPoint: .bottomTrailing)
            case .colorfulAlt:
                LinearGradient(colors: [Color.purple, Color.orange], startPoint: .topLeading, endPoint: .bottomTrailing)
            }
            
            VStack(spacing: 12) {
                Text(title)
                    .font(.system(size: 28, weight: .bold))
                    .foregroundStyle(style == .dark ? .white : .primary)
                Text("Scroll to see how the glass adapts to different backgrounds.")
                    .font(.system(size: 15))
                    .foregroundStyle(style == .dark ? .white.opacity(0.85) : .secondary)
            }
            .padding(.top, 120)
        }
        .frame(height: 360)
    }
    
    enum BlockStyle {
        case light, dark, colorful, colorfulAlt
    }
}

#Preview {
    DemoView()
}

关键修改说明

  1. 统一玻璃容器:把整个两行工具栏放到一个.background(.ultraThinMaterial)的容器里,这样整个工具栏共享一块玻璃面板,不会出现单独的按钮气泡,完美融合成一个整体。
  2. 自适应前景色:给每个按钮加.foregroundStyle(.primary),这是SwiftUI内置的自适应样式——暗背景下自动显示亮色,亮背景下自动显示暗色,完全跟着滚动的内容变化。
  3. 可选的按钮交互:把Image改成Button,既保留了颜色适配效果,又能添加点击事件,完全符合实际开发需求。
  4. 简化玻璃逻辑:去掉了之前复杂的.glassEffectUnion,改用更直接的.background(.ultraThinMaterial),效果更稳定也更容易控制。

现在滚动背景试试,工具栏按钮会自动跟着下方的明暗区域切换颜色,玻璃面板平滑统一,完全就是你想要的Safari同款效果!

火山引擎 最新活动