react-native-navigation的迁移库

RNNNavigationButtons.m 10KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. #import "RNNNavigationButtons.h"
  2. #import "RNNUIBarButtonItem.h"
  3. #import <React/RCTConvert.h>
  4. #import "RCTHelpers.h"
  5. #import "UIImage+tint.h"
  6. #import "RNNComponentViewController.h"
  7. #import "UIImage+insets.h"
  8. #import "UIViewController+LayoutProtocol.h"
  9. #import "RNNFontAttributesCreator.h"
  10. #import "NSArray+utils.h"
  11. @interface RNNNavigationButtons()
  12. @property (weak, nonatomic) UIViewController<RNNLayoutProtocol>* viewController;
  13. @property (strong, nonatomic) RNNButtonOptions* defaultLeftButtonStyle;
  14. @property (strong, nonatomic) RNNButtonOptions* defaultRightButtonStyle;
  15. @property (strong, nonatomic) RNNReactComponentRegistry* componentRegistry;
  16. @end
  17. @implementation RNNNavigationButtons
  18. -(instancetype)initWithViewController:(UIViewController<RNNLayoutProtocol>*)viewController componentRegistry:(id)componentRegistry {
  19. self = [super init];
  20. self.viewController = viewController;
  21. self.componentRegistry = componentRegistry;
  22. return self;
  23. }
  24. - (void)applyLeftButtons:(NSArray *)leftButtons rightButtons:(NSArray *)rightButtons defaultLeftButtonStyle:(RNNButtonOptions *)defaultLeftButtonStyle defaultRightButtonStyle:(RNNButtonOptions *)defaultRightButtonStyle {
  25. _defaultLeftButtonStyle = defaultLeftButtonStyle;
  26. _defaultRightButtonStyle = defaultRightButtonStyle;
  27. if (leftButtons) {
  28. [self setButtons:leftButtons side:@"left" animated:NO defaultStyle:_defaultLeftButtonStyle insets:[self leftButtonInsets:_defaultLeftButtonStyle.iconInsets]];
  29. }
  30. if (rightButtons) {
  31. [self setButtons:rightButtons side:@"right" animated:NO defaultStyle:_defaultRightButtonStyle insets:[self rightButtonInsets:_defaultRightButtonStyle.iconInsets]];
  32. }
  33. }
  34. -(void)setButtons:(NSArray*)buttons side:(NSString*)side animated:(BOOL)animated defaultStyle:(RNNButtonOptions *)defaultStyle insets:(UIEdgeInsets)insets {
  35. NSMutableArray *barButtonItems = [NSMutableArray new];
  36. NSArray* resolvedButtons = [self resolveButtons:buttons];
  37. for (NSDictionary *button in resolvedButtons) {
  38. RNNUIBarButtonItem* barButtonItem = [self buildButton:button defaultStyle:defaultStyle insets:insets];
  39. if(barButtonItem) {
  40. [barButtonItems addObject:barButtonItem];
  41. }
  42. UIColor* color = [self color:[RCTConvert UIColor:button[@"color"]] defaultColor:[defaultStyle.color getWithDefaultValue:nil]];
  43. if (color) {
  44. self.viewController.navigationController.navigationBar.tintColor = color;
  45. }
  46. }
  47. if ([side isEqualToString:@"left"]) {
  48. [self clearPreviousButtonViews:barButtonItems oldButtons:self.viewController.navigationItem.leftBarButtonItems];
  49. [self.viewController.navigationItem setLeftBarButtonItems:barButtonItems animated:animated];
  50. }
  51. if ([side isEqualToString:@"right"]) {
  52. [self clearPreviousButtonViews:barButtonItems oldButtons:self.viewController.navigationItem.rightBarButtonItems];
  53. [self.viewController.navigationItem setRightBarButtonItems:barButtonItems animated:animated];
  54. }
  55. [self notifyButtonsDidAppear:barButtonItems];
  56. }
  57. - (NSArray *)currentButtons {
  58. NSArray* currentButtons = [self.viewController.navigationItem.leftBarButtonItems arrayByAddingObjectsFromArray:self.viewController.navigationItem.rightBarButtonItems];
  59. return currentButtons;
  60. }
  61. - (void)componentDidAppear {
  62. for (UIBarButtonItem* barButtonItem in [self currentButtons]) {
  63. if ([self isRNNUIBarButton:barButtonItem]) {
  64. [(RNNUIBarButtonItem *)barButtonItem notifyDidAppear];
  65. }
  66. }
  67. }
  68. - (void)componentDidDisappear {
  69. for (UIBarButtonItem* barButtonItem in [self currentButtons]) {
  70. if ([self isRNNUIBarButton:barButtonItem]) {
  71. [(RNNUIBarButtonItem *)barButtonItem notifyDidDisappear];
  72. }
  73. }
  74. }
  75. - (void)notifyButtonsDidAppear:(NSArray *)barButtonItems {
  76. for (UIBarButtonItem* barButtonItem in barButtonItems) {
  77. if ([self isRNNUIBarButton:barButtonItem]) {
  78. [(RNNUIBarButtonItem *)barButtonItem notifyDidAppear];
  79. }
  80. }
  81. }
  82. - (BOOL)isRNNUIBarButton:(UIBarButtonItem *)barButtonItem {
  83. return [barButtonItem isKindOfClass:[RNNUIBarButtonItem class]];
  84. }
  85. - (void)clearPreviousButtonViews:(NSArray<UIBarButtonItem *> *)newButtons oldButtons:(NSArray<UIBarButtonItem *> *)oldButtons {
  86. NSArray<UIBarButtonItem *>* removedButtons = [oldButtons difference:newButtons withPropertyName:@"customView"];
  87. for (UIBarButtonItem* buttonItem in removedButtons) {
  88. RNNReactView* reactView = buttonItem.customView;
  89. if ([reactView isKindOfClass:[RNNReactView class]]) {
  90. [reactView componentDidDisappear];
  91. [_componentRegistry removeChildComponent:reactView.componentId];
  92. }
  93. }
  94. }
  95. - (NSArray *)resolveButtons:(id)buttons {
  96. if ([buttons isKindOfClass:[NSArray class]]) {
  97. return buttons;
  98. } else {
  99. return @[buttons];
  100. }
  101. }
  102. -(RNNUIBarButtonItem*)buildButton: (NSDictionary*)dictionary defaultStyle:(RNNButtonOptions *)defaultStyle insets:(UIEdgeInsets)insets {
  103. NSString* buttonId = dictionary[@"id"];
  104. NSString* title = [self getValue:dictionary[@"text"] withDefault:[defaultStyle.text getWithDefaultValue:nil]];
  105. NSDictionary* component = dictionary[@"component"];
  106. NSString* systemItemName = dictionary[@"systemItem"];
  107. UIColor* color = [self color:[RCTConvert UIColor:dictionary[@"color"]] defaultColor:[defaultStyle.color getWithDefaultValue:nil]];
  108. UIColor* disabledColor = [self color:[RCTConvert UIColor:dictionary[@"disabledColor"]] defaultColor:[defaultStyle.disabledColor getWithDefaultValue:nil]];
  109. if (!buttonId) {
  110. @throw [NSException exceptionWithName:@"NSInvalidArgumentException" reason:[@"button id is not specified " stringByAppendingString:title] userInfo:nil];
  111. }
  112. UIImage* defaultIcon = [defaultStyle.icon getWithDefaultValue:nil];
  113. UIImage* iconImage = [self getValue:dictionary[@"icon"] withDefault:defaultIcon];
  114. if (![iconImage isKindOfClass:[UIImage class]]) {
  115. iconImage = [RCTConvert UIImage:iconImage];
  116. }
  117. if (iconImage) {
  118. iconImage = [iconImage imageWithInsets:insets];
  119. if (color) {
  120. iconImage = [iconImage withTintColor:color];
  121. }
  122. }
  123. RNNUIBarButtonItem *barButtonItem;
  124. if (component) {
  125. RNNComponentOptions* componentOptions = [RNNComponentOptions new];
  126. componentOptions.componentId = [[Text alloc] initWithValue:component[@"componentId"]];
  127. componentOptions.name = [[Text alloc] initWithValue:component[@"name"]];
  128. RNNReactButtonView *view = [_componentRegistry createComponentIfNotExists:componentOptions parentComponentId:self.viewController.layoutInfo.componentId componentType:RNNComponentTypeTopBarButton reactViewReadyBlock:nil];
  129. barButtonItem = [[RNNUIBarButtonItem alloc] init:buttonId withCustomView:view];
  130. } else if (iconImage) {
  131. barButtonItem = [[RNNUIBarButtonItem alloc] init:buttonId withIcon:iconImage];
  132. } else if (title) {
  133. barButtonItem = [[RNNUIBarButtonItem alloc] init:buttonId withTitle:title];
  134. NSMutableDictionary *buttonTextAttributes = [RCTHelpers textAttributesFromDictionary:dictionary withPrefix:@"button"];
  135. if (buttonTextAttributes.allKeys.count > 0) {
  136. [barButtonItem setTitleTextAttributes:buttonTextAttributes forState:UIControlStateNormal];
  137. }
  138. } else if (systemItemName) {
  139. barButtonItem = [[RNNUIBarButtonItem alloc] init:buttonId withSystemItem:systemItemName];
  140. } else {
  141. return nil;
  142. }
  143. barButtonItem.accessibilityLabel = dictionary[@"accessibilityLabel"];
  144. barButtonItem.target = self.viewController;
  145. barButtonItem.action = @selector(onButtonPress:);
  146. NSNumber *enabled = [self getValue:dictionary[@"enabled"] withDefault:defaultStyle.enabled.getValue];
  147. BOOL enabledBool = enabled ? [enabled boolValue] : YES;
  148. [barButtonItem setEnabled:enabledBool];
  149. NSMutableDictionary* textAttributes = [NSMutableDictionary dictionaryWithDictionary:[RNNFontAttributesCreator createWithFontFamily:dictionary[@"fontFamily"] ?: [defaultStyle.fontFamily getWithDefaultValue:nil] fontSize:dictionary[@"fontSize"] defaultFontSize:[defaultStyle.fontSize getWithDefaultValue:@(17)] fontWeight:dictionary[@"fontWeight"] color:nil defaultColor:nil]];
  150. NSMutableDictionary* disabledTextAttributes = [NSMutableDictionary dictionaryWithDictionary:[RNNFontAttributesCreator createWithFontFamily:dictionary[@"fontFamily"] ?: [defaultStyle.fontFamily getWithDefaultValue:nil] fontSize:dictionary[@"fontSize"] defaultFontSize:[defaultStyle.fontSize getWithDefaultValue:@(17)] fontWeight:dictionary[@"fontWeight"] color:nil defaultColor:nil]];
  151. if (!enabledBool && disabledColor) {
  152. color = disabledColor;
  153. [disabledTextAttributes setObject:disabledColor forKey:NSForegroundColorAttributeName];
  154. }
  155. if (color) {
  156. [textAttributes setObject:color forKey:NSForegroundColorAttributeName];
  157. [barButtonItem setImage:[[iconImage withTintColor:color] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]];
  158. barButtonItem.tintColor = color;
  159. }
  160. [barButtonItem setTitleTextAttributes:textAttributes forState:UIControlStateNormal];
  161. [barButtonItem setTitleTextAttributes:textAttributes forState:UIControlStateHighlighted];
  162. [barButtonItem setTitleTextAttributes:disabledTextAttributes forState:UIControlStateDisabled];
  163. NSString *testID = dictionary[@"testID"];
  164. if (testID)
  165. {
  166. barButtonItem.accessibilityIdentifier = testID;
  167. }
  168. return barButtonItem;
  169. }
  170. - (UIColor *)color:(UIColor *)color defaultColor:(UIColor *)defaultColor {
  171. if (color) {
  172. return color;
  173. } else if (defaultColor) {
  174. return defaultColor;
  175. }
  176. return nil;
  177. }
  178. - (id)getValue:(id)value withDefault:(id)defaultValue {
  179. return value ? value : defaultValue;
  180. }
  181. - (UIEdgeInsets)leftButtonInsets:(RNNInsetsOptions *)defaultInsets {
  182. return UIEdgeInsetsMake([defaultInsets.top getWithDefaultValue:0],
  183. [defaultInsets.left getWithDefaultValue:0],
  184. [defaultInsets.bottom getWithDefaultValue:0],
  185. [defaultInsets.right getWithDefaultValue:15]);
  186. }
  187. - (UIEdgeInsets)rightButtonInsets:(RNNInsetsOptions *)defaultInsets {
  188. return UIEdgeInsetsMake([defaultInsets.top getWithDefaultValue:0],
  189. [defaultInsets.left getWithDefaultValue:15],
  190. [defaultInsets.bottom getWithDefaultValue:0],
  191. [defaultInsets.right getWithDefaultValue:0]);
  192. }
  193. @end