Aucune description

PindanSelectDetailView.m 29KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755
  1. //
  2. // SelectDetailView.m
  3. // FirstLink
  4. //
  5. // Created by 王孝道 on 15/5/28.
  6. // Copyright (c) 2015年 FirstLink. All rights reserved.
  7. //
  8. #import "PindanSelectDetailView.h"
  9. #import "FirstLinkAppDelegate.h"
  10. #import "PindanSpecItem.h"
  11. #define kDurationTime 0.3f
  12. #define kSpecBtnTagBase 100
  13. #define kSpecBtnfontsize 13
  14. #define KSpecBtnTitleMargin 15 // 文字距离边框边距
  15. #define kNumChangeBtnTagBase 50
  16. @interface PindanSelectDetailView (){
  17. UIButton *_selectedSpecBtn; // 选中的规格按钮
  18. }
  19. @property (nonatomic, strong) PindanDetailViewModel *viewModel;
  20. @property (nonatomic, strong) UIView *contentView;
  21. @property (nonatomic, strong) UIScrollView *specScrollView; //规格和数量滑动scrollView
  22. @property (nonatomic, strong) UITextField *numField;
  23. @property (nonatomic, strong) UILabel *detailLabel;
  24. @property (nonatomic, strong) UILabel *numLabel;
  25. @property (nonatomic, strong) UIButton *basketBtn;
  26. @property (nonatomic, strong) CAAnimationGroup *groupAnim;
  27. @property (nonatomic, strong) NSMutableArray *animImgViewArray;
  28. @property (nonatomic, strong) UIView *middleLine;
  29. @property (nonatomic, assign) BOOL isEnd; // 是否已经结束
  30. @property (nonatomic, strong) UIImageView *vipImageIcon;
  31. @end
  32. @implementation PindanSelectDetailView
  33. @synthesize imageView = _imageView;
  34. @synthesize priceLabel = _priceLabel;
  35. - (instancetype)initWithFrame:(CGRect)frame {
  36. self = [super initWithFrame:frame];
  37. if (self) {
  38. UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(tapGestureClick:)];
  39. [self addGestureRecognizer:tap];
  40. _isEnd = NO;
  41. }
  42. return self;
  43. }
  44. - (instancetype)initWithViewModel:(PindanDetailViewModel *)viewModel {
  45. self = [super init];
  46. if (self) {
  47. _viewModel = viewModel;
  48. _specsArray = [_viewModel specsArray];
  49. _limitedAmount = [_viewModel limiteNum];
  50. _nationalPostage = [_viewModel internationalPostage].floatValue;
  51. }
  52. return self;
  53. }
  54. + (NSString *)cdnImgUrlStringWithString:(NSString *)imgUrl {
  55. return [NSString stringWithFormat:@"%@%@", imgUrl,
  56. [FLStringHelper cdnParamaterString:80
  57. height:80]];
  58. }
  59. - (void)initialLayoutWithState:(ProductState)state{
  60. self.isEnd = state == ProductStateNormal ? NO : YES;
  61. UIButton *cancelBtn = ({
  62. UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
  63. [button setImage:[UIImage imageNamed:@"withasingle_body_delete_n"] forState:UIControlStateNormal];
  64. [button addTarget:self action:@selector(cancelBtnClick) forControlEvents:UIControlEventTouchUpInside];
  65. button;
  66. });
  67. UIButton *confirmBtn = ({
  68. UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
  69. [button setTitle:@"加入购物篮" forState:UIControlStateNormal];
  70. [button setBackgroundColor:self.isEnd ? UIColorFromRGB(0xe5e5e5) : UIColorFromRGB(0xff6362)];
  71. [button addTarget:self action:@selector(confirmBtnClick) forControlEvents:UIControlEventTouchUpInside];
  72. button.layer.cornerRadius = 5;
  73. if (self.isEnd) button.enabled = NO;
  74. button;
  75. });
  76. [self addSubview:self.contentView];
  77. [self.contentView addSubview:cancelBtn];
  78. [self.contentView addSubview:self.middleLine];
  79. [self.contentView addSubview:self.imageView];
  80. [self.contentView addSubview:self.priceLabel];
  81. [self.contentView addSubview:self.detailLabel];
  82. [self.contentView addSubview:self.specScrollView];
  83. [self.contentView addSubview:confirmBtn];
  84. [self.contentView addSubview:self.basketBtn];
  85. [self.contentView addSubview:self.numLabel];
  86. UIView *superView = self.contentView;
  87. [cancelBtn mas_makeConstraints:^(MASConstraintMaker *make) {
  88. make.top.equalTo(superView).offset(10);
  89. make.right.equalTo(superView).offset(- 15);
  90. }];
  91. [self.imageView mas_makeConstraints:^(MASConstraintMaker *make) {
  92. make.left.equalTo(superView).offset(15);
  93. make.top.equalTo(superView).offset(- 15);
  94. make.width.height.equalTo(@80);
  95. }];
  96. [self.priceLabel mas_makeConstraints:^(MASConstraintMaker *make) {
  97. make.left.equalTo(self.imageView.mas_right).offset(15);
  98. make.top.equalTo(superView).offset(15);
  99. }];
  100. [self.contentView addSubview:self.vipImageIcon];
  101. [self.vipImageIcon mas_makeConstraints:^(MASConstraintMaker *make) {
  102. make.left.equalTo(self.priceLabel.mas_right).offset(10);
  103. make.centerY.equalTo(self.priceLabel).offset(0);
  104. }];
  105. [self.detailLabel mas_makeConstraints:^(MASConstraintMaker *make) {
  106. make.left.equalTo(self.priceLabel);
  107. make.bottom.equalTo(self.imageView).offset(- 5);
  108. }];
  109. [self.middleLine mas_makeConstraints:^(MASConstraintMaker *make) {
  110. make.left.equalTo(self.imageView);
  111. make.right.equalTo(cancelBtn);
  112. make.height.equalTo(@0.5);
  113. make.top.equalTo(self.imageView.mas_bottom).offset(5);
  114. }];
  115. [self.specScrollView mas_makeConstraints:^(MASConstraintMaker *make) {
  116. make.left.right.equalTo(superView);
  117. make.top.equalTo(self.middleLine.mas_bottom);
  118. make.height.equalTo(@130);
  119. }];
  120. [self.basketBtn mas_makeConstraints:^(MASConstraintMaker *make) {
  121. make.left.equalTo(self.middleLine);
  122. make.bottom.equalTo(superView).offset(- 10);
  123. make.width.height.mas_equalTo(35);
  124. }];
  125. [confirmBtn mas_makeConstraints:^(MASConstraintMaker *make) {
  126. make.left.equalTo(self.basketBtn.mas_right).offset(20);
  127. make.right.equalTo(self.middleLine);
  128. make.bottom.equalTo(superView).offset(- 10);
  129. make.height.equalTo(@35);
  130. }];
  131. [self.numLabel mas_makeConstraints:^(MASConstraintMaker *make) {
  132. make.centerX.equalTo(self.basketBtn).offset(15);
  133. make.centerY.equalTo(self.basketBtn).offset(- 12);
  134. make.size.mas_equalTo(CGSizeMake(15, 15));
  135. }];
  136. [self setInitialUIdata];
  137. [self layoutSpecScrollView];
  138. }
  139. - (void)setInitialUIdata
  140. {
  141. // 初始化默认数据
  142. self.numField.text = @"1";
  143. PindanSpecItem *specItem = [self specItemAtIndex:[self getFirstSelectedIndex]];
  144. if (specItem) {
  145. CGFloat unitPrice = 0;
  146. if ([self.viewModel isVIP] && specItem.vipPrice.length >0) {
  147. if ([specItem.vipPrice isKindOfClass:[NSString class]]) unitPrice = specItem.vipPrice.floatValue / 100.0f + self.nationalPostage / 100.0f;
  148. self.vipImageIcon.hidden = NO;
  149. } else {
  150. if ([specItem.price isKindOfClass:[NSString class]]) unitPrice = specItem.price.floatValue / 100.0f + self.nationalPostage / 100.0f;
  151. self.vipImageIcon.hidden = YES;
  152. }
  153. self.priceLabel.text = [NSString stringWithFormat:@"¥%.2f", unitPrice];
  154. self.detailLabel.text = specItem.name;
  155. [self.imageView sd_setImageWithURL:[NSURL URLWithString:[PindanSelectDetailView cdnImgUrlStringWithString:specItem.imgUrl]]];
  156. }
  157. }
  158. - (void)layoutSpecScrollView
  159. {
  160. UIView *superView = self.specScrollView;
  161. UILabel *speLabel = ({
  162. UILabel *label = [[UILabel alloc]init];
  163. label.text = @"规格";
  164. label.backgroundColor = [UIColor clearColor];
  165. label.textColor = UIColorFromRGB(0x333333);
  166. label.font = [UIFont systemFontOfSize:15];
  167. label.textAlignment = NSTextAlignmentCenter;
  168. label;
  169. });
  170. UILabel *numLabel = ({
  171. UILabel *label = [[UILabel alloc]init];
  172. label.backgroundColor = [UIColor clearColor];
  173. label.font = [UIFont systemFontOfSize:15];
  174. label.textColor = UIColorFromRGB(0x333333);
  175. label.text = @"数量";
  176. label;
  177. });
  178. UIButton *addButton = ({
  179. UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
  180. button.tag = kNumChangeBtnTagBase + 0;
  181. [button setImage:[UIImage imageNamed:@"specification_body_add_n"] forState:UIControlStateNormal];
  182. [button addTarget:self action:@selector(changNumBtnClick:) forControlEvents:UIControlEventTouchUpInside];
  183. button;
  184. });
  185. UIButton *reduceButton = ({
  186. UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
  187. button.tag = kNumChangeBtnTagBase + 1;
  188. [button setImage:[UIImage imageNamed:@"specification_body_lower_n"] forState:UIControlStateNormal];
  189. [button addTarget:self action:@selector(changNumBtnClick:) forControlEvents:UIControlEventTouchUpInside];
  190. button;
  191. });
  192. UIView *containerView = [[UIView alloc]init]; // 放颜色规格按钮
  193. containerView.backgroundColor = [UIColor clearColor];
  194. CGFloat containerH = [self heigtForAllSpecsBtn];
  195. [self.specScrollView addSubview:speLabel];
  196. [self.specScrollView addSubview:containerView];
  197. [self.specScrollView addSubview:addButton];
  198. [self.specScrollView addSubview:reduceButton];
  199. [self.specScrollView addSubview:self.numField];
  200. [self.specScrollView addSubview:numLabel];
  201. [speLabel mas_makeConstraints:^(MASConstraintMaker *make) {
  202. make.top.equalTo(superView);
  203. make.left.equalTo(superView).offset(10);
  204. make.height.equalTo(@20);
  205. }];
  206. [containerView mas_makeConstraints:^(MASConstraintMaker *make) {
  207. make.left.equalTo(superView).offset(10);
  208. make.right.equalTo(superView).offset(- 10);
  209. make.width.equalTo(@(UISCREENWIDTH - 20));
  210. make.top.equalTo(speLabel.mas_bottom);
  211. make.height.equalTo(@(containerH));
  212. }];
  213. [addButton mas_makeConstraints:^(MASConstraintMaker *make) {
  214. make.top.equalTo(containerView.mas_bottom).offset(10);
  215. make.right.equalTo(superView).offset(- 10);
  216. make.left.equalTo(superView).offset(UISCREENWIDTH - 10 - 30);
  217. make.bottom.equalTo(superView).offset(- 10);
  218. make.width.height.equalTo(@30);
  219. }];
  220. [self.numField mas_makeConstraints:^(MASConstraintMaker *make) {
  221. make.right.equalTo(addButton.mas_left).offset(- 2);
  222. make.top.height.equalTo(addButton);
  223. make.width.equalTo(@60);
  224. }];
  225. [reduceButton mas_makeConstraints:^(MASConstraintMaker *make) {
  226. make.top.width.height.equalTo(addButton);
  227. make.right.equalTo(self.numField.mas_left).offset(- 2);
  228. }];
  229. [numLabel mas_makeConstraints:^(MASConstraintMaker *make) {
  230. make.left.equalTo(superView).offset(10);
  231. make.bottom.equalTo(reduceButton);
  232. }];
  233. [self initializeButtonsWithContainer:containerView];
  234. }
  235. - (void)initializeButtonsWithContainer:(UIView *)containerView
  236. {
  237. UIButton *preBtn = nil;
  238. CGFloat rowNum = 0; // 第几行
  239. for (int i = 0; i < self.specsArray.count; i++) {
  240. PindanSpecItem *specItem = [self specItemAtIndex:i];
  241. BOOL selected = [self getFirstSelectedIndex] == i ? YES : NO;
  242. BOOL enabled = [self isSpecBtnEnabledAtIndex:i];
  243. if (self.isEnd) enabled = NO; // 已结束状态 全部禁用
  244. UIButton *button = [self createCommonSpecsBtnWithTitle:specItem.name
  245. tag:i + kSpecBtnTagBase
  246. selected:selected enabled:enabled];
  247. if (selected) _selectedSpecBtn = button;
  248. [containerView addSubview:button];
  249. CGFloat btnWidth = [self sizeForText:specItem.name withFontSize:kSpecBtnfontsize].width + 2 * KSpecBtnTitleMargin;
  250. // 判断当前button是否另起一行
  251. BOOL rowChange = NO;
  252. NSUInteger curentRowNum = [self rowNumberForSepcsBtnIndex:i];
  253. if (curentRowNum > rowNum && i > 0) {
  254. rowChange = YES;
  255. rowNum = curentRowNum;
  256. }
  257. if (i == 0) {
  258. [button mas_makeConstraints:^(MASConstraintMaker *make) {
  259. make.left.equalTo(containerView);
  260. make.top.equalTo(containerView).offset(10);
  261. make.width.equalTo(@(btnWidth));
  262. make.height.equalTo(@30);
  263. }];
  264. }else if (rowChange){
  265. [button mas_makeConstraints:^(MASConstraintMaker *make) {
  266. make.left.equalTo(containerView);
  267. make.top.equalTo(preBtn.mas_bottom).offset(10);
  268. make.width.equalTo(@(btnWidth));
  269. make.height.equalTo(@30);
  270. }];
  271. }else{
  272. [button mas_makeConstraints:^(MASConstraintMaker *make) {
  273. make.left.equalTo(preBtn.mas_right).offset(10);
  274. make.top.height.equalTo(preBtn);
  275. make.width.equalTo(@(btnWidth));
  276. }];
  277. }
  278. preBtn = button;
  279. }
  280. }
  281. - (UIButton *)createCommonSpecsBtnWithTitle:(NSString *)title tag:(int)tag selected:(BOOL)selected enabled:(BOOL)enabled
  282. {
  283. UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
  284. button.titleLabel.font = [UIFont systemFontOfSize:kSpecBtnfontsize];
  285. [button addTarget:self action:@selector(specsBtnClick:) forControlEvents:UIControlEventTouchUpInside];
  286. [button setTitle:title forState:UIControlStateNormal];
  287. button.layer.borderWidth = 0.5f;
  288. button.layer.borderColor = selected ? [UIColorFromRGB(0xff6362) CGColor] : [UIColorFromRGB(0xc4cccc) CGColor];
  289. UIColor *titleColor = selected ? UIColorFromRGB(0xff6362) : UIColorFromRGB(0x666666);
  290. [button setTitleColor:titleColor forState:UIControlStateNormal];
  291. button.tag = tag;
  292. button.enabled = enabled;
  293. if (!enabled){
  294. [button setBackgroundColor:UIColorFromRGB(0xeeeeee)];
  295. [button setTitleColor:UIColorFromRGB(0xcccccc) forState:UIControlStateNormal];
  296. button.layer.borderColor = [UIColor clearColor].CGColor;
  297. }
  298. return button;
  299. }
  300. - (BOOL)isSpecBtnEnabledAtIndex:(NSInteger)index
  301. {
  302. PindanSpecItem *specItem = [self specItemAtIndex:index];
  303. if ([specItem.stock isKindOfClass:[NSString class]] && specItem.stock.integerValue == 0) {
  304. // 库存为0
  305. return NO;
  306. }
  307. return YES;
  308. }
  309. - (PindanSpecItem *)specItemAtIndex:(NSUInteger)index{
  310. if (self.specsArray.count > 0 && self.specsArray.count > index) {
  311. return self.specsArray[index];
  312. }
  313. return nil;
  314. }
  315. - (NSInteger)getFirstSelectedIndex
  316. {
  317. __block NSInteger index = 0;
  318. [self.specsArray enumerateObjectsUsingBlock:^(PindanSpecItem *obj, NSUInteger idx, BOOL *stop) {
  319. if (![obj.stock isKindOfClass:[NSString class]] || obj.stock.integerValue > 0) {
  320. index = idx;
  321. *stop = YES;
  322. }
  323. }];
  324. return index;
  325. }
  326. // 根据规格按钮算出所在行数
  327. - (NSUInteger)rowNumberForSepcsBtnIndex:(NSUInteger)index
  328. {
  329. if (self.specsArray.count == 0 || index >= self.specsArray.count) {
  330. return 0;
  331. }
  332. CGFloat screenMargin = 10; // 规格按钮距离屏幕边距
  333. CGFloat betMargin = 5; // 规格按钮之间边距
  334. CGFloat rowLength = 2 * screenMargin; // 累计行长度
  335. CGFloat rowCount = 0; // 共几行
  336. for (int i = 0; i < index + 1; i++) {
  337. PindanSpecItem *specItem = [self specItemAtIndex:i];
  338. if (specItem.name.length == 0) continue;
  339. CGFloat titleWidth = [self sizeForText:specItem.name withFontSize:kSpecBtnfontsize].width;
  340. CGFloat buttonWidth = titleWidth + 2 * KSpecBtnTitleMargin;
  341. rowLength += (buttonWidth + (i ? betMargin : 0));
  342. if (rowLength >= UISCREENWIDTH) {
  343. rowCount++;
  344. rowLength = buttonWidth + 2 * screenMargin; // 假设不可能一个规格按钮超出一行
  345. }
  346. }
  347. return rowCount;
  348. }
  349. // 规格按钮视图容器的总高度
  350. - (CGFloat)heigtForAllSpecsBtn
  351. {
  352. NSUInteger rowCount = [self rowNumberForSepcsBtnIndex:self.specsArray.count - 1] + 1;
  353. return (rowCount + 1) * 15 + rowCount * 30;
  354. }
  355. - (CGSize)sizeForText:(NSString *)text withFontSize:(CGFloat)fontSize
  356. {
  357. if (text.length == 0 || fontSize <= 0) {
  358. return CGSizeZero;
  359. }
  360. NSDictionary *dict = @{NSFontAttributeName : [UIFont systemFontOfSize:fontSize]};
  361. return [text sizeWithAttributes:dict];
  362. }
  363. // 限购数量
  364. - (NSInteger)limitedAmountForIndex:(NSInteger)index
  365. {
  366. return self.limitedAmount == 0 ? NSIntegerMax : self.limitedAmount;
  367. }
  368. // 库存限制
  369. - (NSInteger)limitedStockForIndex:(NSInteger)index
  370. {
  371. PindanSpecItem *specItem = self.specsArray[index];
  372. return [specItem.stock isKindOfClass:[NSString class]] ? specItem.stock.integerValue : NSIntegerMax;
  373. }
  374. - (void)showToView:(UIView *)view animated:(BOOL)animated
  375. {
  376. if (!view) {
  377. return;
  378. }
  379. CGFloat height = view.frame.size.height;
  380. CGFloat width = view.frame.size.width;
  381. CGFloat contentH = 250; // 内容高度
  382. [view addSubview:self];
  383. [self setFrame:view.frame];
  384. [self.contentView setFrame:CGRectMake(0, height, width, contentH)];
  385. self.backgroundColor = [UIColor clearColor];
  386. CGFloat duration = animated ? kDurationTime : 0;
  387. [UIView animateWithDuration:duration delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{
  388. self.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.5f];
  389. [self.contentView setFrame:CGRectMake(0, height - contentH, width, contentH)];
  390. } completion:nil];
  391. }
  392. #pragma mark - event response
  393. - (void)changNumBtnClick:(UIButton *)sender
  394. {
  395. if (self.isEnd) return;
  396. NSInteger numLimit = [self limitedAmountForIndex:self.selectedSpecsIndex];
  397. NSInteger stockLimit = [self limitedStockForIndex:self.selectedSpecsIndex];
  398. PindanSpecItem *specItem = self.specsArray[self.selectedSpecsIndex];
  399. NSInteger number = [self.numField.text integerValue]; // 选中数量
  400. NSInteger basketNum = self.basketBtn.tag; // 购物车中数量
  401. NSInteger specNum = specItem.selectedAmount; // 当前选中规格购物篮中数量
  402. if (sender.tag - kNumChangeBtnTagBase == 0) {
  403. number++;
  404. if (number + basketNum > numLimit){
  405. NSString *warnString = [NSString stringWithFormat:@"每个账号只能购买%ld件哦", (long)numLimit];
  406. [FLProgressHUDHelper showText:warnString inView:self.superview];
  407. return;
  408. }
  409. if (number + specNum > stockLimit){
  410. NSString *warnString = [NSString stringWithFormat:@"该商品库存仅剩%ld件", (long)stockLimit];
  411. [FLProgressHUDHelper showText:warnString inView:self.superview];
  412. return;
  413. }
  414. }else if (sender.tag - kNumChangeBtnTagBase == 1){
  415. number--;
  416. }
  417. if (number <= 0) number = 1;
  418. self.numField.text = [NSString stringWithFormat:@"%ld", (long)number];
  419. }
  420. - (void)specsBtnClick:(UIButton *)sender
  421. {
  422. if (sender == _selectedSpecBtn) return;
  423. if (_selectedSpecBtn) {
  424. _selectedSpecBtn.layer.borderColor = [UIColorFromRGB(0xc4cccc) CGColor];
  425. [_selectedSpecBtn setTitleColor:UIColorFromRGB(0x666666) forState:UIControlStateNormal];
  426. }
  427. sender.layer.borderColor = [UIColorFromRGB(0xff6362) CGColor];
  428. [sender setTitleColor:UIColorFromRGB(0xff6362) forState:UIControlStateNormal];
  429. _selectedSpecBtn = sender;
  430. // 刷新UI
  431. PindanSpecItem *specItem = self.specsArray[self.selectedSpecsIndex];
  432. if (specItem){
  433. CGFloat unitPrice = 0;
  434. if ([self.viewModel isVIP] && specItem.vipPrice.length >0) {
  435. self.vipImageIcon.hidden = NO;
  436. if ([specItem.vipPrice isKindOfClass:[NSString class]]) unitPrice = specItem.vipPrice.floatValue;
  437. } else {
  438. self.vipImageIcon.hidden = YES;
  439. if ([specItem.price isKindOfClass:[NSString class]]) unitPrice = specItem.price.floatValue;
  440. }
  441. self.detailLabel.text = specItem.name;
  442. self.priceLabel.text = [NSString stringWithFormat:@"¥%.2f", (unitPrice + self.nationalPostage) / 100.0f];
  443. self.numField.text = @"1";
  444. [self.imageView sd_setImageWithURL:[NSURL URLWithString:[PindanSelectDetailView cdnImgUrlStringWithString:specItem.imgUrl]]];
  445. [self.contentView bringSubviewToFront:self.imageView];
  446. }
  447. }
  448. - (void)cancelBtnClick
  449. {
  450. [UIView animateWithDuration:kDurationTime delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{
  451. self.backgroundColor = [UIColor clearColor];
  452. [self.contentView setFrame:CGRectOffset(self.contentView.frame, 0, CGRectGetHeight(self.contentView.frame))];
  453. } completion:^(BOOL finished) {
  454. [self removeFromSuperview];
  455. }];
  456. }
  457. - (void)confirmBtnClick
  458. {
  459. if (self.isEnd) return;
  460. NSInteger numLimit = [self limitedAmountForIndex:self.selectedSpecsIndex];
  461. NSInteger stockLimit = [self limitedStockForIndex:self.selectedSpecsIndex];
  462. PindanSpecItem *specItem = self.specsArray[self.selectedSpecsIndex];
  463. NSInteger number = [self.numField.text integerValue]; // 选中数量
  464. NSInteger basketNum = self.basketBtn.tag; // 购物车中数量
  465. NSInteger specNum = specItem.selectedAmount; // 当前选中规格购物篮中数量
  466. if (number + basketNum > numLimit){
  467. NSString *warnString = [NSString stringWithFormat:@"每个账号只能购买%ld件哦", (long)numLimit];
  468. [FLProgressHUDHelper showText:warnString inView:self.superview];
  469. return;
  470. }
  471. if (number + specNum > stockLimit){
  472. NSString *warnString = [NSString stringWithFormat:@"该商品库存仅剩%ld件", (long)stockLimit];
  473. [FLProgressHUDHelper showText:warnString inView:self.superview];
  474. return;
  475. }
  476. specItem.selectedAmount += number;
  477. self.basketBtn.tag += number;
  478. NSString *animKey = @"animationGroup";
  479. if (_animImgViewArray == nil) {
  480. _animImgViewArray = [NSMutableArray array];
  481. }
  482. UIImageView *targetImgView = nil;
  483. for (UIImageView *imageView in self.animImgViewArray) {
  484. CAAnimation *anim = [imageView.layer animationForKey:animKey];
  485. if (!anim) targetImgView = imageView;
  486. }
  487. if (!targetImgView){
  488. targetImgView = [[UIImageView alloc]initWithImage:self.imageView.image];
  489. targetImgView.layer.masksToBounds = YES;
  490. targetImgView.layer.cornerRadius = 5;
  491. [self.contentView addSubview:targetImgView];
  492. [targetImgView setFrame:self.imageView.frame];
  493. [self.animImgViewArray addObject:targetImgView];
  494. }
  495. [targetImgView sd_setImageWithURL:[NSURL URLWithString:[PindanSelectDetailView cdnImgUrlStringWithString:specItem.imgUrl]]];
  496. [self.contentView bringSubviewToFront:targetImgView];
  497. targetImgView.tag = number;
  498. [targetImgView.layer addAnimation:self.groupAnim forKey:animKey];
  499. }
  500. - (void)tapGestureClick:(UITapGestureRecognizer *)tapGesture
  501. {
  502. CGPoint location = [tapGesture locationInView:self];
  503. BOOL isOnContent = CGRectContainsPoint(self.contentView.frame, location);
  504. if (isOnContent) {
  505. return;
  506. }else{
  507. [self cancelBtnClick];
  508. }
  509. }
  510. - (void)ClickbasketBtn:(UIButton *)sender{
  511. if (self.basketBtn.tag <= 0) return;
  512. [UIView animateWithDuration:kDurationTime delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{
  513. self.backgroundColor = [UIColor clearColor];
  514. [self.contentView setFrame:CGRectOffset(self.contentView.frame, 0, CGRectGetHeight(self.contentView.frame))];
  515. } completion:^(BOOL finished) {
  516. if (self.selectDoneAction) self.selectDoneAction(self);
  517. [self removeFromSuperview];
  518. }];
  519. }
  520. - (void)refreshSelectSpecContent{
  521. NSInteger allCount = 0;
  522. for (PindanSpecItem *item in self.specsArray) {
  523. allCount += item.selectedAmount;
  524. }
  525. self.basketBtn.tag = allCount;
  526. self.numLabel.text = [NSString stringWithFormat:@"%ld", (long)self.basketBtn.tag];
  527. }
  528. #pragma mark - animation delegate
  529. - (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag{
  530. self.basketBtn.selected = YES;
  531. self.numLabel.text = [NSString stringWithFormat:@"%ld", (long)self.basketBtn.tag];
  532. self.numLabel.hidden = NO;
  533. }
  534. #pragma mark - getter && setter
  535. - (UIView *)contentView
  536. {
  537. if (_contentView == nil) {
  538. _contentView = [[UIView alloc]init];
  539. _contentView.backgroundColor = [UIColor whiteColor];
  540. }
  541. return _contentView;
  542. }
  543. - (UIImageView *)imageView
  544. {
  545. if (_imageView == nil) {
  546. _imageView = [[UIImageView alloc]init];
  547. _imageView.layer.masksToBounds = YES;
  548. _imageView.layer.cornerRadius = 5;
  549. }
  550. return _imageView;
  551. }
  552. - (UIImageView *)vipImageIcon
  553. {
  554. if (_vipImageIcon == nil) {
  555. _vipImageIcon = [[UIImageView alloc]init];
  556. _vipImageIcon.image = [UIImage imageNamed:@"VipPriceIcon"];
  557. _vipImageIcon.hidden = YES;
  558. }
  559. return _vipImageIcon;
  560. }
  561. - (UILabel *)priceLabel
  562. {
  563. if (_priceLabel == nil) {
  564. _priceLabel = [[UILabel alloc]init];
  565. _priceLabel.backgroundColor = [UIColor clearColor];
  566. _priceLabel.font = [UIFont systemFontOfSize:13];
  567. _priceLabel.textAlignment = NSTextAlignmentRight;
  568. _priceLabel.textColor = UIColorFromRGB(0xff6362);
  569. }
  570. return _priceLabel;
  571. }
  572. - (UILabel *)detailLabel
  573. {
  574. if (_detailLabel == nil) {
  575. _detailLabel = [[UILabel alloc]init];
  576. _detailLabel.backgroundColor = [UIColor clearColor];
  577. _detailLabel.font = [UIFont systemFontOfSize:13];
  578. _detailLabel.textColor = UIColorFromRGB(0x999999);
  579. }
  580. return _detailLabel;
  581. }
  582. - (UIScrollView *)specScrollView
  583. {
  584. if (_specScrollView == nil) {
  585. _specScrollView = [[UIScrollView alloc]init];
  586. _specScrollView.backgroundColor = [UIColor clearColor];
  587. _specScrollView.showsHorizontalScrollIndicator = NO;
  588. _specScrollView.showsVerticalScrollIndicator = NO;
  589. }
  590. return _specScrollView;
  591. }
  592. - (UITextField *)numField
  593. {
  594. if (_numField == nil) {
  595. _numField = [[UITextField alloc]init];
  596. _numField.textAlignment = NSTextAlignmentCenter;
  597. _numField.layer.borderWidth = 0.5f;
  598. _numField.layer.borderColor = [UIColorFromRGB(0xcccccc) CGColor];
  599. _numField.enabled = NO;
  600. }
  601. return _numField;
  602. }
  603. - (UILabel *)numLabel{
  604. if (_numLabel == nil) {
  605. _numLabel = [[UILabel alloc]init];
  606. _numLabel.backgroundColor = UIColorFromRGB(0xff6362);
  607. _numLabel.layer.cornerRadius = 7.5;
  608. _numLabel.layer.masksToBounds = YES;
  609. _numLabel.textColor = [UIColor whiteColor];
  610. _numLabel.font = [UIFont systemFontOfSize:10];
  611. _numLabel.textAlignment = NSTextAlignmentCenter;
  612. _numLabel.hidden = YES;
  613. }
  614. return _numLabel;
  615. }
  616. - (UIButton *)basketBtn{
  617. if (_basketBtn == nil) {
  618. _basketBtn = [UIButton buttonWithType:UIButtonTypeCustom];
  619. [_basketBtn setImage:[UIImage imageNamed:@"product_basketH"] forState:UIControlStateSelected];
  620. [_basketBtn setImage:[UIImage imageNamed:@"product_basket_n"] forState:UIControlStateNormal];
  621. [_basketBtn addTarget:self action:@selector(ClickbasketBtn:) forControlEvents:UIControlEventTouchUpInside];
  622. _basketBtn.tag = 0;
  623. }
  624. return _basketBtn;
  625. }
  626. - (UIView *)middleLine{
  627. if (_middleLine == nil) {
  628. _middleLine = [[UIView alloc]init];
  629. _middleLine.backgroundColor = UIColorFromRGB(0xe0e0e0);
  630. }
  631. return _middleLine;
  632. }
  633. - (CAAnimationGroup *)groupAnim{
  634. if (_groupAnim == nil) {
  635. CGFloat animDuration = 0.6f;
  636. CAKeyframeAnimation *anim = [CAKeyframeAnimation animationWithKeyPath:@"position"];
  637. anim.duration = animDuration;
  638. anim.repeatCount = 1;
  639. anim.removedOnCompletion = YES;
  640. UIBezierPath *path = [UIBezierPath bezierPath];
  641. [path moveToPoint:CGPointMake(self.imageView.layer.position.x, self.imageView.layer.position.y)];
  642. [path addQuadCurveToPoint:self.basketBtn.layer.position controlPoint:CGPointMake(self.imageView.layer.position.x + 100, self.imageView.layer.position.y)];
  643. anim.path = path.CGPath;
  644. CABasicAnimation *alpAnim = [CABasicAnimation animationWithKeyPath:@"opacity"];
  645. alpAnim.fromValue = @1.0;
  646. alpAnim.toValue = @0.2f;
  647. alpAnim.duration = animDuration;
  648. CAKeyframeAnimation *scaleAnim = [CAKeyframeAnimation animationWithKeyPath:@"transform"];
  649. CATransform3D transform1 = CATransform3DMakeScale(0.8, 0.8, 1.0f);
  650. CATransform3D transform2 = CATransform3DMakeScale(0.4, 0.4, 1.0f);
  651. CATransform3D transform3 = CATransform3DMakeScale(0.4, 0.4, 1.0f);
  652. scaleAnim.values = @[[NSValue valueWithCATransform3D:transform1], [NSValue valueWithCATransform3D:transform2], [NSValue valueWithCATransform3D:transform3],];
  653. scaleAnim.keyTimes = @[@0, @0.6, @1.0];
  654. CABasicAnimation *rotateAnim = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
  655. rotateAnim.fromValue = @0;
  656. rotateAnim.toValue = @(2 * M_PI * 3);
  657. rotateAnim.duration = animDuration;
  658. _groupAnim = [CAAnimationGroup animation];
  659. _groupAnim.duration = animDuration;
  660. _groupAnim.removedOnCompletion = YES;
  661. _groupAnim.animations = @[anim, alpAnim, scaleAnim, rotateAnim];
  662. _groupAnim.delegate = self;
  663. }
  664. return _groupAnim;
  665. }
  666. - (NSInteger)selectedSpecsIndex
  667. {
  668. if (!_selectedSpecBtn) {
  669. return 0;
  670. }
  671. return _selectedSpecBtn.tag - kSpecBtnTagBase;
  672. }
  673. - (NSInteger)selectedAmount
  674. {
  675. return [self.numField.text integerValue];
  676. }
  677. @end