YBPopupMenu.m 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690
  1. //
  2. // YBPopupMenu.m
  3. // YBPopupMenu
  4. //
  5. // Created by lyb on 2017/5/10.
  6. // Copyright © 2017年 lyb. All rights reserved.
  7. //
  8. #import "YBPopupMenu.h"
  9. #import "YBPopupMenuPath.h"
  10. #define YBScreenWidth [UIScreen mainScreen].bounds.size.width
  11. #define YBScreenHeight [UIScreen mainScreen].bounds.size.height
  12. #define YBMainWindow [UIApplication sharedApplication].keyWindow
  13. #define YB_SAFE_BLOCK(BlockName, ...) ({ !BlockName ? nil : BlockName(__VA_ARGS__); })
  14. #pragma mark - /////////////
  15. #pragma mark - private cell
  16. @interface YBPopupMenuCell : UITableViewCell
  17. @property (nonatomic, assign) BOOL isShowSeparator;
  18. @property (nonatomic, strong) UIColor * separatorColor;
  19. @end
  20. @implementation YBPopupMenuCell
  21. - (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
  22. {
  23. self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
  24. if (self) {
  25. _isShowSeparator = NO;
  26. _separatorColor = [UIColor lightGrayColor];
  27. [self setNeedsDisplay];
  28. }
  29. return self;
  30. }
  31. - (void)setIsShowSeparator:(BOOL)isShowSeparator
  32. {
  33. _isShowSeparator = isShowSeparator;
  34. [self setNeedsDisplay];
  35. }
  36. - (void)setSeparatorColor:(UIColor *)separatorColor
  37. {
  38. _separatorColor = separatorColor;
  39. [self setNeedsDisplay];
  40. }
  41. - (void)layoutSubviews
  42. {
  43. [super layoutSubviews];
  44. self.contentView.frame = self.bounds;
  45. self.contentView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
  46. }
  47. - (void)drawRect:(CGRect)rect
  48. {
  49. if (!_isShowSeparator) return;
  50. UIBezierPath *bezierPath = [UIBezierPath bezierPathWithRect:CGRectMake(0, rect.size.height - 0.5, rect.size.width, 0.5)];
  51. [_separatorColor setFill];
  52. [bezierPath fillWithBlendMode:kCGBlendModeNormal alpha:1];
  53. [bezierPath closePath];
  54. }
  55. @end
  56. @interface YBPopupMenu ()
  57. <
  58. UITableViewDelegate,
  59. UITableViewDataSource
  60. >
  61. @property (nonatomic, strong) UIView * menuBackView;
  62. @property (nonatomic) CGRect relyRect;
  63. @property (nonatomic, assign) CGFloat itemWidth;
  64. @property (nonatomic) CGPoint point;
  65. @property (nonatomic, assign) BOOL isCornerChanged;
  66. @property (nonatomic, strong) UIColor * separatorColor;
  67. @property (nonatomic, assign) BOOL isChangeDirection;
  68. @property (nonatomic, strong) UIView * relyView;
  69. @end
  70. @implementation YBPopupMenu
  71. - (instancetype)init
  72. {
  73. self = [super init];
  74. if (self) {
  75. [self setDefaultSettings];
  76. }
  77. return self;
  78. }
  79. #pragma mark - publics
  80. + (YBPopupMenu *)showAtPoint:(CGPoint)point titles:(NSArray *)titles icons:(NSArray *)icons menuWidth:(CGFloat)itemWidth otherSettings:(void (^) (YBPopupMenu * popupMenu))otherSetting
  81. {
  82. YBPopupMenu *popupMenu = [[YBPopupMenu alloc] init];
  83. popupMenu.point = point;
  84. popupMenu.titles = titles;
  85. popupMenu.images = icons;
  86. popupMenu.itemWidth = itemWidth;
  87. YB_SAFE_BLOCK(otherSetting,popupMenu);
  88. [popupMenu show];
  89. return popupMenu;
  90. }
  91. + (YBPopupMenu *)showRelyOnView:(UIView *)view titles:(NSArray *)titles icons:(NSArray *)icons menuWidth:(CGFloat)itemWidth otherSettings:(void (^) (YBPopupMenu * popupMenu))otherSetting
  92. {
  93. YBPopupMenu *popupMenu = [[YBPopupMenu alloc] init];
  94. popupMenu.relyView = view;
  95. popupMenu.titles = titles;
  96. popupMenu.images = icons;
  97. popupMenu.itemWidth = itemWidth;
  98. YB_SAFE_BLOCK(otherSetting,popupMenu);
  99. [popupMenu show];
  100. return popupMenu;
  101. }
  102. - (void)dismiss
  103. {
  104. [self.orientationManager endMonitorDeviceOrientation];
  105. if (self.delegate && [self.delegate respondsToSelector:@selector(ybPopupMenuBeganDismiss:)]) {
  106. [self.delegate ybPopupMenuBeganDismiss:self];
  107. }
  108. __weak typeof(self) weakSelf = self;
  109. [self.animationManager displayDismissAnimationCompletion:^{
  110. __strong typeof(weakSelf)self = weakSelf;
  111. if (self.delegate && [self.delegate respondsToSelector:@selector(ybPopupMenuDidDismiss:)]) {
  112. [self.delegate ybPopupMenuDidDismiss:self];
  113. }
  114. self.delegate = nil;
  115. [self removeFromSuperview];
  116. [self.menuBackView removeFromSuperview];
  117. }];
  118. }
  119. + (void)dismissAllPopupMenu
  120. {
  121. for (UIView * subView in YBMainWindow.subviews) {
  122. if ([subView isKindOfClass:[YBPopupMenu class]]) {
  123. YBPopupMenu * popupMenu = (YBPopupMenu *)subView;
  124. [popupMenu dismiss];
  125. }
  126. }
  127. }
  128. #pragma mark tableViewDelegate & dataSource
  129. - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
  130. {
  131. return _titles.count;
  132. }
  133. - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
  134. {
  135. UITableViewCell * tableViewCell = nil;
  136. if (self.delegate && [self.delegate respondsToSelector:@selector(ybPopupMenu:cellForRowAtIndex:)]) {
  137. tableViewCell = [self.delegate ybPopupMenu:self cellForRowAtIndex:indexPath.row];
  138. }
  139. if (tableViewCell) {
  140. return tableViewCell;
  141. }
  142. static NSString * identifier = @"ybPopupMenu";
  143. YBPopupMenuCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
  144. if (!cell) {
  145. cell = [[YBPopupMenuCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier];
  146. cell.textLabel.numberOfLines = 0;
  147. }
  148. cell.backgroundColor = [UIColor clearColor];
  149. cell.textLabel.textColor = _textColor;
  150. if (_font) {
  151. cell.textLabel.font = _font;
  152. }else {
  153. cell.textLabel.font = [UIFont systemFontOfSize:_fontSize];
  154. }
  155. if (self.isCenter) {
  156. cell.textLabel.textAlignment = NSTextAlignmentCenter;
  157. }
  158. if ([_titles[indexPath.row] isKindOfClass:[NSAttributedString class]]) {
  159. cell.textLabel.attributedText = _titles[indexPath.row];
  160. }else if ([_titles[indexPath.row] isKindOfClass:[NSString class]]) {
  161. cell.textLabel.text = _titles[indexPath.row];
  162. }else {
  163. cell.textLabel.text = nil;
  164. }
  165. cell.separatorColor = _separatorColor;
  166. if (_images.count >= indexPath.row + 1) {
  167. if ([_images[indexPath.row] isKindOfClass:[NSString class]]) {
  168. cell.imageView.image = [UIImage imageNamed:_images[indexPath.row]];
  169. }else if ([_images[indexPath.row] isKindOfClass:[UIImage class]]){
  170. cell.imageView.image = _images[indexPath.row];
  171. }else {
  172. cell.imageView.image = nil;
  173. }
  174. }else {
  175. cell.imageView.image = nil;
  176. }
  177. [cell setSelectionStyle:UITableViewCellSelectionStyleNone];
  178. return cell;
  179. }
  180. - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
  181. {
  182. if (self.delegate && [self.delegate respondsToSelector:@selector(ybPopupMenu:heightForRowAtIndex:)]) {
  183. return [self.delegate ybPopupMenu:self heightForRowAtIndex:indexPath.row];
  184. }
  185. return _itemHeight;
  186. }
  187. - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
  188. {
  189. [tableView deselectRowAtIndexPath:indexPath animated:YES];
  190. if (_dismissOnSelected) [self dismiss];
  191. if (self.selectTextColor) {
  192. YBPopupMenuCell *cell = [tableView cellForRowAtIndexPath:indexPath];
  193. cell.textLabel.textColor = HexColorFromRGB(0xFF0084);
  194. }
  195. if (self.delegate && [self.delegate respondsToSelector:@selector(ybPopupMenu:didSelectedAtIndex:)]) {
  196. [self.delegate ybPopupMenu:self didSelectedAtIndex:indexPath.row];
  197. }
  198. }
  199. #pragma mark - scrollViewDelegate
  200. - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
  201. {
  202. if ([[self getLastVisibleCell] isKindOfClass:[YBPopupMenuCell class]]) {
  203. YBPopupMenuCell *cell = [self getLastVisibleCell];
  204. cell.isShowSeparator = NO;
  205. }
  206. }
  207. - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
  208. {
  209. if ([[self getLastVisibleCell] isKindOfClass:[YBPopupMenuCell class]]) {
  210. YBPopupMenuCell *cell = [self getLastVisibleCell];
  211. cell.isShowSeparator = NO;
  212. }
  213. }
  214. - (YBPopupMenuCell *)getLastVisibleCell
  215. {
  216. NSArray <NSIndexPath *>*indexPaths = [self.tableView indexPathsForVisibleRows];
  217. indexPaths = [indexPaths sortedArrayUsingComparator:^NSComparisonResult(NSIndexPath * _Nonnull obj1, NSIndexPath * _Nonnull obj2) {
  218. return obj1.row < obj2.row;
  219. }];
  220. NSIndexPath *indexPath = indexPaths.firstObject;
  221. return [self.tableView cellForRowAtIndexPath:indexPath];
  222. }
  223. #pragma mark - privates
  224. - (void)show
  225. {
  226. [self.orientationManager startMonitorDeviceOrientation];
  227. [self updateUI];
  228. [YBMainWindow addSubview:_menuBackView];
  229. [YBMainWindow addSubview:self];
  230. if (self.delegate && [self.delegate respondsToSelector:@selector(ybPopupMenuBeganShow:)]) {
  231. [self.delegate ybPopupMenuBeganShow:self];
  232. }
  233. if ([[self getLastVisibleCell] isKindOfClass:[YBPopupMenuCell class]]) {
  234. YBPopupMenuCell *cell = [self getLastVisibleCell];
  235. cell.isShowSeparator = NO;
  236. }
  237. __weak typeof(self) weakSelf = self;
  238. [self.animationManager displayShowAnimationCompletion:^{
  239. __strong typeof(weakSelf)self = weakSelf;
  240. if (self.delegate && [self.delegate respondsToSelector:@selector(ybPopupMenuDidShow:)]) {
  241. [self.delegate ybPopupMenuDidShow:self];
  242. }
  243. }];
  244. }
  245. - (void)setDefaultSettings
  246. {
  247. _cornerRadius = 5.0;
  248. _rectCorner = UIRectCornerAllCorners;
  249. self.isShowShadow = YES;
  250. _dismissOnSelected = YES;
  251. _dismissOnTouchOutside = YES;
  252. _fontSize = 15;
  253. _textColor = [UIColor blackColor];
  254. _offset = 0.0;
  255. _relyRect = CGRectZero;
  256. _point = CGPointZero;
  257. _borderWidth = 0.0;
  258. _borderColor = [UIColor lightGrayColor];
  259. _arrowWidth = 15.0;
  260. _arrowHeight = 10.0;
  261. _backColor = [UIColor whiteColor];
  262. _type = YBPopupMenuTypeDefault;
  263. _arrowDirection = YBPopupMenuArrowDirectionTop;
  264. _priorityDirection = YBPopupMenuPriorityDirectionTop;
  265. _minSpace = 10.0;
  266. _maxVisibleCount = 5;
  267. _itemHeight = 44;
  268. _isCornerChanged = NO;
  269. _showMaskView = YES;
  270. _orientationManager = [YBPopupMenuDeviceOrientationManager manager];
  271. _animationManager = [YBPopupMenuAnimationManager manager];
  272. _animationManager.animationView = self;
  273. _menuBackView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, YBScreenWidth, YBScreenHeight)];
  274. _menuBackView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.1];
  275. _menuBackView.alpha = 1;
  276. UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget: self action: @selector(touchOutSide)];
  277. [_menuBackView addGestureRecognizer: tap];
  278. self.alpha = 1;
  279. self.backgroundColor = [UIColor clearColor];
  280. [self addSubview:self.tableView];
  281. __weak typeof(self) weakSelf = self;
  282. [_orientationManager setDeviceOrientDidChangeHandle:^(UIInterfaceOrientation orientation) {
  283. __strong typeof(weakSelf)self = weakSelf;
  284. if (orientation == UIInterfaceOrientationPortrait ||
  285. orientation == UIInterfaceOrientationLandscapeLeft ||
  286. orientation == UIInterfaceOrientationLandscapeRight)
  287. {
  288. if (self.relyView) {
  289. //依赖view
  290. dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.01 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
  291. //需要延迟加载才可以获取真实的frame,这里先做个标记,若有更合适的方法再替换
  292. [self calculateRealPointIfNeed];
  293. [self updateUI];
  294. });
  295. }else {
  296. //依赖point
  297. [self updateUI];
  298. }
  299. }
  300. }];
  301. }
  302. - (UITableView *)tableView
  303. {
  304. if (!_tableView) {
  305. _tableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStylePlain];
  306. _tableView.backgroundColor = [UIColor clearColor];
  307. _tableView.tableFooterView = [UIView new];
  308. _tableView.delegate = self;
  309. _tableView.dataSource = self;
  310. _tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
  311. }
  312. return _tableView;
  313. }
  314. - (void)touchOutSide
  315. {
  316. if (_dismissOnTouchOutside) {
  317. [self dismiss];
  318. }
  319. }
  320. - (void)setIsShowShadow:(BOOL)isShowShadow
  321. {
  322. _isShowShadow = isShowShadow;
  323. self.layer.shadowOpacity = isShowShadow ? 0.5 : 0;
  324. self.layer.shadowOffset = CGSizeMake(0, 0);
  325. self.layer.shadowRadius = isShowShadow ? 2.0 : 0;
  326. }
  327. - (void)setRelyView:(UIView *)relyView
  328. {
  329. _relyView = relyView;
  330. [self calculateRealPointIfNeed];
  331. }
  332. - (void)calculateRealPointIfNeed
  333. {
  334. CGRect absoluteRect = [_relyView convertRect:_relyView.bounds toView:YBMainWindow];
  335. CGPoint relyPoint = CGPointMake(absoluteRect.origin.x + absoluteRect.size.width / 2, absoluteRect.origin.y + absoluteRect.size.height);
  336. self.relyRect = absoluteRect;
  337. self.point = relyPoint;
  338. }
  339. - (void)setShowMaskView:(BOOL)showMaskView
  340. {
  341. _showMaskView = showMaskView;
  342. _menuBackView.backgroundColor = showMaskView ? [[UIColor blackColor] colorWithAlphaComponent:0.1] : [UIColor clearColor];
  343. }
  344. - (void)setType:(YBPopupMenuType)type
  345. {
  346. _type = type;
  347. switch (type) {
  348. case YBPopupMenuTypeDark:
  349. {
  350. _textColor = [UIColor lightGrayColor];
  351. _backColor = [UIColor colorWithRed:0.25 green:0.27 blue:0.29 alpha:1];
  352. _separatorColor = [UIColor lightGrayColor];
  353. }
  354. break;
  355. default:
  356. {
  357. _textColor = [UIColor blackColor];
  358. _backColor = [UIColor whiteColor];
  359. _separatorColor = [UIColor lightGrayColor];
  360. }
  361. break;
  362. }
  363. }
  364. - (void)setTitles:(NSArray *)titles
  365. {
  366. _titles = titles;
  367. }
  368. - (void)setImages:(NSArray *)images
  369. {
  370. _images = images;
  371. }
  372. - (void)updateUI
  373. {
  374. _menuBackView.frame = CGRectMake(0, 0, YBScreenWidth, YBScreenHeight);
  375. CGFloat height;
  376. if (_titles.count > _maxVisibleCount) {
  377. height = _itemHeight * _maxVisibleCount + _borderWidth * 2;
  378. self.tableView.bounces = YES;
  379. }else {
  380. height = _itemHeight * _titles.count + _borderWidth * 2;
  381. self.tableView.bounces = NO;
  382. }
  383. _isChangeDirection = NO;
  384. if (_priorityDirection == YBPopupMenuPriorityDirectionTop) {
  385. if (_point.y + height + _arrowHeight > YBScreenHeight - _minSpace) {
  386. _arrowDirection = YBPopupMenuArrowDirectionBottom;
  387. _isChangeDirection = YES;
  388. }else {
  389. _arrowDirection = YBPopupMenuArrowDirectionTop;
  390. _isChangeDirection = NO;
  391. }
  392. }else if (_priorityDirection == YBPopupMenuPriorityDirectionBottom) {
  393. if (_point.y - height - _arrowHeight < _minSpace) {
  394. _arrowDirection = YBPopupMenuArrowDirectionTop;
  395. _isChangeDirection = YES;
  396. }else {
  397. _arrowDirection = YBPopupMenuArrowDirectionBottom;
  398. _isChangeDirection = NO;
  399. }
  400. }else if (_priorityDirection == YBPopupMenuPriorityDirectionLeft) {
  401. if (_point.x + _itemWidth + _arrowHeight > YBScreenWidth - _minSpace) {
  402. _arrowDirection = YBPopupMenuArrowDirectionRight;
  403. _isChangeDirection = YES;
  404. }else {
  405. _arrowDirection = YBPopupMenuArrowDirectionLeft;
  406. _isChangeDirection = NO;
  407. }
  408. }else if (_priorityDirection == YBPopupMenuPriorityDirectionRight) {
  409. if (_point.x - _itemWidth - _arrowHeight < _minSpace) {
  410. _arrowDirection = YBPopupMenuArrowDirectionLeft;
  411. _isChangeDirection = YES;
  412. }else {
  413. _arrowDirection = YBPopupMenuArrowDirectionRight;
  414. _isChangeDirection = NO;
  415. }
  416. }
  417. [self setArrowPosition];
  418. [self setRelyRect];
  419. if (_arrowDirection == YBPopupMenuArrowDirectionTop) {
  420. CGFloat y = _isChangeDirection ? _point.y : _point.y;
  421. if (_arrowPosition > _itemWidth / 2) {
  422. self.frame = CGRectMake(YBScreenWidth - _minSpace - _itemWidth, y, _itemWidth, height + _arrowHeight);
  423. }else if (_arrowPosition < _itemWidth / 2) {
  424. self.frame = CGRectMake(_minSpace, y, _itemWidth, height + _arrowHeight);
  425. }else {
  426. self.frame = CGRectMake(_point.x - _itemWidth / 2, y, _itemWidth, height + _arrowHeight);
  427. }
  428. }else if (_arrowDirection == YBPopupMenuArrowDirectionBottom) {
  429. CGFloat y = _isChangeDirection ? _point.y - _arrowHeight - height : _point.y - _arrowHeight - height;
  430. if (_arrowPosition > _itemWidth / 2) {
  431. self.frame = CGRectMake(YBScreenWidth - _minSpace - _itemWidth, y, _itemWidth, height + _arrowHeight);
  432. }else if (_arrowPosition < _itemWidth / 2) {
  433. self.frame = CGRectMake(_minSpace, y, _itemWidth, height + _arrowHeight);
  434. }else {
  435. self.frame = CGRectMake(_point.x - _itemWidth / 2, y, _itemWidth, height + _arrowHeight);
  436. }
  437. }else if (_arrowDirection == YBPopupMenuArrowDirectionLeft) {
  438. CGFloat x = _isChangeDirection ? _point.x : _point.x;
  439. if (_arrowPosition < _itemHeight / 2) {
  440. self.frame = CGRectMake(x, _point.y - _arrowPosition, _itemWidth + _arrowHeight, height);
  441. }else if (_arrowPosition > _itemHeight / 2) {
  442. self.frame = CGRectMake(x, _point.y - _arrowPosition, _itemWidth + _arrowHeight, height);
  443. }else {
  444. self.frame = CGRectMake(x, _point.y - _arrowPosition, _itemWidth + _arrowHeight, height);
  445. }
  446. }else if (_arrowDirection == YBPopupMenuArrowDirectionRight) {
  447. CGFloat x = _isChangeDirection ? _point.x - _itemWidth - _arrowHeight : _point.x - _itemWidth - _arrowHeight;
  448. if (_arrowPosition < _itemHeight / 2) {
  449. self.frame = CGRectMake(x, _point.y - _arrowPosition, _itemWidth + _arrowHeight, height);
  450. }else if (_arrowPosition > _itemHeight / 2) {
  451. self.frame = CGRectMake(x, _point.y - _arrowPosition, _itemWidth + _arrowHeight, height);
  452. }else {
  453. self.frame = CGRectMake(x, _point.y - _arrowPosition, _itemWidth + _arrowHeight, height);
  454. }
  455. }else if (_arrowDirection == YBPopupMenuArrowDirectionNone) {
  456. }
  457. if (_isChangeDirection) {
  458. [self changeRectCorner];
  459. }
  460. [self setAnchorPoint];
  461. [self setOffset];
  462. [self.tableView reloadData];
  463. [self setNeedsDisplay];
  464. }
  465. - (void)setRelyRect
  466. {
  467. if (CGRectEqualToRect(_relyRect, CGRectZero)) {
  468. return;
  469. }
  470. if (_arrowDirection == YBPopupMenuArrowDirectionTop) {
  471. _point.y = _relyRect.size.height + _relyRect.origin.y;
  472. }else if (_arrowDirection == YBPopupMenuArrowDirectionBottom) {
  473. _point.y = _relyRect.origin.y;
  474. }else if (_arrowDirection == YBPopupMenuArrowDirectionLeft) {
  475. _point = CGPointMake(_relyRect.origin.x + _relyRect.size.width, _relyRect.origin.y + _relyRect.size.height / 2);
  476. }else {
  477. _point = CGPointMake(_relyRect.origin.x, _relyRect.origin.y + _relyRect.size.height / 2);
  478. }
  479. }
  480. - (void)setFrame:(CGRect)frame
  481. {
  482. [super setFrame:frame];
  483. if (_arrowDirection == YBPopupMenuArrowDirectionTop) {
  484. self.tableView.frame = CGRectMake(_borderWidth, _borderWidth + _arrowHeight, frame.size.width - _borderWidth * 2, frame.size.height - _arrowHeight);
  485. }else if (_arrowDirection == YBPopupMenuArrowDirectionBottom) {
  486. self.tableView.frame = CGRectMake(_borderWidth, _borderWidth, frame.size.width - _borderWidth * 2, frame.size.height - _arrowHeight);
  487. }else if (_arrowDirection == YBPopupMenuArrowDirectionLeft) {
  488. self.tableView.frame = CGRectMake(_borderWidth + _arrowHeight, _borderWidth , frame.size.width - _borderWidth * 2 - _arrowHeight, frame.size.height);
  489. }else if (_arrowDirection == YBPopupMenuArrowDirectionRight) {
  490. self.tableView.frame = CGRectMake(_borderWidth , _borderWidth , frame.size.width - _borderWidth * 2 - _arrowHeight, frame.size.height);
  491. }
  492. }
  493. - (void)changeRectCorner
  494. {
  495. if (_isCornerChanged || _rectCorner == UIRectCornerAllCorners) {
  496. return;
  497. }
  498. BOOL haveTopLeftCorner = NO, haveTopRightCorner = NO, haveBottomLeftCorner = NO, haveBottomRightCorner = NO;
  499. if (_rectCorner & UIRectCornerTopLeft) {
  500. haveTopLeftCorner = YES;
  501. }
  502. if (_rectCorner & UIRectCornerTopRight) {
  503. haveTopRightCorner = YES;
  504. }
  505. if (_rectCorner & UIRectCornerBottomLeft) {
  506. haveBottomLeftCorner = YES;
  507. }
  508. if (_rectCorner & UIRectCornerBottomRight) {
  509. haveBottomRightCorner = YES;
  510. }
  511. if (_arrowDirection == YBPopupMenuArrowDirectionTop || _arrowDirection == YBPopupMenuArrowDirectionBottom) {
  512. if (haveTopLeftCorner) {
  513. _rectCorner = _rectCorner | UIRectCornerBottomLeft;
  514. }else {
  515. _rectCorner = _rectCorner & (~UIRectCornerBottomLeft);
  516. }
  517. if (haveTopRightCorner) {
  518. _rectCorner = _rectCorner | UIRectCornerBottomRight;
  519. }else {
  520. _rectCorner = _rectCorner & (~UIRectCornerBottomRight);
  521. }
  522. if (haveBottomLeftCorner) {
  523. _rectCorner = _rectCorner | UIRectCornerTopLeft;
  524. }else {
  525. _rectCorner = _rectCorner & (~UIRectCornerTopLeft);
  526. }
  527. if (haveBottomRightCorner) {
  528. _rectCorner = _rectCorner | UIRectCornerTopRight;
  529. }else {
  530. _rectCorner = _rectCorner & (~UIRectCornerTopRight);
  531. }
  532. }else if (_arrowDirection == YBPopupMenuArrowDirectionLeft || _arrowDirection == YBPopupMenuArrowDirectionRight) {
  533. if (haveTopLeftCorner) {
  534. _rectCorner = _rectCorner | UIRectCornerTopRight;
  535. }else {
  536. _rectCorner = _rectCorner & (~UIRectCornerTopRight);
  537. }
  538. if (haveTopRightCorner) {
  539. _rectCorner = _rectCorner | UIRectCornerTopLeft;
  540. }else {
  541. _rectCorner = _rectCorner & (~UIRectCornerTopLeft);
  542. }
  543. if (haveBottomLeftCorner) {
  544. _rectCorner = _rectCorner | UIRectCornerBottomRight;
  545. }else {
  546. _rectCorner = _rectCorner & (~UIRectCornerBottomRight);
  547. }
  548. if (haveBottomRightCorner) {
  549. _rectCorner = _rectCorner | UIRectCornerBottomLeft;
  550. }else {
  551. _rectCorner = _rectCorner & (~UIRectCornerBottomLeft);
  552. }
  553. }
  554. _isCornerChanged = YES;
  555. }
  556. - (void)setOffset
  557. {
  558. if (_itemWidth == 0) return;
  559. CGRect originRect = self.frame;
  560. if (_arrowDirection == YBPopupMenuArrowDirectionTop) {
  561. originRect.origin.y += _offset;
  562. }else if (_arrowDirection == YBPopupMenuArrowDirectionBottom) {
  563. originRect.origin.y -= _offset;
  564. }else if (_arrowDirection == YBPopupMenuArrowDirectionLeft) {
  565. originRect.origin.x += _offset;
  566. }else if (_arrowDirection == YBPopupMenuArrowDirectionRight) {
  567. originRect.origin.x -= _offset;
  568. }
  569. self.frame = originRect;
  570. }
  571. - (void)setAnchorPoint
  572. {
  573. if (_itemWidth == 0) return;
  574. CGFloat menuHeight = [self getMenuTotalHeight];
  575. CGPoint point = CGPointMake(0.5, 0.5);
  576. if (_arrowDirection == YBPopupMenuArrowDirectionTop) {
  577. point = CGPointMake(_arrowPosition / _itemWidth, 0);
  578. }else if (_arrowDirection == YBPopupMenuArrowDirectionBottom) {
  579. point = CGPointMake(_arrowPosition / _itemWidth, 1);
  580. }else if (_arrowDirection == YBPopupMenuArrowDirectionLeft) {
  581. point = CGPointMake(0, _arrowPosition / menuHeight);
  582. }else if (_arrowDirection == YBPopupMenuArrowDirectionRight) {
  583. point = CGPointMake(1, _arrowPosition / menuHeight);
  584. }
  585. CGRect originRect = self.frame;
  586. self.layer.anchorPoint = point;
  587. self.frame = originRect;
  588. }
  589. - (void)setArrowPosition
  590. {
  591. if (_priorityDirection == YBPopupMenuPriorityDirectionNone) {
  592. return;
  593. }
  594. if (_arrowDirection == YBPopupMenuArrowDirectionTop || _arrowDirection == YBPopupMenuArrowDirectionBottom) {
  595. if (_point.x + _itemWidth / 2 > YBScreenWidth - _minSpace) {
  596. _arrowPosition = _itemWidth - (YBScreenWidth - _minSpace - _point.x);
  597. }else if (_point.x < _itemWidth / 2 + _minSpace) {
  598. _arrowPosition = _point.x - _minSpace;
  599. }else {
  600. _arrowPosition = _itemWidth / 2;
  601. }
  602. }else if (_arrowDirection == YBPopupMenuArrowDirectionLeft || _arrowDirection == YBPopupMenuArrowDirectionRight) {
  603. }
  604. }
  605. - (CGFloat)getMenuTotalHeight
  606. {
  607. CGFloat menuHeight = 0;
  608. if (_titles.count > _maxVisibleCount) {
  609. menuHeight = _itemHeight * _maxVisibleCount + _borderWidth * 2;
  610. }else {
  611. menuHeight = _itemHeight * _titles.count + _borderWidth * 2;
  612. }
  613. return menuHeight;
  614. }
  615. - (void)drawRect:(CGRect)rect
  616. {
  617. UIBezierPath *bezierPath = [YBPopupMenuPath yb_bezierPathWithRect:rect rectCorner:_rectCorner cornerRadius:_cornerRadius borderWidth:_borderWidth borderColor:_borderColor backgroundColor:_backColor arrowWidth:_arrowWidth arrowHeight:_arrowHeight arrowPosition:_arrowPosition arrowDirection:_arrowDirection];
  618. [bezierPath fill];
  619. [bezierPath stroke];
  620. }
  621. @end