YCXMenu.m 41 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267
  1. //
  2. // YCXMenu.m
  3. // YCXMenuDemo_ObjC
  4. //
  5. // Created by 牛萌 on 15/5/6.
  6. // Copyright (c) 2015年 NiuMeng. All rights reserved.
  7. //
  8. #import "YCXMenu.h"
  9. #import <QuartzCore/QuartzCore.h>
  10. NSString * const YCXMenuWillAppearNotification = @"YCXMenuWillAppearNotification";
  11. NSString * const YCXMenuDidAppearNotification = @"YCXMenuDidAppearNotification";
  12. NSString * const YCXMenuWillDisappearNotification = @"YCXMenuWillDisappearNotification";
  13. NSString * const YCXMenuDidDisappearNotification = @"YCXMenuDidDisappearNotification";
  14. #define kArrowSize 10.0f //!< 箭头尺寸
  15. #define kCornerRadius 2.0f //!< 圆角
  16. #define kTintColor [UIColor colorWithRed:0.267 green:0.303 blue:0.335 alpha:1] //!< 主题颜色
  17. #define kSelectedColor [UIColor colorWithRed:0.059 green:0.353 blue:0.839 alpha:1.0f]
  18. #define kTitleFont [UIFont systemFontOfSize:16.0]
  19. #define kSeparatorInsetLeft 16
  20. #define kSeparatorInsetRight 0
  21. #define kSeparatorHeight 1
  22. #define kSeparatorColor [UIColor colorWithRed:0.44 green:0.44 blue:0.44 alpha:1]
  23. #define kMenuViewInsetTop 0
  24. #define kMenuViewInsetBottom 0
  25. const CGFloat kMenuItemMarginY = 6.f;
  26. /// 背景色
  27. static UIColor *gTintColor;
  28. /// 箭头尺寸
  29. static CGFloat gArrowSize = kArrowSize;
  30. /// 圆角
  31. CGFloat gCornerRadius = kCornerRadius;
  32. /// 字体
  33. static UIFont *gTitleFont;
  34. /// 背景色效果
  35. static YCXMenuBackgrounColorEffect gBackgroundColorEffect = YCXMenuBackgrounColorEffectSolid;
  36. /// 是否显示阴影
  37. static BOOL gHasShadow = YES;
  38. /// 选中颜色(默认蓝色)
  39. static UIColor *gSelectedColor;
  40. /// 分割线颜色
  41. static UIColor *gSeparatorColor;
  42. /// 菜单原始的垂直边距值
  43. static CGFloat gMenuItemMarginY = kMenuItemMarginY;
  44. //@property (nonatomic) UIEdgeInsets separatorInset NS_AVAILABLE_IOS(7_0) UI_APPEARANCE_SELECTOR; // allows customization of the frame of cell separators
  45. typedef enum {
  46. YCXMenuViewArrowDirectionNone,
  47. YCXMenuViewArrowDirectionUp,
  48. YCXMenuViewArrowDirectionDown,
  49. YCXMenuViewArrowDirectionLeft,
  50. YCXMenuViewArrowDirectionRight,
  51. } YCXMenuViewArrowDirection;
  52. @interface YCXMenuView : UIView
  53. /**
  54. * @method
  55. * @brief 隐藏Menu
  56. *
  57. * @param animated 是否有动画
  58. */
  59. - (void)dismissMenu:(BOOL)animated;
  60. @end
  61. @interface YCXMenuOverlay : UIView
  62. @end
  63. @interface YCXMenu ()
  64. + (instancetype)sharedMenu;
  65. /// 视图当前是否显示
  66. @property(nonatomic, assign) BOOL isShow;
  67. /// 重置属性
  68. + (void)reset;
  69. @end
  70. #pragma mark - YCXMenuOverlay
  71. @implementation YCXMenuOverlay
  72. #pragma mark System Methods
  73. - (id)initWithFrame:(CGRect)frame {
  74. self = [super initWithFrame:frame];
  75. if (self) {
  76. self.backgroundColor = [UIColor clearColor];
  77. self.opaque = NO;
  78. UITapGestureRecognizer *gestureRecognizer;
  79. gestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(singleTap:)];
  80. [self addGestureRecognizer:gestureRecognizer];
  81. }
  82. return self;
  83. }
  84. - (void)singleTap:(UITapGestureRecognizer *)recognizer {
  85. for (UIView *view in self.subviews) {
  86. if ([view isKindOfClass:[YCXMenuView class]] && [view respondsToSelector:@selector(dismissMenu:)]) {
  87. [view performSelector:@selector(dismissMenu:) withObject:@(YES)];
  88. }
  89. }
  90. }
  91. @end
  92. #pragma mark - YCXMenuView
  93. @implementation YCXMenuView {
  94. YCXMenuViewArrowDirection _arrowDirection;
  95. CGFloat _arrowPosition;
  96. UIView *_contentView;
  97. NSArray *_menuItems;
  98. YCXMenuSelectedItem _selectedItem;
  99. BOOL hasImg;
  100. }
  101. #pragma mark System Methods
  102. - (id)init {
  103. self = [super initWithFrame:CGRectZero];
  104. if(self) {
  105. self.backgroundColor = [UIColor clearColor];
  106. self.opaque = YES;
  107. self.alpha = 0;
  108. if ([YCXMenu hasShadow]) {
  109. self.layer.shadowOpacity = 0.5;
  110. self.layer.shadowColor = [MOTools colorWithHexString:@"#666666" alpha:1.0].CGColor;
  111. self.layer.shadowOffset = CGSizeMake(0.5, 0.5);
  112. self.layer.shadowRadius = 1;
  113. }
  114. }
  115. return self;
  116. }
  117. - (void)setupFrameInView:(UIView *)view fromRect:(CGRect)fromRect {
  118. const CGSize contentSize = _contentView.frame.size;
  119. const CGFloat outerWidth = view.bounds.size.width;
  120. const CGFloat outerHeight = view.bounds.size.height;
  121. const CGFloat rectX0 = fromRect.origin.x;
  122. const CGFloat rectX1 = fromRect.origin.x + fromRect.size.width;
  123. const CGFloat rectXM = fromRect.origin.x + fromRect.size.width * 0.5f;
  124. const CGFloat rectY0 = fromRect.origin.y;
  125. const CGFloat rectY1 = fromRect.origin.y + fromRect.size.height;
  126. const CGFloat rectYM = fromRect.origin.y + fromRect.size.height * 0.5f;;
  127. const CGFloat widthPlusArrow = contentSize.width + [YCXMenu arrowSize];
  128. const CGFloat heightPlusArrow = contentSize.height + [YCXMenu arrowSize];
  129. const CGFloat widthHalf = contentSize.width * 0.5f;
  130. const CGFloat heightHalf = contentSize.height * 0.5f;
  131. const CGFloat kMargin = 5.f;
  132. if (heightPlusArrow < (outerHeight - rectY1)) {
  133. _arrowDirection = YCXMenuViewArrowDirectionUp;
  134. CGPoint point = (CGPoint){
  135. rectXM - widthHalf,
  136. rectY1
  137. };
  138. if (point.x < kMargin)
  139. point.x = kMargin;
  140. if ((point.x + contentSize.width + kMargin) > outerWidth)
  141. point.x = outerWidth - contentSize.width - kMargin;
  142. _arrowPosition = rectXM - point.x;
  143. _contentView.frame = (CGRect){0, [YCXMenu arrowSize], contentSize};
  144. self.frame = (CGRect) {
  145. point,
  146. contentSize.width,
  147. contentSize.height + [YCXMenu arrowSize]
  148. };
  149. } else if (heightPlusArrow < rectY0) {
  150. _arrowDirection = YCXMenuViewArrowDirectionDown;
  151. CGPoint point = (CGPoint){
  152. rectXM - widthHalf,
  153. rectY0 - heightPlusArrow
  154. };
  155. if (point.x < kMargin)
  156. point.x = kMargin;
  157. if ((point.x + contentSize.width + kMargin) > outerWidth)
  158. point.x = outerWidth - contentSize.width - kMargin;
  159. _arrowPosition = rectXM - point.x;
  160. _contentView.frame = (CGRect){CGPointZero, contentSize};
  161. self.frame = (CGRect) {
  162. point,
  163. contentSize.width,
  164. contentSize.height + [YCXMenu arrowSize]
  165. };
  166. } else if (widthPlusArrow < (outerWidth - rectX1)) {
  167. _arrowDirection = YCXMenuViewArrowDirectionLeft;
  168. CGPoint point = (CGPoint){
  169. rectX1,
  170. rectYM - heightHalf
  171. };
  172. if (point.y < kMargin)
  173. point.y = kMargin;
  174. if ((point.y + contentSize.height + kMargin) > outerHeight)
  175. point.y = outerHeight - contentSize.height - kMargin;
  176. _arrowPosition = rectYM - point.y;
  177. _contentView.frame = (CGRect){[YCXMenu arrowSize], 0, contentSize};
  178. self.frame = (CGRect) {
  179. point,
  180. contentSize.width + [YCXMenu arrowSize],
  181. contentSize.height
  182. };
  183. } else if (widthPlusArrow < rectX0) {
  184. _arrowDirection = YCXMenuViewArrowDirectionRight;
  185. CGPoint point = (CGPoint){
  186. rectX0 - widthPlusArrow,
  187. rectYM - heightHalf
  188. };
  189. if (point.y < kMargin)
  190. point.y = kMargin;
  191. if ((point.y + contentSize.height + 5) > outerHeight)
  192. point.y = outerHeight - contentSize.height - kMargin;
  193. _arrowPosition = rectYM - point.y;
  194. _contentView.frame = (CGRect){CGPointZero, contentSize};
  195. self.frame = (CGRect) {
  196. point,
  197. contentSize.width + [YCXMenu arrowSize],
  198. contentSize.height
  199. };
  200. } else {
  201. _arrowDirection = YCXMenuViewArrowDirectionNone;
  202. self.frame = (CGRect) {
  203. (outerWidth - contentSize.width) * 0.5f,
  204. (outerHeight - contentSize.height) * 0.5f,
  205. contentSize,
  206. };
  207. }
  208. }
  209. - (void)showMenuInView:(UIView *)view fromRect:(CGRect)rect menuItems:(NSArray *)menuItems selected:(YCXMenuSelectedItem)selectedItem {
  210. _menuItems = menuItems;
  211. _selectedItem = selectedItem;
  212. _contentView = [self mkContentView];
  213. [self addSubview:_contentView];
  214. [self setupFrameInView:view fromRect:rect];
  215. YCXMenuOverlay *overlay = [[YCXMenuOverlay alloc] initWithFrame:view.bounds];
  216. [overlay addSubview:self];
  217. [view addSubview:overlay];
  218. //mask
  219. UIView *mask = [[UIView alloc] initWithFrame:view.bounds];
  220. mask.backgroundColor = [UIColor clearColor];
  221. mask.userInteractionEnabled = NO;
  222. mask.tag = 9899;
  223. [overlay insertSubview:mask belowSubview:self];
  224. _contentView.hidden = YES;
  225. const CGRect toFrame = self.frame;
  226. self.frame = (CGRect){self.arrowPoint, 1, 1};
  227. [[NSNotificationCenter defaultCenter] postNotificationName:YCXMenuWillAppearNotification object:nil];
  228. [UIView animateWithDuration:0.2 animations:^(void) {
  229. self.alpha = 1.0f;
  230. self.frame = toFrame;
  231. mask.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.2];
  232. } completion:^(BOOL completed) {
  233. _contentView.hidden = NO;
  234. [[NSNotificationCenter defaultCenter] postNotificationName:YCXMenuDidAppearNotification object:nil];
  235. }];
  236. }
  237. - (void)showMenuInView:(UIView *)view fromRect:(CGRect)rect menuItems:(NSArray *)menuItems itemWidth:(CGFloat)width selected:(YCXMenuSelectedItem)selectedItem
  238. {
  239. _menuItems = menuItems;
  240. _selectedItem = selectedItem;
  241. _contentView = [self mkContentView:width];
  242. [self addSubview:_contentView];
  243. [self setupFrameInView:view fromRect:rect];
  244. YCXMenuOverlay *overlay = [[YCXMenuOverlay alloc] initWithFrame:view.bounds];
  245. [overlay addSubview:self];
  246. [view addSubview:overlay];
  247. //mask
  248. UIView *mask = [[UIView alloc] initWithFrame:view.bounds];
  249. mask.backgroundColor = [UIColor clearColor];
  250. mask.userInteractionEnabled = NO;
  251. mask.tag = 9899;
  252. [overlay insertSubview:mask belowSubview:self];
  253. _contentView.hidden = YES;
  254. const CGRect toFrame = self.frame;
  255. self.frame = (CGRect){self.arrowPoint, 1, 1};
  256. [[NSNotificationCenter defaultCenter] postNotificationName:YCXMenuWillAppearNotification object:nil];
  257. [UIView animateWithDuration:0.2 animations:^(void) {
  258. self.alpha = 1.0f;
  259. self.frame = toFrame;
  260. mask.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.2];
  261. } completion:^(BOOL completed) {
  262. _contentView.hidden = NO;
  263. [[NSNotificationCenter defaultCenter] postNotificationName:YCXMenuDidAppearNotification object:nil];
  264. }];
  265. }
  266. - (void)dismissMenu:(BOOL)animated {
  267. if (self.superview) {
  268. [[NSNotificationCenter defaultCenter] postNotificationName:YCXMenuWillDisappearNotification object:nil];
  269. __weak typeof(self) weakSelf = self;
  270. void (^removeView)(void) = ^(void) {
  271. if ([weakSelf.superview isKindOfClass:[YCXMenuOverlay class]])
  272. [weakSelf.superview removeFromSuperview];
  273. [weakSelf removeFromSuperview];
  274. [[NSNotificationCenter defaultCenter] postNotificationName:YCXMenuDidDisappearNotification object:nil];
  275. };
  276. UIView *mask = [self.superview viewWithTag:9899];
  277. if (animated) {
  278. _contentView.hidden = YES;
  279. const CGRect toFrame = (CGRect){self.arrowPoint, 1, 1};
  280. [UIView animateWithDuration:0.2 animations:^(void) {
  281. self.alpha = 0;
  282. self.frame = toFrame;
  283. mask.backgroundColor = [UIColor clearColor];
  284. } completion:^(BOOL finished) {
  285. removeView();
  286. }];
  287. }
  288. else {
  289. removeView();
  290. }
  291. }
  292. [YCXMenu sharedMenu].isShow = NO;
  293. }
  294. - (void)performAction:(id)sender {
  295. [self dismissMenu:YES];
  296. UIButton *button = (UIButton *)sender;
  297. if (_menuItems.count >= button.tag) {
  298. YCXMenuItem *menuItem = _menuItems[button.tag];
  299. [menuItem performAction];
  300. if (_selectedItem) {
  301. _selectedItem(button.tag, menuItem);
  302. }
  303. }
  304. }
  305. - (UIView *)mkContentView {
  306. for (UIView *v in self.subviews) {
  307. [v removeFromSuperview];
  308. }
  309. if (!_menuItems.count)
  310. return nil;
  311. hasImg = YES;
  312. const CGFloat kMinMenuItemHeight = 32.f;
  313. // const CGFloat kMinMenuItemWidth = 32.f;//默认值
  314. const CGFloat kMinMenuItemWidth = 180.0;
  315. const CGFloat kMarginX = 8.f;
  316. UIFont *titleFont = [YCXMenu titleFont];
  317. CGFloat maxImageWidth = 0;
  318. CGFloat maxItemHeight = 0;
  319. CGFloat maxItemWidth = 0;
  320. for (YCXMenuItem *menuItem in _menuItems) {
  321. const CGSize imageSize = menuItem.image.size;
  322. if (menuItem.imageUrl && ![menuItem.imageUrl isEqualToString:@""]) {//如果是网络图片的情况
  323. maxImageWidth = 16.0;//16.0为常用固定图片大小
  324. }
  325. else{
  326. if (imageSize.width > maxImageWidth)
  327. maxImageWidth = imageSize.width;
  328. }
  329. }
  330. if (maxImageWidth) {
  331. maxImageWidth += kMarginX;
  332. }
  333. for (YCXMenuItem *menuItem in _menuItems) {
  334. const CGSize titleSize = [menuItem.title sizeWithAttributes:@{NSFontAttributeName:menuItem.titleFont?menuItem.titleFont:titleFont}];
  335. //const CGSize titleSize = [menuItem.title sizeWithFont:titleFont];
  336. const CGSize imageSize = (menuItem.imageUrl && ![menuItem.imageUrl isEqualToString:@""])?CGSizeMake(16.0, 16.0):menuItem.image.size;
  337. const CGFloat itemHeight = MAX(titleSize.height, imageSize.height) + [YCXMenu menuItemMarginY] * 2;
  338. const CGFloat itemWidth = ((!menuItem.enabled && !menuItem.image) ? titleSize.width : maxImageWidth + titleSize.width) + kMarginX * 4;
  339. if (itemHeight > maxItemHeight)
  340. maxItemHeight = itemHeight;
  341. if (itemWidth > maxItemWidth){
  342. // //TODO
  343. // if (itemWidth > 226) {
  344. // maxItemWidth = itemWidth+25;
  345. // }else{
  346. maxItemWidth = itemWidth;
  347. // }
  348. }
  349. }
  350. maxItemWidth = MAX(maxItemWidth, kMinMenuItemWidth);
  351. maxItemHeight = MAX(maxItemHeight, kMinMenuItemHeight);
  352. const CGFloat titleX = kMarginX * 3 + maxImageWidth;
  353. const CGFloat titleWidth = maxItemWidth - titleX - kMarginX * 2;
  354. UIImage *selectedImage = [YCXMenuView selectedImage:(CGSize){maxItemWidth, maxItemHeight}];
  355. UIImage *gradientLine = [YCXMenuView gradientLineWithColor:[YCXMenu separatorColor]];
  356. UIView *contentView = [[UIView alloc] initWithFrame:CGRectZero];
  357. contentView.autoresizingMask = UIViewAutoresizingNone;
  358. contentView.backgroundColor = [UIColor clearColor];
  359. contentView.opaque = NO;
  360. contentView.layer.cornerRadius = gCornerRadius;
  361. [contentView setClipsToBounds:YES];
  362. CGFloat itemY = kMenuViewInsetTop;
  363. NSUInteger itemNum = 0;
  364. for (YCXMenuItem *menuItem in _menuItems) {
  365. if (menuItem.imageUrl && ![menuItem.imageUrl isEqualToString:@""]) {
  366. hasImg = YES;
  367. }
  368. else{
  369. if (menuItem.image == nil) {
  370. hasImg = NO;
  371. }
  372. }
  373. const CGRect itemFrame = (CGRect){0, itemY, maxItemWidth, maxItemHeight};
  374. UIView *itemView = [[UIView alloc] initWithFrame:itemFrame];
  375. itemView.autoresizingMask = UIViewAutoresizingNone;
  376. itemView.backgroundColor = [UIColor clearColor];
  377. itemView.opaque = NO;
  378. [contentView addSubview:itemView];
  379. if (menuItem.enabled) {
  380. UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
  381. button.tag = itemNum;
  382. button.frame = CGRectMake(0, 0, itemView.frame.size.width, itemView.frame.size.height);
  383. button.enabled = menuItem.enabled;
  384. button.backgroundColor = [UIColor clearColor];
  385. button.opaque = NO;
  386. button.autoresizingMask = UIViewAutoresizingNone;
  387. [button addTarget:self
  388. action:@selector(performAction:)
  389. forControlEvents:UIControlEventTouchUpInside];
  390. [button setBackgroundImage:selectedImage forState:UIControlStateHighlighted];
  391. [itemView addSubview:button];
  392. }
  393. if (menuItem.title.length) {
  394. CGRect titleFrame;
  395. if (!menuItem.enabled && !menuItem.image) {
  396. titleFrame = (CGRect){kMarginX * 2,[YCXMenu menuItemMarginY],maxItemWidth - kMarginX * 4,maxItemHeight - [YCXMenu menuItemMarginY] * 2
  397. };
  398. } else {
  399. titleFrame = (CGRect){hasImg?titleX:titleX-maxImageWidth,[YCXMenu menuItemMarginY],titleWidth,maxItemHeight - [YCXMenu menuItemMarginY] * 2
  400. };
  401. }
  402. //标题
  403. UILabel *titleLabel = [[UILabel alloc] initWithFrame:titleFrame];
  404. titleLabel.text = menuItem.title;
  405. titleLabel.font = menuItem.titleFont ? menuItem.titleFont : titleFont;
  406. titleLabel.textAlignment = menuItem.alignment;
  407. if (menuItem.tag == 10) {
  408. titleLabel.textColor = UIColorFromHex(0xE67720);
  409. }else{
  410. titleLabel.textColor = [MOTools colorWithHexString:@"#333333" alpha:1.0];
  411. }
  412. titleLabel.backgroundColor = [UIColor clearColor];
  413. titleLabel.autoresizingMask = UIViewAutoresizingNone;
  414. [itemView addSubview:titleLabel];
  415. }
  416. //图片
  417. if (menuItem.imageUrl && ![menuItem.imageUrl isEqualToString:@""]) {
  418. const CGRect imageFrame = {kMarginX * 2, [YCXMenu menuItemMarginY], maxImageWidth, maxItemHeight - [YCXMenu menuItemMarginY] * 2};
  419. UIImageView *imageView = [[UIImageView alloc] initWithFrame:imageFrame];
  420. [imageView sd_setImageWithURL:[NSURL URLWithString:menuItem.imageUrl]];
  421. imageView.clipsToBounds = YES;
  422. imageView.contentMode = UIViewContentModeScaleAspectFit;
  423. imageView.autoresizingMask = UIViewAutoresizingNone;
  424. [itemView addSubview:imageView];
  425. }
  426. else{
  427. if (menuItem.image) {
  428. const CGRect imageFrame = {kMarginX * 2, [YCXMenu menuItemMarginY], maxImageWidth, maxItemHeight - [YCXMenu menuItemMarginY] * 2};
  429. UIImageView *imageView = [[UIImageView alloc] initWithFrame:imageFrame];
  430. imageView.image = menuItem.image;
  431. imageView.clipsToBounds = YES;
  432. imageView.contentMode = UIViewContentModeCenter;
  433. imageView.autoresizingMask = UIViewAutoresizingNone;
  434. [itemView addSubview:imageView];
  435. }
  436. }
  437. //分割线
  438. if (itemNum < _menuItems.count - 1) {
  439. UIImageView *gradientView = [[UIImageView alloc] initWithImage:gradientLine];
  440. gradientView.frame = (CGRect){kSeparatorInsetLeft, maxItemHeight, maxItemWidth - kSeparatorInsetLeft - kSeparatorInsetRight, kSeparatorHeight};
  441. gradientView.contentMode = UIViewContentModeScaleToFill;
  442. [itemView addSubview:gradientView];
  443. itemY += gradientView.frame.size.height;
  444. [itemView bringSubviewToFront:gradientView];
  445. }
  446. if (menuItem.showBadge) {
  447. UILabel *_itemLabel = [[UILabel alloc] initWithFrame:CGRectMake(maxItemWidth-17,maxItemHeight/2-5, 10, 10)];
  448. _itemLabel.backgroundColor = [UIColor redColor];
  449. _itemLabel.font = [UIFont systemFontOfSize:7];
  450. _itemLabel.text = @"";
  451. _itemLabel.textColor = [UIColor whiteColor];
  452. _itemLabel.textAlignment = NSTextAlignmentCenter;
  453. _itemLabel.layer.cornerRadius = 5;
  454. [_itemLabel.layer setMasksToBounds:YES];
  455. _itemLabel.hidden = NO;
  456. [itemView addSubview:_itemLabel];
  457. [itemView bringSubviewToFront:_itemLabel];
  458. }
  459. itemY += maxItemHeight;
  460. ++itemNum;
  461. }
  462. //小慧3.31.0UI整改,所有的下拉弹窗都是160宽,icon左边距16,icon与title边距为8
  463. // CGFloat width = hasImg?maxItemWidth:(maxItemWidth-maxImageWidth);
  464. CGFloat width = 160;
  465. contentView.frame = (CGRect){0, 0, width, itemY + kMenuViewInsetBottom};
  466. return contentView;
  467. }
  468. - (UIView *)mkContentView:(CGFloat)itemWidth
  469. {
  470. for (UIView *v in self.subviews) {
  471. [v removeFromSuperview];
  472. }
  473. if (!_menuItems.count)
  474. return nil;
  475. hasImg = YES;
  476. const CGFloat kMinMenuItemHeight = 32.f;
  477. // const CGFloat kMinMenuItemWidth = 32.f;//默认值
  478. const CGFloat kMinMenuItemWidth = 160.f;
  479. const CGFloat kMarginX = 8.f;
  480. UIFont *titleFont = [YCXMenu titleFont];
  481. CGFloat maxImageWidth = 0;
  482. CGFloat maxItemHeight = 0;
  483. CGFloat maxItemWidth = 0;
  484. for (YCXMenuItem *menuItem in _menuItems) {
  485. const CGSize imageSize = menuItem.image.size;
  486. if (menuItem.imageUrl && ![menuItem.imageUrl isEqualToString:@""]) {//如果是网络图片的情况
  487. maxImageWidth = 16.0;//16.0为常用固定图片大小
  488. }
  489. else{
  490. if (imageSize.width > maxImageWidth)
  491. maxImageWidth = imageSize.width;
  492. }
  493. }
  494. if (maxImageWidth) {
  495. maxImageWidth += kMarginX;
  496. }
  497. for (YCXMenuItem *menuItem in _menuItems) {
  498. const CGSize titleSize = [menuItem.title sizeWithAttributes:@{NSFontAttributeName:menuItem.titleFont?menuItem.titleFont:titleFont}];
  499. //const CGSize titleSize = [menuItem.title sizeWithFont:titleFont];
  500. const CGSize imageSize = (menuItem.imageUrl && ![menuItem.imageUrl isEqualToString:@""])?CGSizeMake(16.0, 16.0):menuItem.image.size;
  501. const CGFloat itemHeight = MAX(titleSize.height, imageSize.height) + [YCXMenu menuItemMarginY] * 2;
  502. const CGFloat itemWidth = ((!menuItem.enabled && !menuItem.image) ? titleSize.width : maxImageWidth + titleSize.width) + kMarginX * 4;
  503. if (itemHeight > maxItemHeight)
  504. maxItemHeight = itemHeight;
  505. if (itemWidth > maxItemWidth){
  506. // //TODO
  507. // if (itemWidth > 226) {
  508. // maxItemWidth = itemWidth+25;
  509. // }else{
  510. maxItemWidth = itemWidth;
  511. // }
  512. }
  513. }
  514. maxItemWidth = MAX(maxItemWidth, kMinMenuItemWidth);
  515. maxItemHeight = MAX(maxItemHeight, kMinMenuItemHeight);
  516. const CGFloat titleX = kMarginX * 3 + maxImageWidth;
  517. const CGFloat titleWidth = maxItemWidth - titleX - kMarginX * 2;
  518. UIImage *selectedImage = [YCXMenuView selectedImage:(CGSize){maxItemWidth, maxItemHeight}];
  519. UIImage *gradientLine = [YCXMenuView gradientLineWithColor:[YCXMenu separatorColor]];
  520. UIView *contentView = [[UIView alloc] initWithFrame:CGRectZero];
  521. contentView.autoresizingMask = UIViewAutoresizingNone;
  522. contentView.backgroundColor = [UIColor clearColor];
  523. contentView.opaque = NO;
  524. contentView.layer.cornerRadius = gCornerRadius;
  525. [contentView setClipsToBounds:YES];
  526. CGFloat itemY = kMenuViewInsetTop;
  527. NSUInteger itemNum = 0;
  528. for (YCXMenuItem *menuItem in _menuItems) {
  529. if (menuItem.imageUrl && ![menuItem.imageUrl isEqualToString:@""]) {
  530. hasImg = YES;
  531. }
  532. else{
  533. if (menuItem.image == nil) {
  534. hasImg = NO;
  535. }
  536. }
  537. const CGRect itemFrame = (CGRect){0, itemY, maxItemWidth, maxItemHeight};
  538. UIView *itemView = [[UIView alloc] initWithFrame:itemFrame];
  539. itemView.autoresizingMask = UIViewAutoresizingNone;
  540. itemView.backgroundColor = [UIColor clearColor];
  541. itemView.opaque = NO;
  542. [contentView addSubview:itemView];
  543. if (menuItem.enabled) {
  544. UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
  545. button.tag = itemNum;
  546. button.frame = CGRectMake(0, 0, itemView.frame.size.width, itemView.frame.size.height);
  547. button.enabled = menuItem.enabled;
  548. button.backgroundColor = [UIColor clearColor];
  549. button.opaque = NO;
  550. button.autoresizingMask = UIViewAutoresizingNone;
  551. [button addTarget:self
  552. action:@selector(performAction:)
  553. forControlEvents:UIControlEventTouchUpInside];
  554. [button setBackgroundImage:selectedImage forState:UIControlStateHighlighted];
  555. [itemView addSubview:button];
  556. }
  557. if (menuItem.title.length) {
  558. CGRect titleFrame;
  559. if (!menuItem.enabled && !menuItem.image) {
  560. titleFrame = (CGRect){kMarginX * 2,[YCXMenu menuItemMarginY],maxItemWidth - kMarginX * 4,maxItemHeight - [YCXMenu menuItemMarginY] * 2
  561. };
  562. } else {
  563. titleFrame = (CGRect){hasImg?titleX:titleX-maxImageWidth,[YCXMenu menuItemMarginY],titleWidth,maxItemHeight - [YCXMenu menuItemMarginY] * 2
  564. };
  565. }
  566. //标题
  567. UILabel *titleLabel = [[UILabel alloc] initWithFrame:titleFrame];
  568. titleLabel.text = menuItem.title;
  569. titleLabel.font = menuItem.titleFont ? menuItem.titleFont : titleFont;
  570. titleLabel.textAlignment = menuItem.alignment;
  571. if (menuItem.tag == 10) {
  572. titleLabel.textColor = UIColorFromHex(0xE67720);
  573. }else{
  574. titleLabel.textColor = [MOTools colorWithHexString:@"#333333" alpha:1.0];
  575. }
  576. titleLabel.backgroundColor = [UIColor clearColor];
  577. titleLabel.autoresizingMask = UIViewAutoresizingNone;
  578. [itemView addSubview:titleLabel];
  579. }
  580. //图片
  581. if (menuItem.imageUrl && ![menuItem.imageUrl isEqualToString:@""]) {
  582. const CGRect imageFrame = {kMarginX * 2, [YCXMenu menuItemMarginY], maxImageWidth, maxItemHeight - [YCXMenu menuItemMarginY] * 2};
  583. UIImageView *imageView = [[UIImageView alloc] initWithFrame:imageFrame];
  584. [imageView sd_setImageWithURL:[NSURL URLWithString:menuItem.imageUrl]];
  585. imageView.clipsToBounds = YES;
  586. imageView.contentMode = UIViewContentModeScaleAspectFit;
  587. imageView.autoresizingMask = UIViewAutoresizingNone;
  588. [itemView addSubview:imageView];
  589. }
  590. else{
  591. if (menuItem.image) {
  592. const CGRect imageFrame = {kMarginX * 2, [YCXMenu menuItemMarginY], maxImageWidth, maxItemHeight - [YCXMenu menuItemMarginY] * 2};
  593. UIImageView *imageView = [[UIImageView alloc] initWithFrame:imageFrame];
  594. imageView.image = menuItem.image;
  595. imageView.clipsToBounds = YES;
  596. imageView.contentMode = UIViewContentModeCenter;
  597. imageView.autoresizingMask = UIViewAutoresizingNone;
  598. [itemView addSubview:imageView];
  599. }
  600. }
  601. //分割线
  602. if (itemNum < _menuItems.count - 1) {
  603. UIImageView *gradientView = [[UIImageView alloc] initWithImage:gradientLine];
  604. gradientView.frame = (CGRect){kSeparatorInsetLeft, maxItemHeight, maxItemWidth - kSeparatorInsetLeft - kSeparatorInsetRight, kSeparatorHeight};
  605. gradientView.contentMode = UIViewContentModeScaleToFill;
  606. [itemView addSubview:gradientView];
  607. itemY += gradientView.frame.size.height;
  608. [itemView bringSubviewToFront:gradientView];
  609. }
  610. if (menuItem.showBadge) {
  611. UILabel *_itemLabel = [[UILabel alloc] initWithFrame:CGRectMake(maxItemWidth-17,maxItemHeight/2-5, 10, 10)];
  612. _itemLabel.backgroundColor = [UIColor redColor];
  613. _itemLabel.font = [UIFont systemFontOfSize:7];
  614. _itemLabel.text = @"";
  615. _itemLabel.textColor = [UIColor whiteColor];
  616. _itemLabel.textAlignment = NSTextAlignmentCenter;
  617. _itemLabel.layer.cornerRadius = 5;
  618. [_itemLabel.layer setMasksToBounds:YES];
  619. _itemLabel.hidden = NO;
  620. [itemView addSubview:_itemLabel];
  621. [itemView bringSubviewToFront:_itemLabel];
  622. }
  623. itemY += maxItemHeight;
  624. ++itemNum;
  625. }
  626. //如果参数有值,优先使用参数
  627. CGFloat width = itemWidth ? : 160;
  628. contentView.frame = (CGRect){0, 0, width, itemY + kMenuViewInsetBottom};
  629. return contentView;
  630. }
  631. - (CGPoint)arrowPoint {
  632. CGPoint point;
  633. if (_arrowDirection == YCXMenuViewArrowDirectionUp) {
  634. point = (CGPoint){ CGRectGetMinX(self.frame) + _arrowPosition, CGRectGetMinY(self.frame) };
  635. } else if (_arrowDirection == YCXMenuViewArrowDirectionDown) {
  636. point = (CGPoint){ CGRectGetMinX(self.frame) + _arrowPosition, CGRectGetMaxY(self.frame) };
  637. } else if (_arrowDirection == YCXMenuViewArrowDirectionLeft) {
  638. point = (CGPoint){ CGRectGetMinX(self.frame), CGRectGetMinY(self.frame) + _arrowPosition };
  639. } else if (_arrowDirection == YCXMenuViewArrowDirectionRight) {
  640. point = (CGPoint){ CGRectGetMaxX(self.frame), CGRectGetMinY(self.frame) + _arrowPosition };
  641. } else {
  642. point = self.center;
  643. }
  644. return point;
  645. }
  646. /**
  647. * 渐变颜色的图片
  648. */
  649. + (UIImage *)selectedImage:(CGSize)size {
  650. UIGraphicsBeginImageContextWithOptions(size, NO, 0);
  651. CGContextRef context = UIGraphicsGetCurrentContext();
  652. CGContextSetFillColorWithColor(context, [[YCXMenu selectedColor] CGColor]);
  653. CGContextFillRect(context, CGRectMake(0, 0, size.width, size.height));
  654. UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
  655. UIGraphicsEndImageContext();
  656. return image;
  657. }
  658. + (UIImage *)gradientLineWithColor:(UIColor *)color {
  659. CGRect rect = CGRectMake(0.0f, 0.0f, 1.0f, 0.5f);
  660. UIGraphicsBeginImageContext(rect.size);
  661. CGContextRef context = UIGraphicsGetCurrentContext();
  662. CGContextSetFillColorWithColor(context, [color CGColor]);
  663. CGContextFillRect(context, rect);
  664. UIImage *theImage = UIGraphicsGetImageFromCurrentImageContext();
  665. UIGraphicsEndImageContext();
  666. return theImage;
  667. }
  668. /*
  669. + (UIImage *)gradientLine:(CGSize)size {
  670. const CGFloat locations[5] = {0,0.2,0.5,0.8,1};
  671. const CGFloat R = 0.44f, G = 0.44f, B = 0.44f;
  672. const CGFloat components[20] = {
  673. R,G,B,0.1,
  674. R,G,B,0.4,
  675. R,G,B,0.7,
  676. R,G,B,0.4,
  677. R,G,B,0.1
  678. };
  679. return [self gradientImageWithSize:size locations:locations components:components count:5];
  680. }
  681. + (UIImage *)gradientImageWithSize:(CGSize) size locations:(const CGFloat []) locations components:(const CGFloat []) components count:(NSUInteger)count {
  682. UIGraphicsBeginImageContextWithOptions(size, NO, 0);
  683. CGContextRef context = UIGraphicsGetCurrentContext();
  684. CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
  685. CGGradientRef colorGradient = CGGradientCreateWithColorComponents(colorSpace, components, locations, 2);
  686. CGColorSpaceRelease(colorSpace);
  687. CGContextDrawLinearGradient(context, colorGradient, (CGPoint){0, 0}, (CGPoint){size.width, 0}, 0);
  688. CGGradientRelease(colorGradient);
  689. UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
  690. UIGraphicsEndImageContext();
  691. return image;
  692. }
  693. */
  694. - (void)drawRect:(CGRect)rect {
  695. [self drawBackground:self.bounds inContext:UIGraphicsGetCurrentContext()];
  696. // 绘制完成后,初始静态变量值
  697. // 防止下次调用控件时沿用上一次设置的属性
  698. [YCXMenu reset];
  699. }
  700. - (void)drawBackground:(CGRect)frame inContext:(CGContextRef) context {
  701. CGFloat R0 = 0.0, G0 = 0.0, B0 = 0.0;
  702. CGFloat R1 = 0.0, G1 = 0.0, B1 = 0.0;
  703. UIColor *tintColor = [YCXMenu tintColor];
  704. if (tintColor) {
  705. CGFloat a;
  706. [tintColor getRed:&R0 green:&G0 blue:&B0 alpha:&a];
  707. [tintColor getRed:&R1 green:&G1 blue:&B1 alpha:&a];
  708. }
  709. if ([YCXMenu backgrounColorEffect] == YCXMenuBackgrounColorEffectGradient) {
  710. R1-=0.2;
  711. G1-=0.2;
  712. B1-=0.2;
  713. }
  714. CGFloat X0 = frame.origin.x;
  715. CGFloat X1 = frame.origin.x + frame.size.width;
  716. CGFloat Y0 = frame.origin.y;
  717. CGFloat Y1 = frame.origin.y + frame.size.height;
  718. // render arrow
  719. UIBezierPath *arrowPath = [UIBezierPath bezierPath];
  720. // fix the issue with gap of arrow's base if on the edge
  721. const CGFloat kEmbedFix = 3.f;
  722. if (_arrowDirection == YCXMenuViewArrowDirectionUp) {
  723. const CGFloat arrowXM = _arrowPosition;
  724. const CGFloat arrowX0 = arrowXM - [YCXMenu arrowSize]-3;
  725. const CGFloat arrowX1 = arrowXM + [YCXMenu arrowSize]+3;
  726. const CGFloat arrowY0 = Y0;
  727. const CGFloat arrowY1 = Y0 + [YCXMenu arrowSize] + kEmbedFix;
  728. [arrowPath moveToPoint: (CGPoint){arrowXM, arrowY0}];
  729. [arrowPath addLineToPoint: (CGPoint){arrowX1, arrowY1}];
  730. [arrowPath addLineToPoint: (CGPoint){arrowX0, arrowY1}];
  731. [arrowPath addLineToPoint: (CGPoint){arrowXM, arrowY0}];
  732. [[UIColor colorWithRed:R0 green:G0 blue:B0 alpha:1] set];
  733. Y0 += [YCXMenu arrowSize];
  734. } else if (_arrowDirection == YCXMenuViewArrowDirectionDown) {
  735. const CGFloat arrowXM = _arrowPosition;
  736. const CGFloat arrowX0 = arrowXM - [YCXMenu arrowSize];
  737. const CGFloat arrowX1 = arrowXM + [YCXMenu arrowSize];
  738. const CGFloat arrowY0 = Y1 - [YCXMenu arrowSize] - kEmbedFix;
  739. const CGFloat arrowY1 = Y1;
  740. [arrowPath moveToPoint: (CGPoint){arrowXM, arrowY1}];
  741. [arrowPath addLineToPoint: (CGPoint){arrowX1, arrowY0}];
  742. [arrowPath addLineToPoint: (CGPoint){arrowX0, arrowY0}];
  743. [arrowPath addLineToPoint: (CGPoint){arrowXM, arrowY1}];
  744. [[UIColor colorWithRed:R1 green:G1 blue:B1 alpha:1] set];
  745. Y1 -= [YCXMenu arrowSize];
  746. } else if (_arrowDirection == YCXMenuViewArrowDirectionLeft) {
  747. const CGFloat arrowYM = _arrowPosition;
  748. const CGFloat arrowX0 = X0;
  749. const CGFloat arrowX1 = X0 + [YCXMenu arrowSize] + kEmbedFix;
  750. const CGFloat arrowY0 = arrowYM - [YCXMenu arrowSize];;
  751. const CGFloat arrowY1 = arrowYM + [YCXMenu arrowSize];
  752. [arrowPath moveToPoint: (CGPoint){arrowX0, arrowYM}];
  753. [arrowPath addLineToPoint: (CGPoint){arrowX1, arrowY0}];
  754. [arrowPath addLineToPoint: (CGPoint){arrowX1, arrowY1}];
  755. [arrowPath addLineToPoint: (CGPoint){arrowX0, arrowYM}];
  756. [[UIColor colorWithRed:R0 green:G0 blue:B0 alpha:1] set];
  757. X0 += [YCXMenu arrowSize];
  758. } else if (_arrowDirection == YCXMenuViewArrowDirectionRight) {
  759. const CGFloat arrowYM = _arrowPosition;
  760. const CGFloat arrowX0 = X1;
  761. const CGFloat arrowX1 = X1 - [YCXMenu arrowSize] - kEmbedFix;
  762. const CGFloat arrowY0 = arrowYM - [YCXMenu arrowSize];;
  763. const CGFloat arrowY1 = arrowYM + [YCXMenu arrowSize];
  764. [arrowPath moveToPoint: (CGPoint){arrowX0, arrowYM}];
  765. [arrowPath addLineToPoint: (CGPoint){arrowX1, arrowY0}];
  766. [arrowPath addLineToPoint: (CGPoint){arrowX1, arrowY1}];
  767. [arrowPath addLineToPoint: (CGPoint){arrowX0, arrowYM}];
  768. [[UIColor colorWithRed:R1 green:G1 blue:B1 alpha:1] set];
  769. X1 -= [YCXMenu arrowSize];
  770. }
  771. [arrowPath fill];
  772. // render body
  773. const CGRect bodyFrame = {X0, Y0, X1 - X0, Y1 - Y0};
  774. UIBezierPath *borderPath = [UIBezierPath bezierPathWithRoundedRect:bodyFrame
  775. cornerRadius:[YCXMenu cornerRadius]];
  776. const CGFloat locations[] = {0, 1};
  777. const CGFloat components[] = {
  778. R0, G0, B0, 1,
  779. R1, G1, B1, 1,
  780. };
  781. CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
  782. CGGradientRef gradient = CGGradientCreateWithColorComponents(colorSpace,
  783. components,
  784. locations,
  785. sizeof(locations)/sizeof(locations[0]));
  786. CGColorSpaceRelease(colorSpace);
  787. [borderPath addClip];
  788. CGPoint start, end;
  789. if (_arrowDirection == YCXMenuViewArrowDirectionLeft ||
  790. _arrowDirection == YCXMenuViewArrowDirectionRight) {
  791. start = (CGPoint){X0, Y0};
  792. end = (CGPoint){X1, Y0};
  793. } else {
  794. start = (CGPoint){X0, Y0};
  795. end = (CGPoint){X0, Y1};
  796. }
  797. CGContextDrawLinearGradient(context, gradient, start, end, 0);
  798. CGGradientRelease(gradient);
  799. }
  800. @end
  801. #pragma mark - YCXMenu
  802. /// MenuView
  803. static YCXMenu *gMenu;
  804. @implementation YCXMenu {
  805. YCXMenuView *_menuView;
  806. BOOL _observing;
  807. }
  808. #pragma mark System Methods
  809. + (instancetype)sharedMenu {
  810. static dispatch_once_t onceToken;
  811. dispatch_once(&onceToken, ^{
  812. gMenu = [[YCXMenu alloc] init];
  813. });
  814. return gMenu;
  815. }
  816. - (id)init {
  817. NSAssert(!gMenu, @"singleton object");
  818. self = [super init];
  819. if (self) {
  820. self.isShow = NO;
  821. }
  822. return self;
  823. }
  824. - (void) dealloc {
  825. if (_observing) {
  826. [[NSNotificationCenter defaultCenter] removeObserver:self];
  827. }
  828. }
  829. #pragma mark Public Methods
  830. + (void)showMenuInView:(UIView *)view fromRect:(CGRect)rect menuItems:(NSArray *)menuItems selected:(YCXMenuSelectedItem)selectedItem {
  831. [[self sharedMenu] showMenuInView:view fromRect:rect menuItems:menuItems selected:selectedItem];
  832. }
  833. + (void)showMenuInView:(UIView *)view fromRect:(CGRect)rect menuItems:(NSArray *)menuItems itemWidth:(CGFloat)width selected:(YCXMenuSelectedItem)selectedItem
  834. {
  835. [[self sharedMenu] showMenuInView:view fromRect:rect menuItems:menuItems itemWidth:width selected:selectedItem ];
  836. }
  837. + (void)dismissMenu {
  838. [[self sharedMenu] dismissMenu];
  839. }
  840. + (BOOL)isShow {
  841. return [[self sharedMenu] isShow];
  842. }
  843. + (void)reset {
  844. gTintColor = nil;
  845. gTitleFont = nil;
  846. gArrowSize = kArrowSize;
  847. gCornerRadius = kCornerRadius;
  848. gBackgroundColorEffect = YCXMenuBackgrounColorEffectSolid;
  849. gHasShadow = NO;
  850. gSelectedColor = kSelectedColor;
  851. gSeparatorColor = kSeparatorColor;
  852. }
  853. #pragma mark Private Methods
  854. - (void)showMenuInView:(UIView *)view fromRect:(CGRect)rect menuItems:(NSArray *)menuItems selected:(YCXMenuSelectedItem)selectedItem {
  855. NSParameterAssert(view);
  856. NSParameterAssert(menuItems.count);
  857. if (_menuView) {
  858. [_menuView dismissMenu:NO];
  859. _menuView = nil;
  860. }
  861. if (!_observing) {
  862. _observing = YES;
  863. [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(orientationWillChange:) name:UIApplicationWillChangeStatusBarOrientationNotification object:nil];
  864. }
  865. // 创建MenuView
  866. _menuView = [[YCXMenuView alloc] init];
  867. [_menuView showMenuInView:view fromRect:rect menuItems:menuItems selected:selectedItem];
  868. self.isShow = YES;
  869. }
  870. - (void)showMenuInView:(UIView *)view fromRect:(CGRect)rect menuItems:(NSArray *)menuItems itemWidth:(CGFloat)width selected:(YCXMenuSelectedItem)selectedItem
  871. {
  872. NSParameterAssert(view);
  873. NSParameterAssert(menuItems.count);
  874. if (_menuView) {
  875. [_menuView dismissMenu:NO];
  876. _menuView = nil;
  877. }
  878. if (!_observing) {
  879. _observing = YES;
  880. [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(orientationWillChange:) name:UIApplicationWillChangeStatusBarOrientationNotification object:nil];
  881. }
  882. // 创建MenuView
  883. _menuView = [[YCXMenuView alloc] init];
  884. [_menuView showMenuInView:view fromRect:rect menuItems:menuItems itemWidth:width selected:selectedItem];
  885. self.isShow = YES;
  886. }
  887. - (void)dismissMenu {
  888. if (_menuView) {
  889. [_menuView dismissMenu:NO];
  890. _menuView = nil;
  891. }
  892. if (_observing) {
  893. _observing = NO;
  894. [[NSNotificationCenter defaultCenter] removeObserver:self];
  895. }
  896. self.isShow = NO;
  897. }
  898. #pragma mark Notification
  899. - (void)orientationWillChange:(NSNotification *)notification {
  900. [self dismissMenu];
  901. }
  902. #pragma mark setter/getter
  903. + (UIColor *)tintColor {
  904. return gTintColor?gTintColor:kTintColor;
  905. }
  906. + (void)setTintColor:(UIColor *)tintColor {
  907. if (tintColor != gTintColor) {
  908. gTintColor = tintColor;
  909. }
  910. }
  911. + (CGFloat)cornerRadius {
  912. return gCornerRadius >0?gCornerRadius:kCornerRadius;
  913. }
  914. + (void)setCornerRadius:(CGFloat)cornerRadius {
  915. if (cornerRadius > 0) {
  916. gCornerRadius = cornerRadius;
  917. }
  918. }
  919. + (CGFloat)arrowSize {
  920. return gArrowSize > 0?gArrowSize:kArrowSize;
  921. }
  922. + (void)setArrowSize:(CGFloat)arrowSize {
  923. if (arrowSize > 0) {
  924. gArrowSize = arrowSize;
  925. }
  926. }
  927. + (UIFont *)titleFont {
  928. return gTitleFont?gTitleFont:kTitleFont;
  929. }
  930. + (void)setTitleFont:(UIFont *)titleFont {
  931. if (titleFont != gTitleFont) {
  932. gTitleFont = titleFont;
  933. }
  934. }
  935. + (YCXMenuBackgrounColorEffect)backgrounColorEffect {
  936. return gBackgroundColorEffect;
  937. }
  938. + (void)setBackgrounColorEffect:(YCXMenuBackgrounColorEffect)effect {
  939. gBackgroundColorEffect = effect;
  940. }
  941. + (BOOL)hasShadow {
  942. return gHasShadow;
  943. }
  944. + (void)setHasShadow:(BOOL)flag {
  945. gHasShadow = flag;
  946. }
  947. +(UIColor *)selectedColor {
  948. return gSelectedColor?gSelectedColor:kSelectedColor;
  949. }
  950. +(void)setSelectedColor:(UIColor *)selectedColor {
  951. gSelectedColor = selectedColor;
  952. }
  953. +(UIColor *)separatorColor {
  954. return gSeparatorColor?gSeparatorColor:kSeparatorColor;
  955. }
  956. +(void)setSeparatorColor:(UIColor *)separatorColor {
  957. gSeparatorColor = separatorColor;
  958. }
  959. /// 菜单元素垂直方向上的边距值
  960. + (CGFloat)menuItemMarginY {
  961. return gMenuItemMarginY > 0?gMenuItemMarginY:kMenuItemMarginY;
  962. }
  963. +(void)setMenuItemMarginY:(CGFloat)menuItemMarginY {
  964. if (menuItemMarginY > 0) {
  965. gMenuItemMarginY = menuItemMarginY;
  966. }
  967. }
  968. @end