@@ -153,6 +153,7 @@ struct TabViewImpl: View {
153153 item. setTitleTextAttributes ( attributes, for: . normal)
154154 item. setTitleTextAttributes ( selectedAttributes ( props: props) , for: . selected)
155155 }
156+ configureTabBarItemImagesAfterLayout ( tabBar: tabBar, props: props)
156157 }
157158
158159 private func configureStandardAppearance( tabBar: UITabBar , props: TabViewProps ) {
@@ -209,6 +210,7 @@ struct TabViewImpl: View {
209210 if let items = tabBar. items {
210211 configureTabBarItemImages ( items: items, props: props)
211212 configureTabBarItemTitles ( items: items, props: props)
213+ configureTabBarItemImagesAfterLayout ( tabBar: tabBar, props: props)
212214 }
213215 }
214216
@@ -233,6 +235,25 @@ struct TabViewImpl: View {
233235 let itemIndex = props. items. firstIndex ( where: { $0. key == tabData. key } ) ,
234236 let icon = props. icons [ itemIndex] else { continue }
235237
238+ if shouldRenderTabBarLabelsIntoImages ( ) , props. labeled {
239+ item. title = " "
240+ item. accessibilityLabel = tabData. title
241+ item. titlePositionAdjustment = UIOffset ( horizontal: 0 , vertical: 100 )
242+ item. image = makeTabBarItemImage (
243+ icon: icon,
244+ title: tabData. title,
245+ color: props. inactiveTintColor,
246+ props: props
247+ )
248+ item. selectedImage = makeTabBarItemImage (
249+ icon: icon,
250+ title: tabData. title,
251+ color: props. selectedActiveTintColor,
252+ props: props
253+ )
254+ continue
255+ }
256+
236257 item. image = props. inactiveTintColor. map {
237258 icon. withTintColor ( $0, renderingMode: . alwaysOriginal)
238259 } ?? icon
@@ -242,6 +263,15 @@ struct TabViewImpl: View {
242263 }
243264 }
244265
266+ private func configureTabBarItemImagesAfterLayout( tabBar: UITabBar , props: TabViewProps ) {
267+ guard shouldRenderTabBarLabelsIntoImages ( ) else { return }
268+
269+ DispatchQueue . main. async { [ weak tabBar] in
270+ guard let tabBar, let items = tabBar. items else { return }
271+ configureTabBarItemImages ( items: items, props: props)
272+ }
273+ }
274+
245275 private func selectedAttributes( props: TabViewProps ) -> [ NSAttributedString . Key : Any ] {
246276 TabBarFontSize . createFontAttributes (
247277 size: props. fontSize. map ( CGFloat . init) ?? TabBarFontSize . defaultSize,
@@ -250,6 +280,62 @@ struct TabViewImpl: View {
250280 color: props. selectedActiveTintColor
251281 )
252282 }
283+
284+ private func shouldRenderTabBarLabelsIntoImages( ) -> Bool {
285+ let version = ProcessInfo . processInfo. operatingSystemVersion
286+ return version. majorVersion > 26 || ( version. majorVersion == 26 && version. minorVersion >= 4 )
287+ }
288+
289+ private func makeTabBarItemImage(
290+ icon: UIImage ,
291+ title: String ,
292+ color: UIColor ? ,
293+ props: TabViewProps
294+ ) -> UIImage {
295+ let color = color ?? . label
296+ let iconSize = CGSize ( width: 27 , height: 27 )
297+ let font = TabBarFontSize . createFontAttributes (
298+ size: props. fontSize. map ( CGFloat . init) ?? TabBarFontSize . defaultSize,
299+ family: props. fontFamily,
300+ weight: props. fontWeight
301+ ) [ . font] as? UIFont ?? UIFont . boldSystemFont ( ofSize: TabBarFontSize . defaultSize)
302+ let paragraphStyle = NSMutableParagraphStyle ( )
303+ paragraphStyle. alignment = . center
304+ let attributes : [ NSAttributedString . Key : Any ] = [
305+ . font: font,
306+ . foregroundColor: color,
307+ . paragraphStyle: paragraphStyle,
308+ ]
309+ let titleSize = ( title as NSString ) . size ( withAttributes: attributes)
310+ let imageSize = CGSize (
311+ width: max ( iconSize. width, ceil ( titleSize. width) ) + 8 ,
312+ height: iconSize. height + 3 + ceil( titleSize. height)
313+ )
314+ let format = UIGraphicsImageRendererFormat ( )
315+ format. scale = UIScreen . main. scale
316+
317+ let image = UIGraphicsImageRenderer ( size: imageSize, format: format) . image { _ in
318+ let tintedIcon = icon. withTintColor ( color, renderingMode: . alwaysOriginal)
319+ tintedIcon. draw ( in: CGRect (
320+ x: ( imageSize. width - iconSize. width) / 2 ,
321+ y: 0 ,
322+ width: iconSize. width,
323+ height: iconSize. height
324+ ) )
325+
326+ ( title as NSString ) . draw (
327+ in: CGRect (
328+ x: 0 ,
329+ y: iconSize. height + 3 ,
330+ width: imageSize. width,
331+ height: ceil ( titleSize. height)
332+ ) ,
333+ withAttributes: attributes
334+ )
335+ }
336+
337+ return image. withRenderingMode ( . alwaysOriginal)
338+ }
253339#endif
254340
255341extension View {
0 commit comments