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
}