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

iOS 11下用Swift获取UIBarButtonItem原点与Frame的方法

在iOS 11中用Swift获取UINavigationBar上UIBarButtonItem的Frame及原点坐标

嘿,这个问题确实有点棘手——毕竟UIBarButtonItem本身并非UIView的子类,直接调用它的frame属性肯定行不通。不过咱们可以通过它背后对应的UI视图来获取所需的坐标和Frame,下面给你几种在iOS 11及以上版本适用的Swift实现方案:

方案一:通过KVC获取内部视图(最直接)

UIBarButtonItem在系统内部是由一个UIView实例来承载的,我们可以通过KVC的方式拿到这个私有视图,进而获取它的Frame:

// 假设你要获取右侧导航栏按钮的Frame
if let targetBarButton = navigationItem.rightBarButtonItem,
   let buttonView = targetBarButton.value(forKey: "view") as? UIView {
    // 获取按钮在导航栏坐标系中的Frame和原点
    let barButtonFrame = buttonView.frame
    print("按钮在导航栏中的Frame:\(barButtonFrame)")
    print("原点坐标:(\(barButtonFrame.origin.x), \(barButtonFrame.origin.y))")
    
    // 如果需要转换到屏幕坐标系的坐标
    let screenFrame = buttonView.convert(buttonView.bounds, to: nil)
    print("按钮在屏幕中的Frame:\(screenFrame)")
}

注意:虽然"view"这个Key属于系统私有API,但在iOS 11及后续版本中稳定性较好,很多成熟的App也在使用。不过如果苹果后续修改内部实现,这个方法可能会失效,需要留意版本适配。

方案二:遍历导航栏子视图(更安全,无私有API)

如果你不想依赖私有API,可以遍历导航栏的子视图,通过标识(比如tag、标题、视图类型)找到目标按钮对应的视图:

// 提前给目标UIBarButtonItem的视图设置tag,比如创建时:
// let customButton = UIButton(type: .system)
// customButton.tag = 100
// let barButtonItem = UIBarButtonItem(customView: customButton)
// navigationItem.rightBarButtonItem = barButtonItem

// 遍历导航栏子视图查找目标
if let navBar = navigationController?.navigationBar {
    for subview in navBar.subviews {
        if let barButton = subview as? UIControl, barButton.tag == 100 {
            let frame = barButton.frame
            print("按钮Frame:\(frame)")
            print("原点坐标:(\(frame.origin.x), \(frame.origin.y))")
            break
        }
    }
}

这种方法的优势是完全基于公开API,兼容性更强,但需要你提前给目标视图设置可识别的标识,或者通过视图的其他特征(比如标题文本)来匹配。

方案三:自定义UIBarButtonItem时直接获取(最稳妥)

如果你是用customView创建的自定义UIBarButtonItem,那直接访问customView的Frame就可以了,这是最稳妥的方式:

if let customButtonView = navigationItem.rightBarButtonItem?.customView {
    // 获取在导航栏中的Frame
    let frameInNavBar = customButtonView.frame
    print("自定义按钮在导航栏中的Frame:\(frameInNavBar)")
    
    // 转换到屏幕坐标系
    let screenFrame = customButtonView.convert(customButtonView.bounds, to: nil)
    print("自定义按钮在屏幕中的Frame:\(screenFrame)")
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 03:28:04