YBPopupMenu.m 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733
  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 = YES;
  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)drawRect:(CGRect)rect
  42. {
  43. if (!_isShowSeparator) return;
  44. UIBezierPath *bezierPath = [UIBezierPath bezierPathWithRect:CGRectMake(0, rect.size.height - 0.5, rect.size.width, 0.5)];
  45. [_separatorColor setFill];
  46. [bezierPath fillWithBlendMode:kCGBlendModeNormal alpha:1];
  47. [bezierPath closePath];
  48. }
  49. @end
  50. @interface YBPopupMenu ()
  51. <
  52. UITableViewDelegate,
  53. UITableViewDataSource
  54. >
  55. @property (nonatomic, strong) UIView * menuBackView;
  56. @property (nonatomic) CGRect relyRect;
  57. @property (nonatomic, strong) UITableView * tableView;
  58. @property (nonatomic, assign) CGFloat minSpace;
  59. @property (nonatomic, assign) CGFloat itemWidth;
  60. @property (nonatomic, strong) NSArray * titles;
  61. @property (nonatomic, strong) NSArray * images;
  62. @property (nonatomic) CGPoint point;
  63. @property (nonatomic, assign) BOOL isCornerChanged;
  64. @property (nonatomic, strong) UIColor * separatorColor;
  65. @property (nonatomic, assign) BOOL isChangeDirection;
  66. @end
  67. @implementation YBPopupMenu
  68. - (instancetype)init
  69. {
  70. self = [super init];
  71. if (self) {
  72. [self setDefaultSettings];
  73. }
  74. return self;
  75. }
  76. #pragma mark - publics
  77. + (YBPopupMenu *)showAtPoint:(CGPoint)point titles:(NSArray *)titles icons:(NSArray *)icons menuWidth:(CGFloat)itemWidth delegate:(id<YBPopupMenuDelegate>)delegate
  78. {
  79. YBPopupMenu *popupMenu = [[YBPopupMenu alloc] init];
  80. popupMenu.point = point;
  81. popupMenu.titles = titles;
  82. popupMenu.images = icons;
  83. popupMenu.itemWidth = itemWidth;
  84. popupMenu.delegate = delegate;
  85. [popupMenu show];
  86. return popupMenu;
  87. }
  88. + (YBPopupMenu *)showRelyOnView:(UIView *)view titles:(NSArray *)titles icons:(NSArray *)icons menuWidth:(CGFloat)itemWidth delegate:(id<YBPopupMenuDelegate>)delegate
  89. {
  90. CGRect absoluteRect = [view convertRect:view.bounds toView:YBMainWindow];
  91. CGPoint relyPoint = CGPointMake(absoluteRect.origin.x + absoluteRect.size.width / 2, absoluteRect.origin.y + absoluteRect.size.height);
  92. YBPopupMenu *popupMenu = [[YBPopupMenu alloc] init];
  93. popupMenu.point = relyPoint;
  94. popupMenu.relyRect = absoluteRect;
  95. popupMenu.titles = titles;
  96. popupMenu.images = icons;
  97. popupMenu.itemWidth = itemWidth;
  98. popupMenu.delegate = delegate;
  99. [popupMenu show];
  100. return popupMenu;
  101. }
  102. + (YBPopupMenu *)showAtPoint:(CGPoint)point titles:(NSArray *)titles icons:(NSArray *)icons menuWidth:(CGFloat)itemWidth otherSettings:(void (^) (YBPopupMenu * popupMenu))otherSetting
  103. {
  104. YBPopupMenu *popupMenu = [[YBPopupMenu alloc] init];
  105. popupMenu.point = point;
  106. popupMenu.titles = titles;
  107. popupMenu.images = icons;
  108. popupMenu.itemWidth = itemWidth;
  109. YB_SAFE_BLOCK(otherSetting,popupMenu);
  110. [popupMenu show];
  111. return popupMenu;
  112. }
  113. + (YBPopupMenu *)showRelyOnView:(UIView *)view titles:(NSArray *)titles icons:(NSArray *)icons menuWidth:(CGFloat)itemWidth otherSettings:(void (^) (YBPopupMenu * popupMenu))otherSetting
  114. {
  115. CGRect absoluteRect = [view convertRect:view.bounds toView:YBMainWindow];
  116. CGPoint relyPoint = CGPointMake(absoluteRect.origin.x + absoluteRect.size.width / 2, absoluteRect.origin.y + absoluteRect.size.height);
  117. YBPopupMenu *popupMenu = [[YBPopupMenu alloc] init];
  118. popupMenu.point = relyPoint;
  119. popupMenu.relyRect = absoluteRect;
  120. popupMenu.titles = titles;
  121. popupMenu.images = icons;
  122. popupMenu.itemWidth = itemWidth;
  123. YB_SAFE_BLOCK(otherSetting,popupMenu);
  124. [popupMenu show];
  125. return popupMenu;
  126. }
  127. - (void)dismiss
  128. {
  129. if (self.delegate && [self.delegate respondsToSelector:@selector(ybPopupMenuBeganDismiss)]) {
  130. [self.delegate ybPopupMenuBeganDismiss];
  131. }
  132. [UIView animateWithDuration: 0.25 animations:^{
  133. self.layer.affineTransform = CGAffineTransformMakeScale(0.1, 0.1);
  134. self.alpha = 0;
  135. _menuBackView.alpha = 0;
  136. } completion:^(BOOL finished) {
  137. if (self.delegate && [self.delegate respondsToSelector:@selector(ybPopupMenuDidDismiss)]) {
  138. [self.delegate ybPopupMenuDidDismiss];
  139. }
  140. self.delegate = nil;
  141. [self removeFromSuperview];
  142. [_menuBackView removeFromSuperview];
  143. }];
  144. }
  145. #pragma mark tableViewDelegate & dataSource
  146. - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
  147. {
  148. return _titles.count;
  149. }
  150. - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
  151. {
  152. static NSString * identifier = @"ybPopupMenu";
  153. YBPopupMenuCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
  154. if (!cell) {
  155. cell = [[YBPopupMenuCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:identifier];
  156. cell.textLabel.numberOfLines = 0;
  157. }
  158. cell.backgroundColor = [UIColor clearColor];
  159. cell.textLabel.textColor = _textColor;
  160. cell.textLabel.font = [UIFont systemFontOfSize:_fontSize];
  161. if ([_titles[indexPath.row] isKindOfClass:[NSAttributedString class]]) {
  162. cell.textLabel.attributedText = _titles[indexPath.row];
  163. }else if ([_titles[indexPath.row] isKindOfClass:[NSString class]]) {
  164. cell.textLabel.text = _titles[indexPath.row];
  165. }else {
  166. cell.textLabel.text = nil;
  167. }
  168. cell.separatorColor = _separatorColor;
  169. if (_images.count >= indexPath.row + 1) {
  170. if ([_images[indexPath.row] isKindOfClass:[NSString class]]) {
  171. cell.imageView.image = [UIImage imageNamed:_images[indexPath.row]];
  172. }else if ([_images[indexPath.row] isKindOfClass:[UIImage class]]){
  173. cell.imageView.image = _images[indexPath.row];
  174. }else {
  175. cell.imageView.image = nil;
  176. }
  177. }else {
  178. cell.imageView.image = nil;
  179. }
  180. return cell;
  181. }
  182. - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
  183. {
  184. [tableView deselectRowAtIndexPath:indexPath animated:YES];
  185. if (_dismissOnSelected) [self dismiss];
  186. if (self.delegate && [self.delegate respondsToSelector:@selector(ybPopupMenuDidSelectedAtIndex:ybPopupMenu:)]) {
  187. [self.delegate ybPopupMenuDidSelectedAtIndex:indexPath.row ybPopupMenu:self];
  188. }
  189. }
  190. #pragma mark - scrollViewDelegate
  191. - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
  192. {
  193. YBPopupMenuCell *cell = [self getLastVisibleCell];
  194. cell.isShowSeparator = YES;
  195. }
  196. - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
  197. {
  198. YBPopupMenuCell *cell = [self getLastVisibleCell];
  199. cell.isShowSeparator = NO;
  200. }
  201. - (YBPopupMenuCell *)getLastVisibleCell
  202. {
  203. NSArray <NSIndexPath *>*indexPaths = [self.tableView indexPathsForVisibleRows];
  204. indexPaths = [indexPaths sortedArrayUsingComparator:^NSComparisonResult(NSIndexPath * _Nonnull obj1, NSIndexPath * _Nonnull obj2) {
  205. return obj1.row < obj2.row;
  206. }];
  207. NSIndexPath *indexPath = indexPaths.firstObject;
  208. return [self.tableView cellForRowAtIndexPath:indexPath];
  209. }
  210. #pragma mark - privates
  211. - (void)show
  212. {
  213. [YBMainWindow addSubview:_menuBackView];
  214. [YBMainWindow addSubview:self];
  215. YBPopupMenuCell *cell = [self getLastVisibleCell];
  216. cell.isShowSeparator = NO;
  217. if (self.delegate && [self.delegate respondsToSelector:@selector(ybPopupMenuBeganShow)]) {
  218. [self.delegate ybPopupMenuBeganShow];
  219. }
  220. self.layer.affineTransform = CGAffineTransformMakeScale(0.1, 0.1);
  221. [UIView animateWithDuration: 0.25 animations:^{
  222. self.layer.affineTransform = CGAffineTransformMakeScale(1.0, 1.0);
  223. self.alpha = 1;
  224. _menuBackView.alpha = 1;
  225. } completion:^(BOOL finished) {
  226. if (self.delegate && [self.delegate respondsToSelector:@selector(ybPopupMenuDidShow)]) {
  227. [self.delegate ybPopupMenuDidShow];
  228. }
  229. }];
  230. }
  231. - (void)setDefaultSettings
  232. {
  233. _cornerRadius = 5.0;
  234. _rectCorner = UIRectCornerAllCorners;
  235. self.isShowShadow = YES;
  236. _dismissOnSelected = YES;
  237. _dismissOnTouchOutside = YES;
  238. _fontSize = 15;
  239. _textColor = [UIColor blackColor];
  240. _offset = 0.0;
  241. _relyRect = CGRectZero;
  242. _point = CGPointZero;
  243. _borderWidth = 0.0;
  244. _borderColor = [UIColor lightGrayColor];
  245. _arrowWidth = 15.0;
  246. _arrowHeight = 10.0;
  247. _backColor = [UIColor whiteColor];
  248. _type = YBPopupMenuTypeDefault;
  249. _arrowDirection = YBPopupMenuArrowDirectionTop;
  250. _priorityDirection = YBPopupMenuPriorityDirectionTop;
  251. _minSpace = 10.0;
  252. _maxVisibleCount = 5;
  253. _itemHeight = 44;
  254. _isCornerChanged = NO;
  255. _showMaskView = YES;
  256. _menuBackView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, YBScreenWidth, YBScreenHeight)];
  257. _menuBackView.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.1];
  258. _menuBackView.alpha = 0;
  259. UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget: self action: @selector(touchOutSide)];
  260. [_menuBackView addGestureRecognizer: tap];
  261. self.alpha = 0;
  262. self.backgroundColor = [UIColor clearColor];
  263. [self addSubview:self.tableView];
  264. }
  265. - (UITableView *)tableView
  266. {
  267. if (!_tableView) {
  268. _tableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStylePlain];
  269. _tableView.backgroundColor = [UIColor clearColor];
  270. _tableView.tableFooterView = [UIView new];
  271. _tableView.delegate = self;
  272. _tableView.dataSource = self;
  273. _tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
  274. }
  275. return _tableView;
  276. }
  277. - (void)touchOutSide
  278. {
  279. if (_dismissOnTouchOutside) {
  280. [self dismiss];
  281. }
  282. }
  283. - (void)setIsShowShadow:(BOOL)isShowShadow
  284. {
  285. _isShowShadow = isShowShadow;
  286. self.layer.shadowOpacity = isShowShadow ? 0.5 : 0;
  287. self.layer.shadowOffset = CGSizeMake(0, 0);
  288. self.layer.shadowRadius = isShowShadow ? 2.0 : 0;
  289. }
  290. - (void)setShowMaskView:(BOOL)showMaskView
  291. {
  292. _showMaskView = showMaskView;
  293. _menuBackView.backgroundColor = showMaskView ? [[UIColor blackColor] colorWithAlphaComponent:0.1] : [UIColor clearColor];
  294. }
  295. - (void)setType:(YBPopupMenuType)type
  296. {
  297. _type = type;
  298. switch (type) {
  299. case YBPopupMenuTypeDark:
  300. {
  301. _textColor = [UIColor lightGrayColor];
  302. _backColor = [UIColor colorWithRed:0.25 green:0.27 blue:0.29 alpha:1];
  303. _separatorColor = [UIColor lightGrayColor];
  304. }
  305. break;
  306. default:
  307. {
  308. _textColor = [UIColor blackColor];
  309. _backColor = [UIColor whiteColor];
  310. _separatorColor = [UIColor lightGrayColor];
  311. }
  312. break;
  313. }
  314. [self updateUI];
  315. }
  316. - (void)setFontSize:(CGFloat)fontSize
  317. {
  318. _fontSize = fontSize;
  319. [self.tableView reloadData];
  320. }
  321. - (void)setTextColor:(UIColor *)textColor
  322. {
  323. _textColor = textColor;
  324. [self.tableView reloadData];
  325. }
  326. - (void)setPoint:(CGPoint)point
  327. {
  328. _point = point;
  329. [self updateUI];
  330. }
  331. - (void)setItemWidth:(CGFloat)itemWidth
  332. {
  333. _itemWidth = itemWidth;
  334. [self updateUI];
  335. }
  336. - (void)setItemHeight:(CGFloat)itemHeight
  337. {
  338. _itemHeight = itemHeight;
  339. self.tableView.rowHeight = itemHeight;
  340. [self updateUI];
  341. }
  342. - (void)setBorderWidth:(CGFloat)borderWidth
  343. {
  344. _borderWidth = borderWidth;
  345. [self updateUI];
  346. }
  347. - (void)setBorderColor:(UIColor *)borderColor
  348. {
  349. _borderColor = borderColor;
  350. [self updateUI];
  351. }
  352. - (void)setArrowPosition:(CGFloat)arrowPosition
  353. {
  354. _arrowPosition = arrowPosition;
  355. [self updateUI];
  356. }
  357. - (void)setArrowWidth:(CGFloat)arrowWidth
  358. {
  359. _arrowWidth = arrowWidth;
  360. [self updateUI];
  361. }
  362. - (void)setArrowHeight:(CGFloat)arrowHeight
  363. {
  364. _arrowHeight = arrowHeight;
  365. [self updateUI];
  366. }
  367. - (void)setArrowDirection:(YBPopupMenuArrowDirection)arrowDirection
  368. {
  369. _arrowDirection = arrowDirection;
  370. [self updateUI];
  371. }
  372. - (void)setMaxVisibleCount:(NSInteger)maxVisibleCount
  373. {
  374. _maxVisibleCount = maxVisibleCount;
  375. [self updateUI];
  376. }
  377. - (void)setBackColor:(UIColor *)backColor
  378. {
  379. _backColor = backColor;
  380. [self updateUI];
  381. }
  382. - (void)setTitles:(NSArray *)titles
  383. {
  384. _titles = titles;
  385. [self updateUI];
  386. }
  387. - (void)setImages:(NSArray *)images
  388. {
  389. _images = images;
  390. [self updateUI];
  391. }
  392. - (void)setPriorityDirection:(YBPopupMenuPriorityDirection)priorityDirection
  393. {
  394. _priorityDirection = priorityDirection;
  395. [self updateUI];
  396. }
  397. - (void)setRectCorner:(UIRectCorner)rectCorner
  398. {
  399. _rectCorner = rectCorner;
  400. [self updateUI];
  401. }
  402. - (void)setCornerRadius:(CGFloat)cornerRadius
  403. {
  404. _cornerRadius = cornerRadius;
  405. [self updateUI];
  406. }
  407. - (void)setOffset:(CGFloat)offset
  408. {
  409. _offset = offset;
  410. [self updateUI];
  411. }
  412. - (void)updateUI
  413. {
  414. CGFloat height;
  415. if (_titles.count > _maxVisibleCount) {
  416. height = _itemHeight * _maxVisibleCount + _borderWidth * 2;
  417. self.tableView.bounces = YES;
  418. }else {
  419. height = _itemHeight * _titles.count + _borderWidth * 2;
  420. self.tableView.bounces = NO;
  421. }
  422. _isChangeDirection = NO;
  423. if (_priorityDirection == YBPopupMenuPriorityDirectionTop) {
  424. if (_point.y + height + _arrowHeight > YBScreenHeight - _minSpace) {
  425. _arrowDirection = YBPopupMenuArrowDirectionBottom;
  426. _isChangeDirection = YES;
  427. }else {
  428. _arrowDirection = YBPopupMenuArrowDirectionTop;
  429. _isChangeDirection = NO;
  430. }
  431. }else if (_priorityDirection == YBPopupMenuPriorityDirectionBottom) {
  432. if (_point.y - height - _arrowHeight < _minSpace) {
  433. _arrowDirection = YBPopupMenuArrowDirectionTop;
  434. _isChangeDirection = YES;
  435. }else {
  436. _arrowDirection = YBPopupMenuArrowDirectionBottom;
  437. _isChangeDirection = NO;
  438. }
  439. }else if (_priorityDirection == YBPopupMenuPriorityDirectionLeft) {
  440. if (_point.x + _itemWidth + _arrowHeight > YBScreenWidth - _minSpace) {
  441. _arrowDirection = YBPopupMenuArrowDirectionRight;
  442. _isChangeDirection = YES;
  443. }else {
  444. _arrowDirection = YBPopupMenuArrowDirectionLeft;
  445. _isChangeDirection = NO;
  446. }
  447. }else if (_priorityDirection == YBPopupMenuPriorityDirectionRight) {
  448. if (_point.x - _itemWidth - _arrowHeight < _minSpace) {
  449. _arrowDirection = YBPopupMenuArrowDirectionLeft;
  450. _isChangeDirection = YES;
  451. }else {
  452. _arrowDirection = YBPopupMenuArrowDirectionRight;
  453. _isChangeDirection = NO;
  454. }
  455. }
  456. [self setArrowPosition];
  457. [self setRelyRect];
  458. if (_arrowDirection == YBPopupMenuArrowDirectionTop) {
  459. CGFloat y = _isChangeDirection ? _point.y : _point.y;
  460. if (_arrowPosition > _itemWidth / 2) {
  461. self.frame = CGRectMake(YBScreenWidth - _minSpace - _itemWidth, y, _itemWidth, height + _arrowHeight);
  462. }else if (_arrowPosition < _itemWidth / 2) {
  463. self.frame = CGRectMake(_minSpace, y, _itemWidth, height + _arrowHeight);
  464. }else {
  465. self.frame = CGRectMake(_point.x - _itemWidth / 2, y, _itemWidth, height + _arrowHeight);
  466. }
  467. }else if (_arrowDirection == YBPopupMenuArrowDirectionBottom) {
  468. CGFloat y = _isChangeDirection ? _point.y - _arrowHeight - height : _point.y - _arrowHeight - height;
  469. if (_arrowPosition > _itemWidth / 2) {
  470. self.frame = CGRectMake(YBScreenWidth - _minSpace - _itemWidth, y, _itemWidth, height + _arrowHeight);
  471. }else if (_arrowPosition < _itemWidth / 2) {
  472. self.frame = CGRectMake(_minSpace, y, _itemWidth, height + _arrowHeight);
  473. }else {
  474. self.frame = CGRectMake(_point.x - _itemWidth / 2, y, _itemWidth, height + _arrowHeight);
  475. }
  476. }else if (_arrowDirection == YBPopupMenuArrowDirectionLeft) {
  477. CGFloat x = _isChangeDirection ? _point.x : _point.x;
  478. if (_arrowPosition < _itemHeight / 2) {
  479. self.frame = CGRectMake(x, _point.y - _arrowPosition, _itemWidth + _arrowHeight, height);
  480. }else if (_arrowPosition > _itemHeight / 2) {
  481. self.frame = CGRectMake(x, _point.y - _arrowPosition, _itemWidth + _arrowHeight, height);
  482. }else {
  483. self.frame = CGRectMake(x, _point.y - _arrowPosition, _itemWidth + _arrowHeight, height);
  484. }
  485. }else if (_arrowDirection == YBPopupMenuArrowDirectionRight) {
  486. CGFloat x = _isChangeDirection ? _point.x - _itemWidth - _arrowHeight : _point.x - _itemWidth - _arrowHeight;
  487. if (_arrowPosition < _itemHeight / 2) {
  488. self.frame = CGRectMake(x, _point.y - _arrowPosition, _itemWidth + _arrowHeight, height);
  489. }else if (_arrowPosition > _itemHeight / 2) {
  490. self.frame = CGRectMake(x, _point.y - _arrowPosition, _itemWidth + _arrowHeight, height);
  491. }else {
  492. self.frame = CGRectMake(x, _point.y - _arrowPosition, _itemWidth + _arrowHeight, height);
  493. }
  494. }else if (_arrowDirection == YBPopupMenuArrowDirectionNone) {
  495. }
  496. if (_isChangeDirection) {
  497. [self changeRectCorner];
  498. }
  499. [self setAnchorPoint];
  500. [self setOffset];
  501. [self.tableView reloadData];
  502. [self setNeedsDisplay];
  503. }
  504. - (void)setRelyRect
  505. {
  506. if (CGRectEqualToRect(_relyRect, CGRectZero)) {
  507. return;
  508. }
  509. if (_arrowDirection == YBPopupMenuArrowDirectionTop) {
  510. _point.y = _relyRect.size.height + _relyRect.origin.y;
  511. }else if (_arrowDirection == YBPopupMenuArrowDirectionBottom) {
  512. _point.y = _relyRect.origin.y;
  513. }else if (_arrowDirection == YBPopupMenuArrowDirectionLeft) {
  514. _point = CGPointMake(_relyRect.origin.x + _relyRect.size.width, _relyRect.origin.y + _relyRect.size.height / 2);
  515. }else {
  516. _point = CGPointMake(_relyRect.origin.x, _relyRect.origin.y + _relyRect.size.height / 2);
  517. }
  518. }
  519. - (void)setFrame:(CGRect)frame
  520. {
  521. [super setFrame:frame];
  522. if (_arrowDirection == YBPopupMenuArrowDirectionTop) {
  523. self.tableView.frame = CGRectMake(_borderWidth, _borderWidth + _arrowHeight, frame.size.width - _borderWidth * 2, frame.size.height - _arrowHeight);
  524. }else if (_arrowDirection == YBPopupMenuArrowDirectionBottom) {
  525. self.tableView.frame = CGRectMake(_borderWidth, _borderWidth, frame.size.width - _borderWidth * 2, frame.size.height - _arrowHeight);
  526. }else if (_arrowDirection == YBPopupMenuArrowDirectionLeft) {
  527. self.tableView.frame = CGRectMake(_borderWidth + _arrowHeight, _borderWidth , frame.size.width - _borderWidth * 2 - _arrowHeight, frame.size.height);
  528. }else if (_arrowDirection == YBPopupMenuArrowDirectionRight) {
  529. self.tableView.frame = CGRectMake(_borderWidth , _borderWidth , frame.size.width - _borderWidth * 2 - _arrowHeight, frame.size.height);
  530. }
  531. }
  532. - (void)changeRectCorner
  533. {
  534. if (_isCornerChanged || _rectCorner == UIRectCornerAllCorners) {
  535. return;
  536. }
  537. BOOL haveTopLeftCorner = NO, haveTopRightCorner = NO, haveBottomLeftCorner = NO, haveBottomRightCorner = NO;
  538. if (_rectCorner & UIRectCornerTopLeft) {
  539. haveTopLeftCorner = YES;
  540. }
  541. if (_rectCorner & UIRectCornerTopRight) {
  542. haveTopRightCorner = YES;
  543. }
  544. if (_rectCorner & UIRectCornerBottomLeft) {
  545. haveBottomLeftCorner = YES;
  546. }
  547. if (_rectCorner & UIRectCornerBottomRight) {
  548. haveBottomRightCorner = YES;
  549. }
  550. if (_arrowDirection == YBPopupMenuArrowDirectionTop || _arrowDirection == YBPopupMenuArrowDirectionBottom) {
  551. if (haveTopLeftCorner) {
  552. _rectCorner = _rectCorner | UIRectCornerBottomLeft;
  553. }else {
  554. _rectCorner = _rectCorner & (~UIRectCornerBottomLeft);
  555. }
  556. if (haveTopRightCorner) {
  557. _rectCorner = _rectCorner | UIRectCornerBottomRight;
  558. }else {
  559. _rectCorner = _rectCorner & (~UIRectCornerBottomRight);
  560. }
  561. if (haveBottomLeftCorner) {
  562. _rectCorner = _rectCorner | UIRectCornerTopLeft;
  563. }else {
  564. _rectCorner = _rectCorner & (~UIRectCornerTopLeft);
  565. }
  566. if (haveBottomRightCorner) {
  567. _rectCorner = _rectCorner | UIRectCornerTopRight;
  568. }else {
  569. _rectCorner = _rectCorner & (~UIRectCornerTopRight);
  570. }
  571. }else if (_arrowDirection == YBPopupMenuArrowDirectionLeft || _arrowDirection == YBPopupMenuArrowDirectionRight) {
  572. if (haveTopLeftCorner) {
  573. _rectCorner = _rectCorner | UIRectCornerTopRight;
  574. }else {
  575. _rectCorner = _rectCorner & (~UIRectCornerTopRight);
  576. }
  577. if (haveTopRightCorner) {
  578. _rectCorner = _rectCorner | UIRectCornerTopLeft;
  579. }else {
  580. _rectCorner = _rectCorner & (~UIRectCornerTopLeft);
  581. }
  582. if (haveBottomLeftCorner) {
  583. _rectCorner = _rectCorner | UIRectCornerBottomRight;
  584. }else {
  585. _rectCorner = _rectCorner & (~UIRectCornerBottomRight);
  586. }
  587. if (haveBottomRightCorner) {
  588. _rectCorner = _rectCorner | UIRectCornerBottomLeft;
  589. }else {
  590. _rectCorner = _rectCorner & (~UIRectCornerBottomLeft);
  591. }
  592. }
  593. _isCornerChanged = YES;
  594. }
  595. - (void)setOffset
  596. {
  597. if (_itemWidth == 0) return;
  598. CGRect originRect = self.frame;
  599. if (_arrowDirection == YBPopupMenuArrowDirectionTop) {
  600. originRect.origin.y += _offset;
  601. }else if (_arrowDirection == YBPopupMenuArrowDirectionBottom) {
  602. originRect.origin.y -= _offset;
  603. }else if (_arrowDirection == YBPopupMenuArrowDirectionLeft) {
  604. originRect.origin.x += _offset;
  605. }else if (_arrowDirection == YBPopupMenuArrowDirectionRight) {
  606. originRect.origin.x -= _offset;
  607. }
  608. self.frame = originRect;
  609. }
  610. - (void)setAnchorPoint
  611. {
  612. if (_itemWidth == 0) return;
  613. CGPoint point = CGPointMake(0.5, 0.5);
  614. if (_arrowDirection == YBPopupMenuArrowDirectionTop) {
  615. point = CGPointMake(_arrowPosition / _itemWidth, 0);
  616. }else if (_arrowDirection == YBPopupMenuArrowDirectionBottom) {
  617. point = CGPointMake(_arrowPosition / _itemWidth, 1);
  618. }else if (_arrowDirection == YBPopupMenuArrowDirectionLeft) {
  619. point = CGPointMake(0, (_itemHeight - _arrowPosition) / _itemHeight);
  620. }else if (_arrowDirection == YBPopupMenuArrowDirectionRight) {
  621. point = CGPointMake(1, (_itemHeight - _arrowPosition) / _itemHeight);
  622. }
  623. CGRect originRect = self.frame;
  624. self.layer.anchorPoint = point;
  625. self.frame = originRect;
  626. }
  627. - (void)setArrowPosition
  628. {
  629. if (_priorityDirection == YBPopupMenuPriorityDirectionNone) {
  630. return;
  631. }
  632. if (_arrowDirection == YBPopupMenuArrowDirectionTop || _arrowDirection == YBPopupMenuArrowDirectionBottom) {
  633. if (_point.x + _itemWidth / 2 > YBScreenWidth - _minSpace) {
  634. _arrowPosition = _itemWidth - (YBScreenWidth - _minSpace - _point.x);
  635. }else if (_point.x < _itemWidth / 2 + _minSpace) {
  636. _arrowPosition = _point.x - _minSpace;
  637. }else {
  638. _arrowPosition = _itemWidth / 2;
  639. }
  640. }else if (_arrowDirection == YBPopupMenuArrowDirectionLeft || _arrowDirection == YBPopupMenuArrowDirectionRight) {
  641. // if (_point.y + _itemHeight / 2 > YBScreenHeight - _minSpace) {
  642. // _arrowPosition = _itemHeight - (YBScreenHeight - _minSpace - _point.y);
  643. // }else if (_point.y < _itemHeight / 2 + _minSpace) {
  644. // _arrowPosition = _point.y - _minSpace;
  645. // }else {
  646. // _arrowPosition = _itemHeight / 2;
  647. // }
  648. }
  649. }
  650. - (void)drawRect:(CGRect)rect
  651. {
  652. UIBezierPath *bezierPath = [YBPopupMenuPath yb_bezierPathWithRect:rect rectCorner:_rectCorner cornerRadius:_cornerRadius borderWidth:_borderWidth borderColor:_borderColor backgroundColor:_backColor arrowWidth:_arrowWidth arrowHeight:_arrowHeight arrowPosition:_arrowPosition arrowDirection:_arrowDirection];
  653. [bezierPath fill];
  654. [bezierPath stroke];
  655. }
  656. @end