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

SwiftUI macOS List实现鼠标点击位置弹出Popover

在macOS SwiftUI List中实现Popover从鼠标精确点击位置弹出

要让Popover从List行的精确点击位置弹出,需捕获点击坐标并将其设为Popover的附着锚点,以下是修改后的完整实现:

核心修改点

  • 捕获鼠标点击的精确坐标
  • 获取List行的实际尺寸,将绝对坐标转换为相对单位点
  • 用转换后的单位点作为Popover的附着锚点

完整代码

import SwiftUI

struct TestPopoverView: View {
    let items = ["Row 1", "Row 2", "Row 3", "Row 4", "Row 5"]

    var body: some View {
        List(items, id: \.self) { item in
            ListRowView(item: item)
        }
    }
}

struct ListRowView: View {
    let item: String
    @State private var showPopover = false
    @State private var tapLocation: CGPoint = .zero
    @State private var rowSize: CGSize = .zero

    var body: some View {
        HStack {
            Text(item)
                .padding()
            Spacer()
        }
        // 获取当前行的尺寸
        .background(
            GeometryReader { proxy in
                Color.clear
                    .onAppear {
                        rowSize = proxy.size
                    }
            }
        )
        .contentShape(Rectangle()) // 确保整行可点击
        .onTapGesture { location in
            tapLocation = location
            showPopover = true
        }
        .popover(
            isPresented: $showPopover,
            // 将点击坐标转换为相对单位点作为锚点
            attachmentAnchor: .point(UnitPoint(
                x: tapLocation.x / rowSize.width,
                y: tapLocation.y / rowSize.height
            )),
            arrowEdge: .bottom
        ) {
            PopoverContentView(item: item)
        }
    }
}

struct PopoverContentView: View {
    let item: String

    var body: some View {
        VStack {
            Text("Selected: \(item)")
                .padding()
        }
        .frame(width: 200, height: 100)
    }
}

#Preview {
    TestPopoverView()
        .frame(width: 300, height: 350)
}

关键说明

  1. 视图尺寸获取:通过GeometryReader包裹行背景,获取行的实际宽高,为坐标转换提供基准
  2. 点击坐标捕获:onTapGesture的location参数直接返回鼠标点击的绝对坐标,存储到状态变量中
  3. 锚点转换:将绝对坐标除以行的宽高,得到0-1范围内的相对单位点,作为Popover的attachmentAnchor,确保箭头精准指向点击位置
  4. 整行可点击:contentShape(Rectangle())保留了原有的整行点击范围,不影响用户交互体验

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 16:21:05