如何在iPadOS中使用SwiftUI为视图实现自定义鼠标指针效果
实现方案
要求运行环境为 iPadOS 13.4 及以上版本,通过桥接 UIKit 指针交互 API 实现和示例完全一致的自定义效果:
第一步:封装交互逻辑
import SwiftUI import UIKit struct PointerInteractionView: UIViewRepresentable { var useStraightLineStitch: Bool var gridHeight: CGFloat func makeCoordinator() -> Coordinator { Coordinator(parent: self) } func makeUIView(context: Context) -> UIView { let view = UIView(frame: .zero) view.backgroundColor = .clear let interaction = UIPointerInteraction(delegate: context.coordinator) view.addInteraction(interaction) return view } func updateUIView(_ uiView: UIView, context: Context) { context.coordinator.parent = self } class Coordinator: NSObject, UIPointerInteractionDelegate { var parent: PointerInteractionView init(parent: PointerInteractionView) { self.parent = parent } func pointerInteraction(_ interaction: UIPointerInteraction, regionFor request: UIPointerRegionRequest, defaultRegion: UIPointerRegion) -> UIPointerRegion? { if parent.useStraightLineStitch { let regionNumber = floor(request.location.y / parent.gridHeight) return UIPointerRegion(rect: CGRect( x: 0, y: regionNumber * parent.gridHeight, width: interaction.view?.bounds.width ?? 0, height: parent.gridHeight )) } else { return defaultRegion } } func pointerInteraction(_ interaction: UIPointerInteraction, styleFor region: UIPointerRegion) -> UIPointerStyle? { let crosshair = UIPointerShape.path(crosshairBezierPath()) if parent.useStraightLineStitch { return UIPointerStyle(shape: crosshair, constrainedAxes: [.vertical]) } else { return UIPointerStyle(shape: crosshair) } } private func crosshairBezierPath() -> UIBezierPath { let crosshairPath = UIBezierPath() crosshairPath.move(to: CGPoint(x: -1.5, y: 1.5)) crosshairPath.addLine(to: CGPoint(x: -1.5, y: 10)) crosshairPath.addArc(withCenter: CGPoint(x: 0, y: 10), radius: 1.5, startAngle: CGFloat.pi, endAngle: 0, clockwise: false) crosshairPath.addLine(to: CGPoint(x: 1.5, y: 1.5)) crosshairPath.addLine(to: CGPoint(x: 10, y: 1.5)) crosshairPath.addArc(withCenter: CGPoint(x: 10, y: 0), radius: 1.5, startAngle: CGFloat.pi / 2.0, endAngle: CGFloat.pi * 1.5, clockwise: false) crosshairPath.addLine(to: CGPoint(x: 1.5, y: -1.5)) crosshairPath.addLine(to: CGPoint(x: 1.5, y: -10)) crosshairPath.addArc(withCenter: CGPoint(x: 0, y: -10), radius: 1.5, startAngle: 0, endAngle: CGFloat.pi, clockwise: false) crosshairPath.addLine(to: CGPoint(x: -1.5, y: -1.5)) crosshairPath.addLine(to: CGPoint(x: -10, y: -1.5)) crosshairPath.addArc(withCenter: CGPoint(x: -10, y: 0), radius: 1.5, startAngle: CGFloat.pi * 1.5, endAngle: CGFloat.pi / 2.0, clockwise: false) crosshairPath.close() return crosshairPath } } } extension View { func customPointer(useStraightLineStitch: Bool, gridHeight: CGFloat) -> some View { self.background( PointerInteractionView(useStraightLineStitch: useStraightLineStitch, gridHeight: gridHeight) .allowsHitTesting(false) ) } }
第二步:调用示例
直接给需要添加自定义指针的 SwiftUI 视图挂载上方封装好的 modifier 即可:
struct QuiltView: View { // 可动态修改的业务参数 @State private var useStraightLineStitch = true @State private var gridHeight: CGFloat = 44 var body: some View { // 这里替换为你原本的视图内容 Rectangle() .fill(.gray.opacity(0.2)) .frame(width: 300, height: 600) // 应用自定义指针效果 .customPointer(useStraightLineStitch: useStraightLineStitch, gridHeight: gridHeight) } }
以上实现完全对齐原 UIKit 示例的指针样式、区域计算逻辑,支持参数动态更新。
内容的提问来源于stack exchange,提问作者Tiago Mendes
相关产品推荐
相关产品推荐

