For what it's worth, here's my implementation to add a UILargeContentViewerInteraction to a UITabBar without using UITabBarController but inside a custom UIViewController.
First, add the interaction to the view of the view controller with the view controller as the interaction delegate.
view.showsLargeContentViewer = true
view.scalesLargeContentImage = true
view.addInteraction(UILargeContentViewerInteraction(delegate: self))
It's needed to implement tow function of the UILargeContentViewerInteractionDelegate protocol:
Both functions have to get the index of the tab bar item for the point parameter so here's a function to do that:
private func tabItemIndex(for point: CGPoint) -> Int? {
let convertedPoint = view.convert(point, to: tabBar)
guard
tabBar.point(inside: convertedPoint, with: nil),
let numberOfItems = tabBar.items?.count,
numberOfItems > 0
else { return nil }
let itemWidth = tabBar.bounds.width / CGFloat(numberOfItems)
return Int(convertedPoint.x / itemWidth)
}
The function converts the point from the view to the tabBar and ensures the point is inside the tabBar. Then the point x member is divided by the width of an item so that every point targets an item.
For the large content item, the view itself is used. It is configured using the retrieved UITabBarItem:
func largeContentViewerInteraction(
_: UILargeContentViewerInteraction,
itemAt point: CGPoint
) -> (any UILargeContentViewerItem)? {
guard
let tabItemIndex = tabItemIndex(for: point),
let item = tabBar.items?[tabItemIndex]
else { return nil }
view.largeContentTitle = item.title
view.largeContentImage = item.image
return view
}
The item is then selected when the interaction ends.
func largeContentViewerInteraction(
_: UILargeContentViewerInteraction,
didEndOn _: (any UILargeContentViewerItem)?,
at point: CGPoint
) {
guard
let tabItemIndex = tabItemIndex(for: point),
let item = tabBar.items?[tabItemIndex]
else { return }
tabBar.selectedItem = item
tabBar(tabBar, didSelect: item) // call of UITabBarDelegate
}