podkovyrin/APNumberPad

Updates to modernise the look of the number pad - rounded buttons for iOS15+

ghr1234 opened this issue · 0 comments

This is more informational than an issue. I hope some find it useful.

Thank you for this project. I was able to use it to replace a solution in a couple of 10-year-old apps whose keypads failed after a recent iOS update.

I offer the following method replacements to achieve a keypad that is closer in look to the current keypad with rounded buttons and, for my use cases, changed to place OK in the bottom left corner.
Please use if desired and/or update the base (with improved style as needed). I am not versed in SwiftPM, Cocoapods, Carthage etc. I used the code files from the zip download and modified as needed.

NumberPad example.pdf

In APNumberPadDefaultStyle.m

+ (CGRect)numberPadFrame {
    CGFloat safeAreaHeight = 0.0f;
    if (@available(iOS 13.0, *)) {
        UIEdgeInsets x = [[[UIApplication sharedApplication] windows][0] safeAreaInsets] ;
        safeAreaHeight = x.bottom;
    }
    if (safeAreaHeight > 0)
        return CGRectMake(0.0, 0.0, 320.0, 260.0);
    else
        return CGRectMake(0.0, 0.0, 320.0, 216.0);
}

+ (CGFloat)separator {
    return 6.0; //[UIScreen mainScreen].scale == 2.0 ? 6.0 : 6.0;
}

In APNumberPad.m

- (instancetype)initWithDelegate:(id<APNumberPadDelegate>)delegate numberPadStyleClass:(Class)styleClass {
    buttonsAdded = NO;
    self = [super initWithFrame:CGRectZero];
    if (self) {
        self.styleClass = styleClass;
        self.frame = [self.styleClass numberPadFrame];
//        self.autoresizingMask = UIViewAutoresizingFlexibleHeight; // for support rotation
        self.backgroundColor = [self.styleClass numberPadBackgroundColor];

        [self addNotificationsObservers];

        self.delegate = delegate;

        // Number buttons (0-9)
        //
        NSMutableArray *numberButtons = [NSMutableArray array];
        for (int i = 0; i < 11; i++) {
            APNumberButton *numberButton = [self numberButton:i];
//            [self addSubview:numberButton];
            [numberButtons addObject:numberButton];
        }
        self.numberButtons = numberButtons;

        self.safeAreaCover = [[UIView alloc] initWithFrame:CGRectZero];
        self.safeAreaCover.backgroundColor = [self.styleClass safeAreaSpaceColor];
        [self addSubview:self.safeAreaCover];

        // Function button
        //
        self.leftButton = [self functionButton];
        if (@available(iOS 15.0, *)) {
            UIButtonConfiguration *conf = _leftButton.configuration;
            NSMutableAttributedString *title = [[NSMutableAttributedString alloc] initWithString:@"OK"];

            // Declare the fonts
            UIFont *titleFont1 = [APNumberPadDefaultStyle functionButtonFont];

            UIColor *titleColour1 = [APNumberPadDefaultStyle functionButtonTextColor];
            
            // Create the attributes and add them to the string
            [title addAttribute:NSFontAttributeName value:titleFont1 range:NSMakeRange(0,2)];
            [title addAttribute:NSForegroundColorAttributeName value:titleColour1 range:NSMakeRange(0,2)];
            conf.attributedTitle = title;

            _leftButton.configuration = conf;
            
        }
        else {
            self.leftButton.titleLabel.font = [self.styleClass functionButtonFont];
            [self.leftButton setTitleColor:[self.styleClass functionButtonTextColor] forState:UIControlStateNormal];
            [self.leftButton setTitle:@"OK" forState:UIControlStateNormal];
        }
        [self.leftButton addTarget:self action:@selector(functionButtonAction:) forControlEvents:UIControlEventTouchUpInside];
//        [self addSubview:self.leftButton];

        // Clear button
        //
        self.clearButton = [self functionButton];
        [self.clearButton setTitle:@"" forState:UIControlStateNormal];
        [self.clearButton setImage:[self.styleClass backspaceFunctionButtonImage] forState:UIControlStateNormal];
        [self.clearButton setImage:[self.styleClass backspaceFunctionButtonImageHighlighted] forState:UIControlStateHighlighted];
        [self.clearButton addTarget:self action:@selector(clearButtonAction) forControlEvents:UIControlEventTouchUpInside];

        UILongPressGestureRecognizer *longPressGestureRecognizer = [[UILongPressGestureRecognizer alloc]
            initWithTarget:self
                    action:@selector(longPressGestureRecognizerAction:)];
        longPressGestureRecognizer.cancelsTouchesInView = NO;
        [self.clearButton addGestureRecognizer:longPressGestureRecognizer];
        [self addSubview:self.clearButton];
    }
    return self;
}

