From fada2f002abb9599b76e2b6165ee381eb0699682 Mon Sep 17 00:00:00 2001 From: adids1221 Date: Mon, 1 Dec 2025 11:25:37 +0200 Subject: [PATCH] feat: add iconBackground support to backButton on iOS and Android --- .../options/BackButton.java | 3 +++ .../stack/topbar/button/ButtonPresenter.kt | 3 ++- ios/RNNBackButtonOptions.h | 2 ++ ios/RNNBackButtonOptions.mm | 5 ++++- ios/TopBarPresenter.mm | 16 ++++++++++++++++ src/interfaces/Options.ts | 4 ++++ 6 files changed, 31 insertions(+), 2 deletions(-) diff --git a/android/src/main/java/com/reactnativenavigation/options/BackButton.java b/android/src/main/java/com/reactnativenavigation/options/BackButton.java index f766ea78549..8be3bcbf489 100644 --- a/android/src/main/java/com/reactnativenavigation/options/BackButton.java +++ b/android/src/main/java/com/reactnativenavigation/options/BackButton.java @@ -27,6 +27,7 @@ public static BackButton parse(Context context, JSONObject json) { result.disableIconTint = BoolParser.parse(json, "disableIconTint"); result.color = ThemeColour.parse(context, json.optJSONObject( "color")); result.disabledColor = ThemeColour.parse(context, json.optJSONObject( "disabledColor")); + result.iconBackground = IconBackgroundOptions.parse(context, json.optJSONObject("iconBackground")); result.testId = TextParser.parse(json, "testID"); result.popStackOnPress = BoolParser.parse(json, "popStackOnPress"); @@ -54,6 +55,7 @@ public void mergeWith(BackButton other) { if (other.disabledColor.hasValue()) disabledColor = other.disabledColor; if (other.disableIconTint.hasValue()) disableIconTint = other.disableIconTint; if (other.enabled.hasValue()) enabled = other.enabled; + if (other.iconBackground.hasValue()) iconBackground = other.iconBackground; if (other.testId.hasValue()) testId = other.testId; if (other.popStackOnPress.hasValue()) popStackOnPress = other.popStackOnPress; } @@ -67,6 +69,7 @@ void mergeWithDefault(final BackButton defaultOptions) { if (!disabledColor.hasValue()) disabledColor = defaultOptions.disabledColor; if (!disableIconTint.hasValue()) disableIconTint = defaultOptions.disableIconTint; if (!enabled.hasValue()) enabled = defaultOptions.enabled; + if (!iconBackground.hasValue()) iconBackground = defaultOptions.iconBackground; if (!testId.hasValue()) testId = defaultOptions.testId; if (!popStackOnPress.hasValue()) popStackOnPress = defaultOptions.popStackOnPress; } diff --git a/android/src/main/java/com/reactnativenavigation/viewcontrollers/stack/topbar/button/ButtonPresenter.kt b/android/src/main/java/com/reactnativenavigation/viewcontrollers/stack/topbar/button/ButtonPresenter.kt index dbe077468fd..ff16ed3d10b 100644 --- a/android/src/main/java/com/reactnativenavigation/viewcontrollers/stack/topbar/button/ButtonPresenter.kt +++ b/android/src/main/java/com/reactnativenavigation/viewcontrollers/stack/topbar/button/ButtonPresenter.kt @@ -163,9 +163,10 @@ open class ButtonPresenter(private val context: Context, private val button: But fun applyNavigationIcon(toolbar: Toolbar, onPress: (ButtonOptions) -> Unit) { iconResolver.resolve(button) { icon: Drawable -> setIconColor(icon) + val iconWithBackground = applyIconBackgroundDrawable(icon) toolbar.setNavigationOnClickListener { onPress(button) } toolbar.navigationIcon = null - toolbar.navigationIcon = icon + toolbar.navigationIcon = iconWithBackground setLeftButtonTestId(toolbar) if (button.accessibilityLabel.hasValue()) toolbar.navigationContentDescription = button.accessibilityLabel.get() } diff --git a/ios/RNNBackButtonOptions.h b/ios/RNNBackButtonOptions.h index e9a0324d62c..47a72954596 100644 --- a/ios/RNNBackButtonOptions.h +++ b/ios/RNNBackButtonOptions.h @@ -1,4 +1,5 @@ #import "RNNOptions.h" +#import "RNNIconBackgroundOptions.h" @interface RNNBackButtonOptions : RNNOptions @@ -16,6 +17,7 @@ @property(nonatomic, strong) Text *displayMode; @property(nonatomic, strong) Text *identifier; @property(nonatomic, strong) Bool *popStackOnPress; +@property(nonatomic, strong) RNNIconBackgroundOptions *iconBackground; - (BOOL)hasValue; diff --git a/ios/RNNBackButtonOptions.mm b/ios/RNNBackButtonOptions.mm index 5fd739a66b5..252d119149d 100644 --- a/ios/RNNBackButtonOptions.mm +++ b/ios/RNNBackButtonOptions.mm @@ -19,11 +19,13 @@ - (instancetype)initWithDict:(NSDictionary *)dict { self.enableMenu = [BoolParser parse:dict key:@"enableMenu"]; self.displayMode = [TextParser parse:dict key:@"displayMode"]; self.popStackOnPress = [BoolParser parse:dict key:@"popStackOnPress"]; + self.iconBackground = [[RNNIconBackgroundOptions alloc] initWithDict:dict[@"iconBackground"] enabled:nil]; return self; } - (void)mergeOptions:(RNNBackButtonOptions *)options { + [self.iconBackground mergeOptions:options.iconBackground]; if (options.identifier.hasValue) self.identifier = options.identifier; if (options.icon.hasValue) @@ -57,7 +59,8 @@ - (void)mergeOptions:(RNNBackButtonOptions *)options { - (BOOL)hasValue { return self.icon.hasValue || self.showTitle.hasValue || self.color.hasValue || self.fontFamily.hasValue || self.fontSize.hasValue || self.title.hasValue || - self.enableMenu.hasValue || self.displayMode.hasValue || self.sfSymbol.hasValue; + self.enableMenu.hasValue || self.displayMode.hasValue || self.sfSymbol.hasValue || + self.iconBackground.hasValue; } @end diff --git a/ios/TopBarPresenter.mm b/ios/TopBarPresenter.mm index 1115bddfa07..cc6531e3fa3 100644 --- a/ios/TopBarPresenter.mm +++ b/ios/TopBarPresenter.mm @@ -1,6 +1,7 @@ #import "TopBarPresenter.h" #import "RNNFontAttributesCreator.h" #import "RNNUIBarBackButtonItem.h" +#import "RNNIconDrawer.h" #import "UIColor+RNNUtils.h" #import "UIImage+utils.h" #import "UINavigationController+RNNOptions.h" @@ -179,6 +180,21 @@ - (void)setBackButtonOptions:(RNNBackButtonOptions *)backButtonOptions { : icon; } + // Apply iconBackground if present + if (backButtonOptions.iconBackground.hasValue && icon) { + UIColor *backgroundColor = [backButtonOptions.iconBackground.color withDefault:UIColor.clearColor]; + CGFloat cornerRadius = [backButtonOptions.iconBackground.cornerRadius withDefault:@(0)].floatValue; + CGFloat width = [backButtonOptions.iconBackground.width withDefault:@(icon.size.width)].floatValue; + CGFloat height = [backButtonOptions.iconBackground.height withDefault:@(icon.size.height)].floatValue; + + RNNIconDrawer *iconDrawer = [[RNNIconDrawer alloc] init]; + icon = [iconDrawer draw:icon + imageColor:color + backgroundColor:backgroundColor + size:CGSizeMake(width, height) + cornerRadius:cornerRadius]; + } + [self setBackIndicatorImage:icon withColor:color]; title = title ? title : (previousNavigationItem.title ? previousNavigationItem.title : @""); diff --git a/src/interfaces/Options.ts b/src/interfaces/Options.ts index 05320abfcaa..22c6aa8b8d9 100644 --- a/src/interfaces/Options.ts +++ b/src/interfaces/Options.ts @@ -399,6 +399,10 @@ export interface OptionsTopBarBackButton { * values, in that case the closest one is chosen. */ fontWeight?: FontWeight; + /** + * Set icon background style + */ + iconBackground?: IconBackgroundOptions; /** * Set testID for reference in E2E tests */