123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254 |
- #import "TOPasscodeVariableInputView.h"
- #import "TOPasscodeCircleImage.h"
- @interface TOPasscodeVariableInputView ()
- @property (nonatomic, strong) UIImage *backgroundImage;
- @property (nonatomic, strong) UIImage *circleImage;
- @property (nonatomic, strong) NSMutableArray<UIImageView *> *circleViews;
- @end
- @implementation TOPasscodeVariableInputView
- #pragma mark - Class Creation -
- - (instancetype)initWithFrame:(CGRect)frame
- {
- if (self = [super initWithFrame:frame]) {
- _outlineThickness = 1.0f;
- _outlineCornerRadius = 5.0f;
- _circleDiameter = 11.0f;
- _circleSpacing = 7.0f;
- _outlinePadding = (CGSize){10,10};
- _maximumVisibleLength = 12;
- }
- return self;
- }
- #pragma mark - View Setup -
- - (void)setUpImageForCircleViews
- {
- if (self.circleImage != nil) { return; }
- self.circleImage = [TOPasscodeCircleImage circleImageOfSize:_circleDiameter inset:0.0f padding:1.0f antialias:YES];
- for (UIImageView *circleView in self.circleViews) {
- circleView.image = self.circleImage;
- [circleView sizeToFit];
- }
- }
- - (void)setUpCircleViewsForLength:(NSInteger)length
- {
-
- if (self.circleViews.count == length) { return; }
- if (self.circleViews == nil) {
- self.circleViews = [NSMutableArray arrayWithCapacity:_maximumVisibleLength];
- }
-
- while (self.circleViews.count > length) {
- UIImageView *circleView = self.circleViews.lastObject;
- [circleView removeFromSuperview];
- [self.circleViews removeLastObject];
- }
-
- [UIView performWithoutAnimation:^{
- while (self.circleViews.count < length) {
- UIImageView *circleView = [[UIImageView alloc] initWithImage:self.circleImage];
- circleView.alpha = 0.0f;
- [self addSubview:circleView];
- [self.circleViews addObject:circleView];
- }
- }];
- }
- - (void)setUpBackgroundImage
- {
- if (self.backgroundImage != nil) { return; }
- self.backgroundImage = [[self class] backgroundImageWithThickness:_outlineThickness cornerRadius:_outlineCornerRadius];
- self.image = self.backgroundImage;
- }
- #pragma mark - View Layout -
- - (void)sizeToFit
- {
- CGRect frame = self.frame;
-
- frame.size.width = self.outlineThickness * 2.0f;
- frame.size.width += (self.outlinePadding.width * 2.0f);
- frame.size.width += (self.maximumVisibleLength * (self.circleDiameter+2.0f));
- frame.size.width += ((self.maximumVisibleLength - 1) * self.circleSpacing);
-
- frame.size.height = self.outlineThickness * 2.0f;
- frame.size.height += self.outlinePadding.height * 2.0f;
- frame.size.height += self.circleDiameter;
- self.frame = CGRectIntegral(frame);
- }
- - (void)layoutSubviews
- {
- [super layoutSubviews];
-
- [self setUpBackgroundImage];
-
- [self setUpImageForCircleViews];
-
- [self setUpCircleViewsForLength:self.maximumVisibleLength];
-
- CGRect frame = CGRectZero;
- frame.size = self.circleImage.size;
- frame.origin.y = CGRectGetMidY(self.bounds) - (frame.size.height * 0.5f);
- frame.origin.x = self.outlinePadding.width + self.outlineThickness;
- for (UIImageView *circleView in self.circleViews) {
- circleView.frame = frame;
- frame.origin.x += frame.size.width + self.circleSpacing;
- }
- }
- #pragma mark - Accessors -
- - (void)setOutlineThickness:(CGFloat)outlineThickness
- {
- if (_outlineThickness == outlineThickness) { return; }
- _outlineThickness = outlineThickness;
- self.backgroundImage = nil;
- [self setNeedsLayout];
- }
- - (void)setOutlineCornerRadius:(CGFloat)outlineCornerRadius
- {
- if (_outlineCornerRadius == outlineCornerRadius) { return; }
- _outlineCornerRadius = outlineCornerRadius;
- self.backgroundImage = nil;
- [self setNeedsLayout];
- }
- - (void)setCircleDiameter:(CGFloat)circleDiameter
- {
- if (_circleDiameter == circleDiameter) { return; }
- _circleDiameter = circleDiameter;
- self.circleImage = nil;
- [self setUpImageForCircleViews];
- }
- - (void)setCircleSpacing:(CGFloat)circleSpacing
- {
- if (_circleSpacing == circleSpacing) { return; }
- _circleSpacing = circleSpacing;
- [self sizeToFit];
- [self setNeedsLayout];
- }
- - (void)setOutlinePadding:(CGSize)outlinePadding
- {
- if (CGSizeEqualToSize(outlinePadding, _outlinePadding)) { return; }
- _outlinePadding = outlinePadding;
- [self sizeToFit];
- [self setNeedsLayout];
- }
- - (void)setMaximumVisibleLength:(NSInteger)maximumVisibleLength
- {
- if (_maximumVisibleLength == maximumVisibleLength) { return; }
- _maximumVisibleLength = maximumVisibleLength;
- [self setUpCircleViewsForLength:maximumVisibleLength];
- [self sizeToFit];
- [self setNeedsLayout];
- }
- - (void)setLength:(NSInteger)length
- {
- [self setLength:length animated:NO];
- }
- - (void)setLength:(NSInteger)length animated:(BOOL)animated
- {
- if (length == _length) { return; }
- _length = length;
- void (^animationBlock)(void) = ^{
- NSInteger i = 0;
- for (UIImageView *circleView in self.circleViews) {
- circleView.alpha = i < length ? 1.0f : 0.0f;
- i++;
- }
- };
- if (!animated) {
- animationBlock();
- return;
- }
- [UIView animateWithDuration:0.4f animations:animationBlock];
- }
- #pragma mark - Image Creation -
- + (UIImage *)backgroundImageWithThickness:(CGFloat)thickness cornerRadius:(CGFloat)radius
- {
- CGFloat inset = thickness / 2.0f;
- CGFloat dimension = (radius * 2.0f) + 2.0f;
- CGRect frame = CGRectZero;
- frame.origin = CGPointMake(inset, inset);
- frame.size = CGSizeMake(dimension, dimension);
- CGSize canvasSize = frame.size;
- canvasSize.width += thickness;
- canvasSize.height += thickness;
- UIGraphicsBeginImageContextWithOptions(canvasSize, NO, 0.0f);
- {
- UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:frame cornerRadius:radius];
- path.lineWidth = thickness;
- [[UIColor blackColor] setStroke];
- [path stroke];
- }
- UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
- UIGraphicsEndImageContext();
- UIEdgeInsets insets = UIEdgeInsetsMake(radius+1, radius+1, radius+1, radius+1);
- image = [image resizableImageWithCapInsets:insets];
- return [image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
- }
- @end
|