#pragma mark - Button fabric
- (APNumberButton *)numberButton:(int)number {
    APNumberButton *b = [APNumberButton buttonWithBackgroundColor:[self.styleClass numberButtonBackgroundColor]
                                                 highlightedColor:[self.styleClass numberButtonHighlightedColor]];
    if(@available(iOS 15.0,*))
    {
        UIButtonConfiguration *conf = b.configuration;
        NSMutableAttributedString *title = [[NSMutableAttributedString alloc] initWithString:
                                            [NSString stringWithFormat:@"%d", number]];

        // Declare the font and colour
        UIFont *titleFont1    = [APNumberPadDefaultStyle numberButtonFont];
        UIColor *titleColour1 = [self.styleClass numberButtonTextColor];
        
        // Create the attributes and add them to the string
        [title addAttribute:NSFontAttributeName value:titleFont1 range:NSMakeRange(0,1)];
        [title addAttribute:NSForegroundColorAttributeName value:titleColour1 range:NSMakeRange(0,1)];
        conf.attributedTitle = title;

        b.configuration = conf;
    }
    else {
        [b setTitleColor:[self.styleClass numberButtonTextColor] forState:UIControlStateNormal];
        b.titleLabel.font = [self.styleClass numberButtonFont];
        [b setTitle:[NSString stringWithFormat:@"%d", number] forState:UIControlStateNormal];
    }
    return b;
}

In APNumberButton.m

+ (UIImage *)ap_imageWithColor:(UIColor *)color {
    CGRect rect = CGRectMake(0.0, 0.0, 1.0, 1.0);
    if(@available(iOS 15.0, *))
    {
        // Should work since iOS10 but doesn't in ios 14.5 simulator! - Godfrey
        UIGraphicsImageRendererFormat *format = [UIGraphicsImageRendererFormat defaultFormat];
        format.scale = 1.0;
        UIGraphicsImageRenderer *renderer = [[UIGraphicsImageRenderer alloc] initWithSize:rect.size
                                                                                   format: format];
        
        UIImage *image = [renderer imageWithActions:^(UIGraphicsImageRendererContext * _Nonnull context) {
            [color setStroke];
            [context fillRect:rect];
        }];
        return image;
    }
    else
    {
        UIGraphicsBeginImageContext(rect.size);
        CGContextRef context = UIGraphicsGetCurrentContext();
        
        CGContextSetFillColorWithColor(context, [color CGColor]);
        CGContextFillRect(context, rect);
        
        UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
        return image;
    }
}

- (instancetype)initWithBackgroundColor:(UIColor *)backgroundColor highlightedColor:(UIColor *)highlightedColor {
    self = [super initWithFrame:CGRectZero];
    if (self) {
        if (@available(iOS 15.0, *))
        {
            UIButtonConfiguration *conf = [UIButtonConfiguration filledButtonConfiguration];
            conf.cornerStyle = UIButtonConfigurationCornerStyleSmall;
            conf.baseForegroundColor = highlightedColor;
            conf.baseBackgroundColor = backgroundColor;
            // Create the attributed string
            NSMutableAttributedString *title = [[NSMutableAttributedString alloc]initWithString:@" "];

            // Declare the fonts
            UIFont *titleFont1 = [UIFont fontWithName:@"Helvetica-Bold" size:10.0]; // place holder

            // Create the attributes and add them to the string
            [title addAttribute:NSFontAttributeName value:titleFont1 range:NSMakeRange(0,1)];
            conf.attributedTitle = title;
            self.configuration = conf;
        }
        else
        {
            [self setBackgroundImage:[UIImage ap_imageWithColor:backgroundColor] forState:UIControlStateNormal];
            [self setBackgroundImage:[UIImage ap_imageWithColor:highlightedColor] forState:UIControlStateHighlighted];
        }
    }
    return self;
}