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

如何为侧边菜单实现仅左侧区域触发的部分DragGesture效果

解决方案

要实现仅从屏幕左侧区域触发侧边菜单的拖动手势,有两种实现方式可选:

方案一:添加专属触发区域(更稳定)

将原本挂载在整个ZStack上的全局手势,移动到左侧专属的透明触发层上,只有拖动该区域才会响应手势,修改后的代码如下:

@State var width = UIScreen.main.bounds.width - 65
@State var x = -UIScreen.main.bounds.width + 65

var body: some View {
    
    ZStack(alignment: Alignment(horizontal: .leading, vertical: .center)) {
        HomePage(x: $x)
        SlideMenu()
            .shadow(color: Color.black.opacity(x == 0 ? 0.2 : 0), radius: 5, x: 5, y:0)
            .offset(x: x)
            .background(Color.gray.opacity(x == 0 ? 0.2 : 0).ignoresSafeArea(.all, edges: .vertical).onTapGesture {
                withAnimation {
                    x = -width
                }
            })
        // 左侧触发区域,width参数可自定义调整匹配你的需求
        Color.clear
            .frame(width: 20)
            .contentShape(Rectangle()) // 确保透明区域可以正常响应手势
            .edgesIgnoringSafeArea(.vertical)
            .gesture(DragGesture().onChanged({ (value) in
                withAnimation {
                    if value.translation.width > 0 {
                        if x < 0 {
                            x = -width + value.translation.width
                        }
                    } else {
                        // 菜单展开后允许向左拖动关闭,不需要可以删除该分支
                        if x == 0 {
                            x = value.translation.width
                        }
                    }
                }
            }).onEnded({ (value) in
                withAnimation {
                    if -x < width / 2 {
                        x = 0
                    } else {
                        x = -width
                    }
                }
            }))
    }
    // 移除原本挂载在ZStack上的全局手势
}

方案二:手势起始位置校验(无需修改视图结构)

直接在原有手势的响应逻辑开头加起始位置校验,只有拖动起点在左侧指定范围内才会触发后续逻辑:

@State var width = UIScreen.main.bounds.width - 65
@State var x = -UIScreen.main.bounds.width + 65

var body: some View {
    
    ZStack(alignment: Alignment(horizontal: .leading, vertical: .center)) {
        HomePage(x: $x)
        SlideMenu()
            .shadow(color: Color.black.opacity(x == 0 ? 0.2 : 0), radius: 5, x: 5, y:0)
            .offset(x: x)
            .background(Color.gray.opacity(x == 0 ? 0.2 : 0).ignoresSafeArea(.all, edges: .vertical).onTapGesture {
                withAnimation {
                    
                    x = -width
                }
            })
    }
    .gesture(DragGesture().onChanged({ (value) in
        // 仅当拖动起始位置在屏幕左侧30pt范围内时才响应,数值可自定义
        guard value.startLocation.x < 30 else { return }
        withAnimation {
            if value.translation.width > 0 {
                if x < 0 {
                    x = -width + value.translation.width
                }
            }
            else {
                x = value.translation.width
            }
        }
    }).onEnded({ (value) in
        guard value.startLocation.x < 30 else { return }
        withAnimation {
            if -x < width / 2 {
            x = 0
            }
            else {
                x = -width
            }
        }
    }))
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 21:42:03