IQActionSheetPickerView.m 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554
  1. //
  2. // IQActionSheetPickerView.m
  3. // https://github.com/hackiftekhar/IQActionSheetPickerView
  4. // Copyright (c) 2013-14 Iftekhar Qurashi.
  5. //
  6. // Permission is hereby granted, free of charge, to any person obtaining a copy
  7. // of this software and associated documentation files (the "Software"), to deal
  8. // in the Software without restriction, including without limitation the rights
  9. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10. // copies of the Software, and to permit persons to whom the Software is
  11. // furnished to do so, subject to the following conditions:
  12. //
  13. // The above copyright notice and this permission notice shall be included in
  14. // all copies or substantial portions of the Software.
  15. //
  16. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  19. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22. // THE SOFTWARE.
  23. #import "IQActionSheetPickerView.h"
  24. #import <QuartzCore/QuartzCore.h>
  25. #import "IQActionSheetViewController.h"
  26. NSString * const kIQActionSheetAttributesForNormalStateKey = @"kIQActionSheetAttributesForNormalStateKey";
  27. /// Identifies an attributed string of the toolbar title for highlighted state.
  28. NSString * const kIQActionSheetAttributesForHighlightedStateKey = @"kIQActionSheetAttributesForHighlightedStateKey";
  29. @interface IQActionSheetPickerView ()<UIPickerViewDataSource,UIPickerViewDelegate>
  30. {
  31. UIPickerView *_pickerView;
  32. UIDatePicker *_datePicker;
  33. }
  34. @property(nonatomic,strong) NSArray* selectArray;
  35. @property(nonatomic, strong) IQActionSheetViewController *actionSheetController;
  36. @end
  37. @implementation IQActionSheetPickerView
  38. @synthesize actionSheetPickerStyle = _actionSheetPickerStyle;
  39. @synthesize titlesForComponents = _titlesForComponents;
  40. @synthesize widthsForComponents = _widthsForComponents;
  41. @synthesize isRangePickerView = _isRangePickerView;
  42. @synthesize delegate = _delegate;
  43. @synthesize date = _date;
  44. -(void)dealloc
  45. {
  46. [[NSNotificationCenter defaultCenter] removeObserver:self];
  47. }
  48. - (instancetype)initWithTitle:(NSString *)title delegate:(id<IQActionSheetPickerViewDelegate>)delegate
  49. {
  50. CGRect rect = [[UIScreen mainScreen] bounds];
  51. rect.size.height = 216+44;
  52. self = [super initWithFrame:rect];
  53. if (self)
  54. {
  55. self.clickBackHide = YES;
  56. self.pickBkgColor = HexColorFromRGBA(0x000000,0.5);
  57. //UIToolbar
  58. {
  59. self.actionToolbar = [[IQActionSheetToolbar alloc] initWithFrame:CGRectMake(0, 0, rect.size.width, 44)];
  60. self.actionToolbar.barStyle = UIBarStyleDefault;
  61. self.actionToolbar.cancelButton.target = self;
  62. self.actionToolbar.cancelButton.action = @selector(pickeryoupaifcancelClicked:);
  63. self.actionToolbar.doneButton.target = self;
  64. self.actionToolbar.doneButton.action = @selector(pickerDoneClicked:);
  65. self.actionToolbar.titleButton.title = title;
  66. [self addSubview:self.actionToolbar];
  67. }
  68. //UIPickerView
  69. {
  70. _pickerView = [[UIPickerView alloc] initWithFrame:CGRectMake(0, CGRectGetMaxY(_actionToolbar.frame) , CGRectGetWidth(_actionToolbar.frame), 216)];
  71. _pickerView.backgroundColor = [UIColor whiteColor];
  72. [_pickerView setShowsSelectionIndicator:NO];
  73. [_pickerView setDelegate:self];
  74. [_pickerView setDataSource:self];
  75. [self addSubview:_pickerView];
  76. }
  77. //UIDatePicker
  78. {
  79. _datePicker = [[UIDatePicker alloc] initWithFrame:_pickerView.frame];
  80. [_datePicker addTarget:self action:@selector(dateChanged:) forControlEvents:UIControlEventValueChanged];
  81. _datePicker.frame = _pickerView.frame;
  82. [_datePicker setDatePickerMode:UIDatePickerModeDate];
  83. [self addSubview:_datePicker];
  84. }
  85. //Initial settings
  86. {
  87. self.backgroundColor = [UIColor colorWithWhite:1.0 alpha:0.8];
  88. [self setFrame:CGRectMake(0, 0, CGRectGetWidth(_pickerView.frame), CGRectGetMaxY(_pickerView.frame))];
  89. [self setActionSheetPickerStyle:IQActionSheetPickerStyleTextPicker];
  90. self.autoresizingMask = UIViewAutoresizingFlexibleTopMargin|UIViewAutoresizingFlexibleWidth;
  91. _actionToolbar.autoresizingMask = UIViewAutoresizingFlexibleWidth;
  92. _pickerView.autoresizingMask = UIViewAutoresizingFlexibleWidth;
  93. _datePicker.autoresizingMask = UIViewAutoresizingFlexibleWidth;
  94. }
  95. }
  96. _delegate = delegate;
  97. return self;
  98. }
  99. -(void)setActionSheetPickerStyle:(IQActionSheetPickerStyle)actionSheetPickerStyle
  100. {
  101. _actionSheetPickerStyle = actionSheetPickerStyle;
  102. switch (actionSheetPickerStyle) {
  103. case IQActionSheetPickerStyleTextPicker:
  104. [_pickerView setHidden:NO];
  105. [_datePicker setHidden:YES];
  106. break;
  107. case IQActionSheetPickerStyleDatePicker:
  108. [_pickerView setHidden:YES];
  109. [_datePicker setHidden:NO];
  110. [_datePicker setDatePickerMode:UIDatePickerModeDate];
  111. break;
  112. case IQActionSheetPickerStyleDateTimePicker:
  113. [_pickerView setHidden:YES];
  114. [_datePicker setHidden:NO];
  115. [_datePicker setDatePickerMode:UIDatePickerModeDateAndTime];
  116. break;
  117. case IQActionSheetPickerStyleTimePicker:
  118. [_pickerView setHidden:YES];
  119. [_datePicker setHidden:NO];
  120. [_datePicker setDatePickerMode:UIDatePickerModeTime];
  121. break;
  122. default:
  123. break;
  124. }
  125. }
  126. /**
  127. * Set Picker View Background Color
  128. *
  129. * @param pickerViewBackgroundColor Picker view custom background color
  130. */
  131. -(void)setPickerViewBackgroundColor:(UIColor *)pickerViewBackgroundColor{
  132. _pickerView.backgroundColor = pickerViewBackgroundColor;
  133. }
  134. /**
  135. * Set Cancel Button Title Attributes
  136. *
  137. * @param cancelButtonAttributes Cancel Button Title Attributes
  138. */
  139. -(void)setCancelButtonAttributes:(NSDictionary *)cancelButtonAttributes{
  140. id attributesForCancelButtonNormalState = [cancelButtonAttributes objectForKey:kIQActionSheetAttributesForNormalStateKey];
  141. if (attributesForCancelButtonNormalState != nil && [attributesForCancelButtonNormalState isKindOfClass:[NSDictionary class]]) {
  142. [_actionToolbar.cancelButton setTitleTextAttributes:(NSDictionary *)attributesForCancelButtonNormalState forState:UIControlStateNormal];
  143. }
  144. id attributesForCancelButtonnHighlightedState = [cancelButtonAttributes objectForKey: kIQActionSheetAttributesForHighlightedStateKey];
  145. if (attributesForCancelButtonnHighlightedState != nil && [attributesForCancelButtonnHighlightedState isKindOfClass:[NSDictionary class]]) {
  146. [_actionToolbar.cancelButton setTitleTextAttributes:(NSDictionary *)attributesForCancelButtonnHighlightedState forState:UIControlStateHighlighted];
  147. }
  148. }
  149. /**
  150. * Set Done Button Title Attributes
  151. *
  152. * @param cancelButtonAttributes Done Button Title Attributes
  153. */
  154. -(void)setDoneButtonAttributes:(NSDictionary *)doneButtonAttributes{
  155. id attributesForDoneButtonNormalState = [doneButtonAttributes objectForKey:kIQActionSheetAttributesForNormalStateKey];
  156. if (attributesForDoneButtonNormalState != nil && [attributesForDoneButtonNormalState isKindOfClass:[NSDictionary class]]) {
  157. [_actionToolbar.doneButton setTitleTextAttributes:(NSDictionary *)attributesForDoneButtonNormalState forState:UIControlStateNormal];
  158. }
  159. id attributesForDoneButtonnHighlightedState = [doneButtonAttributes objectForKey: kIQActionSheetAttributesForHighlightedStateKey];
  160. if (attributesForDoneButtonnHighlightedState != nil && [attributesForDoneButtonnHighlightedState isKindOfClass:[NSDictionary class]]) {
  161. [_actionToolbar.doneButton setTitleTextAttributes:(NSDictionary *)attributesForDoneButtonnHighlightedState forState:UIControlStateHighlighted];
  162. }
  163. }
  164. /**
  165. * Set Action Bar Color
  166. *
  167. * @param barColor Custom color for toolBar
  168. */
  169. -(void)setToolbarTintColor:(UIColor *)toolbarTintColor{
  170. _toolbarTintColor = toolbarTintColor;
  171. [_actionToolbar setBarTintColor:toolbarTintColor];
  172. }
  173. /**
  174. * Set Action Tool Bar Button Color
  175. *
  176. * @param buttonColor Custom color for toolBar button
  177. */
  178. -(void)setToolbarButtonColor:(UIColor *)toolbarButtonColor{
  179. _toolbarButtonColor = toolbarButtonColor;
  180. [_actionToolbar setTintColor:toolbarButtonColor];
  181. }
  182. /*!
  183. Font for the UIPickerView
  184. */
  185. - (void)setTitleFont:(UIFont *)titleFont {
  186. _titleFont = titleFont;
  187. _actionToolbar.titleButton.font = titleFont;
  188. }
  189. /*!
  190. * Color for the UIPickerView
  191. */
  192. - (void)setTitleColor:(UIColor *)titleColor {
  193. _titleColor = titleColor;
  194. _actionToolbar.titleButton.titleColor = titleColor;
  195. }
  196. #pragma mark - Done/Cancel
  197. -(void)pickeryoupaifcancelClicked:(UIBarButtonItem*)barButton
  198. {
  199. if ([self.delegate respondsToSelector:@selector(actionSheetPickerViewWillCancel:)])
  200. {
  201. [self.delegate actionSheetPickerViewWillCancel:self];
  202. }
  203. [self dismissWithCompletion:^{
  204. if ([self.delegate respondsToSelector:@selector(actionSheetPickerViewDidCancel:)])
  205. {
  206. [self.delegate actionSheetPickerViewDidCancel:self];
  207. }
  208. }];
  209. }
  210. -(void)pickerDoneClicked:(UIBarButtonItem*)barButton
  211. {
  212. switch (_actionSheetPickerStyle)
  213. {
  214. case IQActionSheetPickerStyleTextPicker:
  215. {
  216. NSMutableArray *selectedTitles = [[NSMutableArray alloc] init];
  217. for (NSInteger component = 0; component<_pickerView.numberOfComponents; component++)
  218. {
  219. NSInteger row = [_pickerView selectedRowInComponent:component];
  220. if (row!= -1)
  221. {
  222. [selectedTitles addObject:_titlesForComponents[component][row]];
  223. }
  224. else
  225. {
  226. [selectedTitles addObject:[NSNull null]];
  227. }
  228. }
  229. [self setSelectedTitles:selectedTitles];
  230. if ([self.delegate respondsToSelector:@selector(actionSheetPickerView:didSelectTitles:)])
  231. {
  232. [self.delegate actionSheetPickerView:self didSelectTitles:selectedTitles];
  233. }
  234. }
  235. break;
  236. case IQActionSheetPickerStyleDatePicker:
  237. case IQActionSheetPickerStyleDateTimePicker:
  238. case IQActionSheetPickerStyleTimePicker:
  239. {
  240. [self setDate:_datePicker.date];
  241. [self setSelectedTitles:@[_datePicker.date]];
  242. if ([self.delegate respondsToSelector:@selector(actionSheetPickerView:didSelectDate:)])
  243. {
  244. [self.delegate actionSheetPickerView:self didSelectDate:_datePicker.date];
  245. }
  246. }
  247. default:
  248. break;
  249. }
  250. [self dismiss];
  251. }
  252. #pragma mark - IQActionSheetPickerStyleDatePicker / IQActionSheetPickerStyleDateTimePicker / IQActionSheetPickerStyleTimePicker
  253. -(void)dateChanged:(UIDatePicker*)datePicker
  254. {
  255. [self sendActionsForControlEvents:UIControlEventValueChanged];
  256. }
  257. -(void) setDate:(NSDate *)date
  258. {
  259. [self setDate:date animated:NO];
  260. }
  261. -(void)setDate:(NSDate *)date animated:(BOOL)animated
  262. {
  263. _date = date;
  264. if (_date != nil) [_datePicker setDate:_date animated:animated];
  265. }
  266. -(void)setMinimumDate:(NSDate *)minimumDate
  267. {
  268. _minimumDate = minimumDate;
  269. _datePicker.minimumDate = minimumDate;
  270. }
  271. -(void)setMaximumDate:(NSDate *)maximumDate
  272. {
  273. _maximumDate = maximumDate;
  274. _datePicker.maximumDate = maximumDate;
  275. }
  276. #pragma mark - IQActionSheetPickerStyleTextPicker
  277. -(void)reloadComponent:(NSInteger)component
  278. {
  279. [_pickerView reloadComponent:component];
  280. }
  281. -(void)reloadAllComponents
  282. {
  283. [_pickerView reloadAllComponents];
  284. }
  285. -(void)setSelectedTitles:(NSArray *)selectedTitles
  286. {
  287. [self setSelectedTitles:selectedTitles animated:NO];
  288. }
  289. -(NSArray *)selectedTitles
  290. {
  291. if (_actionSheetPickerStyle == IQActionSheetPickerStyleTextPicker)
  292. {
  293. NSMutableArray *selectedTitles = [[NSMutableArray alloc] init];
  294. NSUInteger totalComponent = _pickerView.numberOfComponents;
  295. for (NSInteger component = 0; component<totalComponent; component++)
  296. {
  297. NSInteger selectedRow = [_pickerView selectedRowInComponent:component];
  298. if (selectedRow == -1)
  299. {
  300. [selectedTitles addObject:[NSNull null]];
  301. }
  302. else
  303. {
  304. NSArray *items = _titlesForComponents[component];
  305. if ([items count] > selectedRow)
  306. {
  307. id selectTitle = items[selectedRow];
  308. [selectedTitles addObject:selectTitle];
  309. }
  310. else
  311. {
  312. [selectedTitles addObject:[NSNull null]];
  313. }
  314. }
  315. }
  316. return selectedTitles;
  317. }
  318. else
  319. {
  320. return nil;
  321. }
  322. }
  323. -(void)setSelectedTitles:(NSArray *)selectedTitles animated:(BOOL)animated
  324. {
  325. if (_actionSheetPickerStyle == IQActionSheetPickerStyleTextPicker)
  326. {
  327. NSUInteger totalComponent = MIN(selectedTitles.count, _pickerView.numberOfComponents);
  328. for (NSInteger component = 0; component<totalComponent; component++)
  329. {
  330. NSArray *items = _titlesForComponents[component];
  331. id selectTitle = selectedTitles[component];
  332. if ([items containsObject:selectTitle])
  333. {
  334. NSUInteger rowIndex = [items indexOfObject:selectTitle];
  335. [_pickerView selectRow:rowIndex inComponent:component animated:animated];
  336. }
  337. }
  338. }
  339. }
  340. -(void)selectIndexes:(NSArray *)indexes animated:(BOOL)animated
  341. {
  342. if (_actionSheetPickerStyle == IQActionSheetPickerStyleTextPicker)
  343. {
  344. NSUInteger totalComponent = MIN(indexes.count, _pickerView.numberOfComponents);
  345. for (NSInteger component = 0; component<totalComponent; component++)
  346. {
  347. NSArray *items = _titlesForComponents[component];
  348. NSUInteger selectIndex = [indexes[component] unsignedIntegerValue];
  349. if (selectIndex < items.count)
  350. {
  351. [_pickerView selectRow:selectIndex inComponent:component animated:animated];
  352. }
  353. }
  354. }
  355. }
  356. #pragma mark - UIPickerView delegate/dataSource
  357. - (CGFloat)pickerView:(UIPickerView *)pickerView rowHeightForComponent:(NSInteger)component{
  358. return 50;
  359. }
  360. - (CGFloat)pickerView:(UIPickerView *)pickerView widthForComponent:(NSInteger)component
  361. {
  362. //If having widths
  363. if (_widthsForComponents)
  364. {
  365. CGFloat width = [_widthsForComponents[component] floatValue];
  366. //If width is 0, then calculating it's size.
  367. if (width <= 0)
  368. return ((pickerView.bounds.size.width-20)-2*(_titlesForComponents.count-1))/_titlesForComponents.count;
  369. //Else returning it's width.
  370. else
  371. return width;
  372. }
  373. //Else calculating it's size.
  374. else
  375. {
  376. return ((pickerView.bounds.size.width-20)-2*(_titlesForComponents.count-1))/_titlesForComponents.count;
  377. }
  378. }
  379. - (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView
  380. {
  381. return [_titlesForComponents count];
  382. }
  383. - (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
  384. {
  385. return _titlesForComponents[component].count;
  386. }
  387. -(UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view
  388. { //扩展修改线的颜色
  389. for(UIView *singleLine in pickerView.subviews)
  390. {
  391. if (singleLine.frame.size.height < 1)
  392. {
  393. singleLine.backgroundColor = self.lineColor;
  394. singleLine.frame = CGRectMake(KScreenWidth/2-self.lineSize.width/2,singleLine.frame.origin.y,self.lineSize.width, self.lineSize.height);
  395. }
  396. }
  397. UILabel *labelText = [[UILabel alloc] init];
  398. if(self.pickerComponentsColor != nil) {
  399. labelText.textColor = self.pickerComponentsColor;
  400. }
  401. if(self.pickerComponentsFont == nil){
  402. labelText.font = [UIFont boldSystemFontOfSize:20.0];
  403. }else{
  404. labelText.font = self.pickerComponentsFont;
  405. }
  406. labelText.backgroundColor = [UIColor clearColor];
  407. [labelText setTextAlignment:NSTextAlignmentCenter];
  408. [labelText setText:_titlesForComponents[component][row]];
  409. return labelText;
  410. }
  411. - (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
  412. {
  413. UILabel* label = (UILabel*)[pickerView viewForRow:row forComponent:component];
  414. if(self.pickerComponentsSelectColor != nil) {
  415. label.textColor = self.pickerComponentsSelectColor;
  416. }
  417. if (_isRangePickerView && pickerView.numberOfComponents == 3)
  418. {
  419. if (component == 0)
  420. {
  421. [pickerView selectRow:MAX([pickerView selectedRowInComponent:2], row) inComponent:2 animated:YES];
  422. self.selectArray = _titlesForComponents[row+1];
  423. }
  424. else if (component == 2)
  425. {
  426. [pickerView selectRow:MIN([pickerView selectedRowInComponent:0], row) inComponent:0 animated:YES];
  427. }
  428. }
  429. [self sendActionsForControlEvents:UIControlEventValueChanged];
  430. if ([self.delegate respondsToSelector:@selector(actionSheetPickerView:didChangeRow:inComponent:)]) {
  431. [self.delegate actionSheetPickerView:self didChangeRow:row inComponent:component];
  432. }
  433. }
  434. #pragma mark - show/Hide
  435. -(void)dismiss
  436. {
  437. [_actionSheetController dismissWithCompletion:nil];
  438. _actionSheetController = nil;
  439. }
  440. -(void)dismissWithCompletion:(void (^)(void))completion
  441. {
  442. [_actionSheetController dismissWithCompletion:completion];
  443. _actionSheetController = nil;
  444. }
  445. -(void)show
  446. {
  447. [self showWithCompletion:nil];
  448. }
  449. -(void)showWithCompletion:(void (^)(void))completion
  450. {
  451. [_pickerView reloadAllComponents];
  452. if (_actionSheetController == nil)
  453. {
  454. _actionSheetController = [[IQActionSheetViewController alloc] init];
  455. [_actionSheetController showPickerView:self completion:completion];
  456. }
  457. }
  458. @end