Skip to content

Commit df858e5

Browse files
committed
fix(iOS): labels not following inactiveTintColor on ios 26.4.1
1 parent 0792ae1 commit df858e5

1 file changed

Lines changed: 86 additions & 0 deletions

File tree

packages/react-native-bottom-tabs/ios/TabViewImpl.swift

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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

255341
extension View {

0 commit comments

Comments
 (0)