You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SwiftUI实现滑入视图:保持主视图尺寸不被挤压的方案

滑入视图推开主视图的实现方案

问题场景

滑动前效果:
滑动前
滑动后效果:
滑动后

当前代码实现:

struct SlideView: View {
        @State var isClicked = false
        var body: some View {
            HStack{
                Rectangle()
                    .fill(.gray)
                    .ignoresSafeArea()
                    .frame(width: isClicked ? UIScreen.main.bounds.width * 0.75 : 0)
                
                
            VStack{
                Text("This gets squished")
                HStack{
                    Button{
                        withAnimation(.spring()) {
                            isClicked.toggle()
                        }
                        
                    } label: {
                        Image(systemName: "menucard.fill")
                            .padding(.leading)
                    }
                    Spacer()
                }
                Spacer()
            }

        }
    }
}

现有问题:HStack布局会让灰色视图和主视图按比例分配空间,导致主视图被挤压至原尺寸的25%,需要实现灰色视图滑入时推开主视图,主视图保持原尺寸,仅显示左部1/4区域,其余部分隐藏。

解决方案

使用ZStack配合偏移和裁剪功能,让主视图始终保持全屏尺寸,通过偏移实现被推开的视觉效果,同时裁剪超出屏幕的部分:

struct SlideView: View {
    @State var isClicked = false
    private let menuWidth = UIScreen.main.bounds.width * 0.75
    
    var body: some View {
        ZStack(alignment: .leading) {
            // 滑入的灰色菜单视图
            Rectangle()
                .fill(.gray)
                .ignoresSafeArea()
                .frame(width: menuWidth)
            
            // 主视图:保持全屏尺寸,通过偏移实现被推开效果
            VStack{
                Text("This no longer gets squished")
                HStack{
                    Button{
                        withAnimation(.spring()) {
                            isClicked.toggle()
                        }
                    } label: {
                        Image(systemName: "menucard.fill")
                            .padding(.leading)
                    }
                    Spacer()
                }
                Spacer()
            }
            .frame(maxWidth: .infinity, maxHeight: .infinity)
            .offset(x: isClicked ? menuWidth : 0)
            .clipped() // 裁剪超出屏幕的部分,只显示左部1/4区域
        }
    }
}

原理说明

  1. ZStack将灰色菜单和主视图层叠布局,菜单在底层,主视图在顶层
  2. 主视图通过frame(maxWidth: .infinity, maxHeight: .infinity)保持全屏尺寸
  3. 点击按钮时,主视图向右偏移menuWidth(屏幕宽度的75%),此时屏幕内仅能显示主视图左部25%的区域
  4. clipped()裁剪掉主视图超出屏幕的部分,实现“仅显示左部1/4”的效果
  5. 配合withAnimation(.spring())实现平滑的过渡动画

内容的提问来源于stack exchange,提问作者Tom Mils

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 10:18:19