Getting the frame of a particular tab bar item

Viewed 30636

Is there a way to find the frame of a particular UITabBarItem in a UITabBar?

Specifically, I want to create an animation of an image "falling" into one of the tabs, similar to e.g. deleting an email in the Mail, or buying a track in the iTunes app. So I need the target coordinates for the animation.

As far as I can tell, there's no public API to get the coordinates, but would love to be wrong about that. Short of that, I'll have to guesstimate the coordinates using the index of the given tab relative to the tab bar frame.

11 Answers

By Extending UITabBar

extension UITabBar {

    func getFrameForTabAt(index: Int) -> CGRect? {
        var frames = self.subviews.compactMap { return $0 is UIControl ? $0.frame : nil }
        frames.sort { $0.origin.x < $1.origin.x }
        return frames[safe: index]
    }

}

extension Collection {

    subscript (safe index: Index) -> Element? {
        return indices.contains(index) ? self[index] : nil
    }

}

Swift + iOS 11

private func frameForTabAtIndex(index: Int) -> CGRect {
    guard let tabBarSubviews = tabBarController?.tabBar.subviews else {
        return CGRect.zero
    }
    var allItems = [UIView]()
    for tabBarItem in tabBarSubviews {
        if tabBarItem.isKind(of: NSClassFromString("UITabBarButton")!) {
            allItems.append(tabBarItem)
        }
    }
    let item = allItems[index]
    return item.superview!.convert(item.frame, to: view)
}

Swift 5:

Just put this in your View Controller that handles your tabBar.

guard let tab1frame = self.tabBar.items![0].value(forKey: "view") as? UIView else {return}

then use like so:

let tab1CentreXanc = tab1frame.centerXAnchor
let tab1CentreY = tab1frame.centerYAnchor
let tab1FRAME = tab1frame (centerX and Y and other parameters such as ".origins.x or y"

Hope that helps.

If you want to reference the parameters from other tabs, just change the index from [0] to whatever you want

redead's answer definitely works so please upvote it.

I needed to add an activity indicator to the tabBar and to do that I needed the tabBar's rect inside the window so I had to add some additional code to his answer:

// 1. get the frame for the first tab like in his answer
guard let firstTab = tabBarController?.tabBar.items?[0].valueForKey("view") as? UIView else { return }
print("firstTabframe: \(firstTab.frame)")

// 2. get a reference to the window
guard let window = UIApplication.shared.keyWindow else { return }

// 3. get the firstTab's rect inside the window
let firstTabRectInWindow = firstTab.convert(firstTab.frame, to: window)
print("firstTabRectInWindow: \(firstTabRectInWindow)")
Related