TOPasscodeCircleButton.m 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. //
  2. // TOPasscodeCircleButton.m
  3. //
  4. // Copyright 2017 Timothy Oliver. All rights reserved.
  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
  8. // deal in the Software without restriction, including without limitation the
  9. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  10. // sell 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
  17. // OR 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 LIABILITY,
  20. // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
  21. // IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  22. #import "TOPasscodeCircleButton.h"
  23. #import "TOPasscodeCircleView.h"
  24. #import "TOPasscodeButtonLabel.h"
  25. @interface TOPasscodeCircleButton ()
  26. @property (nonatomic, strong, readwrite) TOPasscodeButtonLabel *buttonLabel;
  27. @property (nonatomic, strong, readwrite) TOPasscodeCircleView *circleView;
  28. @property (nonatomic, strong, readwrite) UIVisualEffectView *vibrancyView;
  29. @property (nonatomic, readwrite, copy) NSString *numberString;
  30. @property (nonatomic, readwrite, copy) NSString *letteringString;
  31. @end
  32. @implementation TOPasscodeCircleButton
  33. - (instancetype)initWithNumberString:(NSString *)numberString letteringString:(NSString *)letteringString
  34. {
  35. if (self = [super init]) {
  36. _numberString = numberString;
  37. _letteringString = letteringString;
  38. _contentAlpha = 1.0f;
  39. [self setUp];
  40. }
  41. return self;
  42. }
  43. - (void)setUp
  44. {
  45. self.userInteractionEnabled = YES;
  46. _textColor = [UIColor whiteColor];
  47. [self setUpSubviews];
  48. [self setUpViewInteraction];
  49. }
  50. - (void)setUpSubviews
  51. {
  52. if (!self.circleView) {
  53. self.circleView = [[TOPasscodeCircleView alloc] initWithFrame:self.bounds];
  54. [self addSubview:self.circleView];
  55. }
  56. if (!self.buttonLabel) {
  57. self.buttonLabel = [[TOPasscodeButtonLabel alloc] initWithFrame:self.bounds];
  58. self.buttonLabel.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
  59. self.buttonLabel.userInteractionEnabled = NO;
  60. self.buttonLabel.textColor = self.textColor;
  61. self.buttonLabel.numberString = self.numberString;
  62. self.buttonLabel.letteringString = self.letteringString;
  63. [self addSubview:self.buttonLabel];
  64. }
  65. if (!self.vibrancyView) {
  66. self.vibrancyView = [[UIVisualEffectView alloc] initWithEffect:nil];
  67. self.vibrancyView.userInteractionEnabled = NO;
  68. [self.vibrancyView.contentView addSubview:self.circleView];
  69. [self addSubview:self.vibrancyView];
  70. }
  71. }
  72. - (void)setUpViewInteraction
  73. {
  74. if (self.allTargets.count) { return; }
  75. [self addTarget:self action:@selector(buttonDidTouchDown:) forControlEvents:UIControlEventTouchDown];
  76. [self addTarget:self action:@selector(buttonDidTouchUpInside:) forControlEvents:UIControlEventTouchUpInside];
  77. [self addTarget:self action:@selector(buttonDidDragInside:) forControlEvents:UIControlEventTouchDragEnter];
  78. [self addTarget:self action:@selector(buttonDidDragOutside:) forControlEvents:UIControlEventTouchDragExit];
  79. }
  80. - (void)layoutSubviews
  81. {
  82. [super layoutSubviews];
  83. self.vibrancyView.frame = self.bounds;
  84. self.circleView.frame = self.vibrancyView ? self.vibrancyView.bounds : self.bounds;
  85. self.buttonLabel.frame = self.bounds;
  86. [self bringSubviewToFront:self.buttonLabel];
  87. }
  88. #pragma mark - User Interaction -
  89. - (void)buttonDidTouchDown:(id)sender
  90. {
  91. if (self.buttonTappedHandler) { self.buttonTappedHandler(); }
  92. [self setHighlighted:YES animated:NO];
  93. }
  94. - (void)buttonDidTouchUpInside:(id)sender { [self setHighlighted:NO animated:YES]; }
  95. - (void)buttonDidDragInside:(id)sender { [self setHighlighted:YES animated:NO]; }
  96. - (void)buttonDidDragOutside:(id)sender { [self setHighlighted:NO animated:YES]; }
  97. #pragma mark - Animated Accessors -
  98. - (void)setHighlighted:(BOOL)highlighted animated:(BOOL)animated
  99. {
  100. [self.circleView setHighlighted:highlighted animated:animated];
  101. if (!self.highlightedTextColor) { return; }
  102. void (^textFadeBlock)(void) = ^{
  103. self.buttonLabel.textColor = highlighted ? self.highlightedTextColor : self.textColor;
  104. };
  105. if (!animated) {
  106. textFadeBlock();
  107. return;
  108. }
  109. [UIView transitionWithView:self.buttonLabel
  110. duration:0.6f
  111. options:UIViewAnimationOptionTransitionCrossDissolve
  112. animations:textFadeBlock
  113. completion:nil];
  114. }
  115. #pragma mark - Accessors -
  116. - (void)setBackgroundImage:(UIImage *)backgroundImage
  117. {
  118. self.circleView.circleImage = backgroundImage;
  119. CGRect frame = self.frame;
  120. frame.size = backgroundImage.size;
  121. self.frame = CGRectIntegral(frame);
  122. }
  123. - (UIImage *)backgroundImage { return self.circleView.circleImage; }
  124. /***********************************************************/
  125. - (void)setVibrancyEffect:(UIVibrancyEffect *)vibrancyEffect
  126. {
  127. if (_vibrancyEffect == vibrancyEffect) { return; }
  128. _vibrancyEffect = vibrancyEffect;
  129. self.vibrancyView.effect = _vibrancyEffect;
  130. }
  131. /***********************************************************/
  132. - (void)setHightlightedBackgroundImage:(UIImage *)hightlightedBackgroundImage
  133. {
  134. self.circleView.highlightedCircleImage = hightlightedBackgroundImage;
  135. }
  136. - (UIImage *)hightlightedBackgroundImage { return self.circleView.highlightedCircleImage; }
  137. /***********************************************************/
  138. - (void)setNumberFont:(UIFont *)numberFont
  139. {
  140. self.buttonLabel.numberLabelFont = numberFont;
  141. [self setNeedsLayout];
  142. }
  143. - (UIFont *)numberFont { return self.buttonLabel.numberLabelFont; }
  144. /***********************************************************/
  145. - (void)setLetteringFont:(UIFont *)letteringFont
  146. {
  147. self.buttonLabel.letteringLabelFont = letteringFont;
  148. [self setNeedsLayout];
  149. }
  150. - (UIFont *)letteringFont { return self.buttonLabel.letteringLabelFont; }
  151. /***********************************************************/
  152. - (void)setLetteringVerticalSpacing:(CGFloat)letteringVerticalSpacing
  153. {
  154. self.buttonLabel.letteringVerticalSpacing = letteringVerticalSpacing;
  155. [self.buttonLabel setNeedsLayout];
  156. }
  157. - (CGFloat)letteringVerticalSpacing { return self.buttonLabel.letteringVerticalSpacing; }
  158. /***********************************************************/
  159. - (void)setLetteringCharacterSpacing:(CGFloat)letteringCharacterSpacing
  160. {
  161. self.buttonLabel.letteringCharacterSpacing = letteringCharacterSpacing;
  162. }
  163. - (CGFloat)letteringCharacterSpacing { return self.buttonLabel.letteringCharacterSpacing; }
  164. /***********************************************************/
  165. - (void)setTextColor:(UIColor *)textColor
  166. {
  167. if (textColor == _textColor) { return; }
  168. _textColor = textColor;
  169. self.buttonLabel.textColor = _textColor;
  170. }
  171. /***********************************************************/
  172. - (void)setContentAlpha:(CGFloat)contentAlpha
  173. {
  174. if (_contentAlpha == contentAlpha) {
  175. return;
  176. }
  177. _contentAlpha = contentAlpha;
  178. self.buttonLabel.alpha = contentAlpha;
  179. self.circleView.alpha = contentAlpha;
  180. }
  181. @end