CustomRadioGroup.m 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439
  1. //
  2. // CustomRadioGroup.m
  3. // JasonDevelop
  4. //
  5. // Created by Jason Lee on 3/10/14.
  6. // Copyright (c) jasondevelop. All rights reserved.
  7. //
  8. @import ObjectiveC.runtime;
  9. #import <stdarg.h>
  10. #import "CustomRadioGroup.h"
  11. #import "CommonUtil.h"
  12. #import "ImageUtil.h"
  13. @interface CustomRadioButton () {
  14. }
  15. @end
  16. @implementation CustomRadioButton
  17. @synthesize checked = _checked;
  18. - (instancetype)initWithFrame:(CGRect)frame normalImage:(UIImage *)normalImage highlightImage:(UIImage *)highlightImage {//소스레벨에서 로드하는 경우, 초기화
  19. if (self = [super initWithFrame:frame]) {
  20. _normalImage = normalImage;
  21. _highlightImage = highlightImage;
  22. [self setImage:_normalImage forState:UIControlStateNormal];
  23. [self setImage:_highlightImage forState:UIControlStateHighlighted];
  24. [self.titleLabel setLineBreakMode:NSLineBreakByTruncatingTail];
  25. [self addTarget:self action:@selector(didRadioButtonTouched:) forControlEvents:UIControlEventTouchUpInside];
  26. }
  27. return self;
  28. }
  29. - (void)awakeFromNib {
  30. [super awakeFromNib];
  31. _normalImage = [self imageForState:UIControlStateNormal];
  32. _highlightImage = [self imageForState:UIControlStateHighlighted];
  33. _titleColorNormal = [self titleColorForState:UIControlStateNormal];
  34. _titleColorHighlight = [self titleColorForState:UIControlStateHighlighted] ? [self titleColorForState:UIControlStateHighlighted] : _titleColorNormal;
  35. [self.titleLabel setLineBreakMode:NSLineBreakByTruncatingTail];
  36. [self addTarget:self action:@selector(didRadioButtonTouched:) forControlEvents:UIControlEventTouchUpInside];
  37. }
  38. - (void)setChecked:(BOOL)checked {//
  39. _checked = checked;
  40. if (_checked) {
  41. [self setImage:_highlightImage forState:UIControlStateNormal];
  42. [self setTitleColor:_titleColorHighlight forState:UIControlStateNormal];
  43. } else {
  44. [self setImage:_normalImage forState:UIControlStateNormal];
  45. [self setTitleColor:_titleColorNormal forState:UIControlStateNormal];
  46. }
  47. if (_value) {
  48. objc_setAssociatedObject(_value, ksCustomRadioButtonStatus, [NSNumber numberWithBool:_checked], OBJC_ASSOCIATION_COPY_NONATOMIC);
  49. }
  50. }
  51. - (BOOL)getRadioStatusFromValue {
  52. BOOL isChecked = NO;
  53. if (_value) {
  54. isChecked = [objc_getAssociatedObject(_value, ksCustomRadioButtonStatus) boolValue];
  55. }
  56. return isChecked;
  57. }
  58. - (void)didRadioButtonTouched:(id)sender {
  59. if (self.delegate) {
  60. self.checked = !self.checked;
  61. }
  62. if ([self.delegate respondsToSelector:@selector(didCheckRadioButton:)]) {
  63. [self.delegate didCheckRadioButton:self];
  64. }
  65. }
  66. @end
  67. @interface CustomBgRadioButton () {
  68. // UIImage *_bgNormalImage, *_bgHighlightImage;
  69. // UIEdgeInsets _bgInsets;
  70. }
  71. @end
  72. #define kfRoundWidth 1.0f
  73. @implementation CustomBgRadioButton
  74. @dynamic checked;
  75. - (instancetype)initWithFrame:(CGRect)frame bgNormalImage:(UIImage *)bgNormalImage bgHighlightImage:(UIImage *)bgHighlightImage rectForCapBg:(CGRect)rectForCapBg {
  76. if (self = [super initWithFrame:frame]) {
  77. _bgNormalImage = bgNormalImage;
  78. _bgHighlightImage = bgHighlightImage;
  79. _rectForCapBg = rectForCapBg;
  80. [self setBackgroundImage:_bgNormalImage forState:UIControlStateNormal];
  81. [self setBackgroundImage:_bgHighlightImage forState:UIControlStateHighlighted];
  82. [self setImage:_normalImage forState:UIControlStateNormal];
  83. [self setImage:_highlightImage forState:UIControlStateHighlighted];
  84. if (!CGRectEqualToRect(_rectForCapBg, CGRectZero)) {//rectForCap이 설정된 경우, 이미지를 리사이즈함.
  85. CGFloat top, left, bottom, right;
  86. top = CGRectGetMinY(_rectForCapBg);
  87. left = CGRectGetMinX(_rectForCapBg);
  88. bottom = CGRectGetHeight(_rectForCapBg);
  89. right = CGRectGetWidth(_rectForCapBg);
  90. _bgInsets = UIEdgeInsetsMake(top, left, bottom, right);
  91. [self setBackgroundImageStretchForState:UIControlStateNormal capInsets:_bgInsets];
  92. [self setBackgroundImageStretchForState:UIControlStateHighlighted capInsets:_bgInsets];
  93. } else {//rectForCap이 설정되지 않은 경우, 픽스된 사이즈로 이미지를 리사이즈함.
  94. _bgInsets = UIEdgeInsetsMake(kfRoundWidth, kfRoundWidth, kfRoundWidth, kfRoundWidth);
  95. [self setBackgroundImageStretchForState:UIControlStateNormal capInsets:_bgInsets];
  96. [self setBackgroundImageStretchForState:UIControlStateHighlighted capInsets:_bgInsets];
  97. }
  98. [self addTarget:self action:@selector(didRadioButtonTouched:) forControlEvents:UIControlEventTouchUpInside];
  99. }
  100. return self;
  101. }
  102. - (void)setBackgroundImageStretchForState:(UIControlState)state capInsets:(UIEdgeInsets)insets {
  103. UIImage *bimage = [self backgroundImageForState:state];
  104. bimage = [ImageUtil resizableImageWithCapInsets:insets resizingMode:UIImageResizingModeStretch img:bimage];
  105. [super setBackgroundImage:bimage forState:state];
  106. }
  107. - (void)awakeFromNib {
  108. _bgNormalImage = [self backgroundImageForState:UIControlStateNormal];
  109. _bgHighlightImage = [self backgroundImageForState:UIControlStateHighlighted];
  110. _normalImage = [self imageForState:UIControlStateNormal];
  111. _highlightImage = [self imageForState:UIControlStateHighlighted];
  112. _titleColorNormal = [self titleColorForState:UIControlStateNormal];
  113. _titleColorHighlight = [self titleColorForState:UIControlStateHighlighted] ? [self titleColorForState:UIControlStateHighlighted] : _titleColorNormal;
  114. if (!CGRectEqualToRect(_rectForCapBg, CGRectZero)) {//rectForCap이 설정된 경우, 이미지를 리사이즈함.
  115. CGFloat top, left, bottom, right;
  116. top = CGRectGetMinY(_rectForCapBg);
  117. left = CGRectGetMinX(_rectForCapBg);
  118. bottom = CGRectGetHeight(_rectForCapBg);
  119. right = CGRectGetWidth(_rectForCapBg);
  120. _bgInsets = UIEdgeInsetsMake(top, left, bottom, right);
  121. [self setBackgroundImageStretchForState:UIControlStateNormal capInsets:_bgInsets];
  122. [self setBackgroundImageStretchForState:UIControlStateHighlighted capInsets:_bgInsets];
  123. } else {//rectForCap이 설정되지 않은 경우, 픽스된 사이즈로 이미지를 리사이즈함.
  124. [self setBackgroundImageStretchForState:UIControlStateNormal capInsets:_bgInsets];
  125. [self setBackgroundImageStretchForState:UIControlStateHighlighted capInsets:_bgInsets];
  126. }
  127. [self addTarget:self action:@selector(didRadioButtonTouched:) forControlEvents:UIControlEventTouchUpInside];
  128. }
  129. - (void)setChecked:(BOOL)checked {
  130. _checked = checked;
  131. if (_checked) {
  132. [self setBackgroundImage:_bgHighlightImage forState:UIControlStateNormal];
  133. [self setTitleColor:_titleColorHighlight forState:UIControlStateNormal];
  134. if (_normalImage && _highlightImage) {
  135. [self setImage:_highlightImage forState:UIControlStateNormal];
  136. [self setImage:_normalImage forState:UIControlStateHighlighted];
  137. }
  138. } else {
  139. [self setBackgroundImage:_bgNormalImage forState:UIControlStateNormal];
  140. [self setTitleColor:_titleColorNormal forState:UIControlStateNormal];
  141. if (_normalImage && _highlightImage) {
  142. [self setImage:_normalImage forState:UIControlStateNormal];
  143. [self setImage:_highlightImage forState:UIControlStateHighlighted];
  144. }
  145. }
  146. [self setBackgroundImageStretchForState:UIControlStateNormal capInsets:_bgInsets];
  147. [self setBackgroundImageStretchForState:UIControlStateHighlighted capInsets:_bgInsets];
  148. if (self.value) {
  149. objc_setAssociatedObject(self.value, ksCustomRadioButtonStatus, [NSNumber numberWithBool:self.checked], OBJC_ASSOCIATION_COPY_NONATOMIC);
  150. }
  151. }
  152. @end
  153. @interface CustomRadioGroup () {
  154. NSMutableArray *_btns;
  155. CustomRadioButton *_btnChecked;
  156. UIImage *_imageNormal, *_imageHighlight, *_bgImageNormal, *_bgImageHighlight;
  157. BOOL _isFirstLoading;
  158. }
  159. @end
  160. @implementation CustomRadioGroup
  161. - (id)init {
  162. if (self = [super init]) {
  163. _btns = [NSMutableArray new];
  164. _isFirstLoading = YES;
  165. }
  166. return self;
  167. }
  168. - (id)initWithRadioButtons:(id)buttons, ... {//라디오 버튼 그룹을 만듬, 들어오는 버튼수만큰 멤버로 할당됨.
  169. if (self = [super init]) {
  170. if (buttons) {
  171. _btns = [NSMutableArray new];
  172. if ([buttons isKindOfClass:[CustomBgRadioButton class]]) {
  173. // _bgImageNormal = [UIImage imageNamed:@"tp_01_img_control_bg_black"];
  174. // _bgImageHighlight = [UIImage imageNamed:@"tp_01_img_control_bg_active"];
  175. [(UIButton *)buttons setBackgroundImage:_imageHighlight forState:UIControlStateHighlighted];
  176. } else if ([buttons isKindOfClass:[CustomBgRadioButton class]]) {
  177. _imageNormal = [UIImage imageNamed:@"common_radiobox_default"];
  178. _imageHighlight = [UIImage imageNamed:@"common_radiobox_checked"];
  179. [(UIButton *)buttons setImage:_imageHighlight forState:UIControlStateHighlighted];
  180. }
  181. [buttons addTarget:self action:@selector(someRadioButtonTouched:) forControlEvents:UIControlEventTouchUpInside];
  182. [_btns addObject:buttons];
  183. _btnChecked = buttons; //첫번째 버튼을 선택상태로
  184. _btnChecked.checked = YES;
  185. va_list args;
  186. va_start(args, buttons);
  187. while ((buttons = va_arg(args, id)) != nil) {//루프 - 버튼을 그룹에 추가함.
  188. if ([buttons isKindOfClass:[CustomRadioButton class]]) {
  189. [buttons addTarget:self action:@selector(someRadioButtonTouched:) forControlEvents:UIControlEventTouchUpInside];
  190. [_btns addObject:buttons];
  191. }
  192. }
  193. va_end(args);
  194. }
  195. }
  196. return self;
  197. }
  198. //Do not use in resusable table
  199. - (void)addRadioButton:(CustomRadioButton *)button {//라디오 그룹에 버튼을 추가함.
  200. CustomRadioButton *lBtn = [_btns lastObject];
  201. if ([button isKindOfClass:[CustomBgRadioButton class]]) {
  202. if (lBtn == nil) {//첫번째 버튼
  203. if (_isFirstLoading) {
  204. _bgImageNormal = [button backgroundImageForState:UIControlStateNormal];
  205. _bgImageHighlight = [button backgroundImageForState:UIControlStateHighlighted];
  206. _isFirstLoading = NO;
  207. }
  208. [button setBackgroundImage:_bgImageHighlight forState:UIControlStateNormal];
  209. [button setBackgroundImage:_bgImageNormal forState:UIControlStateHighlighted];
  210. _btnChecked = button;
  211. _btnChecked.checked = YES;
  212. } else {
  213. [button setBackgroundImage:_bgImageNormal forState:UIControlStateNormal];
  214. [button setBackgroundImage:_bgImageHighlight forState:UIControlStateHighlighted];
  215. }
  216. } else if ([button isKindOfClass:[CustomRadioButton class]]) {
  217. if (lBtn == nil) {//첫번째 버튼
  218. if (_isFirstLoading) {
  219. _imageNormal = [button imageForState:UIControlStateNormal];
  220. _imageHighlight = [button imageForState:UIControlStateHighlighted];
  221. _isFirstLoading = NO;
  222. }
  223. [button setImage:_imageHighlight forState:UIControlStateNormal];
  224. [button setImage:_imageNormal forState:UIControlStateHighlighted];
  225. _btnChecked = button;
  226. _btnChecked.checked = YES;
  227. } else {
  228. [button setImage:_imageNormal forState:UIControlStateNormal];
  229. [button setImage:_imageHighlight forState:UIControlStateHighlighted];
  230. }
  231. }
  232. [button addTarget:self action:@selector(someRadioButtonTouched:) forControlEvents:UIControlEventTouchUpInside];
  233. [_btns addObject:button];
  234. }
  235. - (void)reset {
  236. [_btns removeAllObjects];
  237. }
  238. - (id)valueForChecked {//선택된 Object를 반환함.
  239. return _btnChecked.value;
  240. }
  241. - (id)titleForChecked {//선택된 타이틀을 반환함.
  242. return _btnChecked.titleLabel.text;
  243. }
  244. - (NSInteger)count {
  245. return _btns.count;
  246. }
  247. - (NSArray *)rdoBtns {
  248. return _btns;
  249. }
  250. - (void)someRadioButtonTouched:(id)sender {//특정 라디오버튼이 선택된 경우, 값을 설정함.
  251. if (_btnChecked == sender)
  252. return;
  253. CustomRadioButton *btnSender = (CustomRadioButton *)sender;
  254. for (CustomRadioButton *btn in _btns) {
  255. if ([btnSender isEqual:btn]) {
  256. _btnChecked = btnSender;
  257. _btnChecked.checked = YES;
  258. } else {
  259. btn.checked = NO;
  260. }
  261. }
  262. if ([self.delegate respondsToSelector:@selector(didSomeRadioButtonTouched:)]) {
  263. [self.delegate didSomeRadioButtonTouched:sender];
  264. }
  265. }
  266. @end
  267. @interface CustomRadioReusableGroup () <CustomRadioButtonDelegate> {
  268. NSMutableArray *_valueArray;
  269. }
  270. @end
  271. @implementation CustomRadioReusableGroup
  272. - (instancetype)init {
  273. if (self = [super init]) {
  274. _valueArray = [[NSMutableArray alloc] init];
  275. }
  276. return self;
  277. }
  278. - (void)addRadioButton:(CustomRadioButton *)rbtn {
  279. if ([_valueArray containsObject:rbtn.value]) {//동일한 오브젝트에 대한 validate
  280. return;
  281. }
  282. rbtn.delegate = self;
  283. [_valueArray addObject:rbtn.value];
  284. }
  285. - (NSArray *)values {
  286. return _valueArray;
  287. }
  288. - (void)someRadioButtonTouched:(CustomRadioButton *)touchedRbtn {
  289. NSLog(@"%@", touchedRbtn.value);
  290. for (id avalue in _valueArray) {
  291. if ([touchedRbtn.value isEqual:avalue]) {
  292. touchedRbtn.checked = YES;
  293. continue;
  294. }
  295. if ([objc_getAssociatedObject(avalue, ksCustomRadioButtonStatus) boolValue]) {
  296. objc_setAssociatedObject(avalue, ksCustomRadioButtonStatus, [NSNumber numberWithBool:NO], OBJC_ASSOCIATION_COPY_NONATOMIC);
  297. }
  298. }
  299. [_tableView reloadData];
  300. if ([self.delegate respondsToSelector:@selector(didSomeReuableRadioButtonTouched:)]) {
  301. [self.delegate didSomeReuableRadioButtonTouched:touchedRbtn];
  302. }
  303. }
  304. - (void)reset {
  305. [_valueArray removeAllObjects];
  306. }
  307. - (id)valueForChecked {
  308. id resultValue = nil;
  309. for (id avalue in _valueArray) {
  310. if ([objc_getAssociatedObject(avalue, ksCustomRadioButtonStatus) boolValue]) {
  311. resultValue = avalue;
  312. }
  313. }
  314. return resultValue;
  315. }
  316. #pragma mark - CustomRadioButton Delegate
  317. - (void)didCheckRadioButton:(id)sender {
  318. [self someRadioButtonTouched:sender];
  319. }
  320. @end