0

I am an IOS beginner.

I am trying to show a custom button with code generated by paintcode. I drag a View on Storyboard then set this generic view class to my custom view "GreenButton". When I run the app, the button does not show up. I added NSLogs and could see the drawRect method worked successfully.

The code generated by paintcode seems to include everything to draw the button. I just use XCode to resize my view.

Do I need to implement initWithFrame method at all?

//
//  GreenButton.m
//  Test
//
//  Created by Tim on 13.04.2013.
//  Copyright (c) 2013 Tim. All rights reserved.
//

#import "GreenButton.h"

@implementation GreenButton

- (id)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        // setup the initial properties of the view

    }
    return self;

}

#pragma mark - Touch event overrides


// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect
{
    NSLog(@"drawRect enter");
    //// General Declarations
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    CGContextRef context = UIGraphicsGetCurrentContext();

    //// Color Declarations
    UIColor* strokeColor = [UIColor colorWithRed: 0.419 green: 0.434 blue: 0.455 alpha: 1];
    UIColor* baseColor = [UIColor colorWithRed: 0.218 green: 0.24 blue: 0.268 alpha: 1];
    CGFloat baseColorRGBA[4];
    [baseColor getRed: &baseColorRGBA[0] green: &baseColorRGBA[1] blue: &baseColorRGBA[2] alpha: &baseColorRGBA[3]];

    UIColor* upperColor = [UIColor colorWithRed: (baseColorRGBA[0] * 0.8 + 0.2) green: (baseColorRGBA[1] * 0.8 + 0.2) blue: (baseColorRGBA[2] * 0.8 + 0.2) alpha: (baseColorRGBA[3] * 0.8 + 0.2)];
    UIColor* lowerColor = [UIColor colorWithRed: (baseColorRGBA[0] * 0.9) green: (baseColorRGBA[1] * 0.9) blue: (baseColorRGBA[2] * 0.9) alpha: (baseColorRGBA[3] * 0.9 + 0.1)];
    UIColor* lightUpColor = [UIColor colorWithRed: (baseColorRGBA[0] * 0.5 + 0.5) green: (baseColorRGBA[1] * 0.5 + 0.5) blue: (baseColorRGBA[2] * 0.5 + 0.5) alpha: (baseColorRGBA[3] * 0.5 + 0.5)];
    UIColor* lightDownColor = [UIColor colorWithRed: (baseColorRGBA[0] * 0.8) green: (baseColorRGBA[1] * 0.8) blue: (baseColorRGBA[2] * 0.8) alpha: (baseColorRGBA[3] * 0.8 + 0.2)];

    //// Gradient Declarations
    NSArray* buttonGradientColors = [NSArray arrayWithObjects:
                                     (id)upperColor.CGColor,
                                     (id)lowerColor.CGColor, nil];
    CGFloat buttonGradientLocations[] = {0, 1};
    CGGradientRef buttonGradient = CGGradientCreateWithColors(colorSpace, (__bridge CFArrayRef)buttonGradientColors, buttonGradientLocations);
    NSArray* overlayGradientColors = [NSArray arrayWithObjects:
                                      (id)lightUpColor.CGColor,
                                      (id)[UIColor clearColor].CGColor, nil];
    CGFloat overlayGradientLocations[] = {0, 1};
    CGGradientRef overlayGradient = CGGradientCreateWithColors(colorSpace, (__bridge CFArrayRef)overlayGradientColors, overlayGradientLocations);
    NSArray* gradientColors = [NSArray arrayWithObjects:
                               (id)lightUpColor.CGColor,
                               (id)lightDownColor.CGColor, nil];
    CGFloat gradientLocations[] = {0, 1};
    CGGradientRef gradient = CGGradientCreateWithColors(colorSpace, (__bridge CFArrayRef)gradientColors, gradientLocations);

    //// Shadow Declarations
    UIColor* buttonShadow = [UIColor blackColor];
    CGSize buttonShadowOffset = CGSizeMake(0.1, 1.1);
    CGFloat buttonShadowBlurRadius = 2;
    UIColor* textShadow = [UIColor blackColor];
    CGSize textShadowOffset = CGSizeMake(0.1, -0.1);
    CGFloat textShadowBlurRadius = 5;

    //// Abstracted Attributes
    NSString* textContent = @"Update";


    //// Back Rectangle Drawing
    UIBezierPath* backRectanglePath = [UIBezierPath bezierPathWithRoundedRect: CGRectMake(48, 53, 120, 23) cornerRadius: 4];
    CGContextSaveGState(context);
    CGContextSetShadowWithColor(context, buttonShadowOffset, buttonShadowBlurRadius, buttonShadow.CGColor);
    CGContextBeginTransparencyLayer(context, NULL);
    [backRectanglePath addClip];
    CGContextDrawLinearGradient(context, gradient, CGPointMake(108, 53), CGPointMake(108, 76), 0);
    CGContextEndTransparencyLayer(context);
    CGContextRestoreGState(context);



    //// Rounded Rectangle Drawing
    UIBezierPath* roundedRectanglePath = [UIBezierPath bezierPathWithRoundedRect: CGRectMake(49, 54, 118, 21) cornerRadius: 3];
    CGContextSaveGState(context);
    [roundedRectanglePath addClip];
    CGContextDrawLinearGradient(context, buttonGradient, CGPointMake(108, 54), CGPointMake(108, 75), 0);
    CGContextRestoreGState(context);


    //// Overlay Drawing
    UIBezierPath* overlayPath = [UIBezierPath bezierPathWithRoundedRect: CGRectMake(48, 53, 120, 23) cornerRadius: 4];
    CGContextSaveGState(context);
    [overlayPath addClip];
    CGContextDrawRadialGradient(context, overlayGradient,
                                CGPointMake(54.72, 38.09), 10,
                                CGPointMake(108, 11.46), 102.2,
                                kCGGradientDrawsBeforeStartLocation | kCGGradientDrawsAfterEndLocation);
    CGContextRestoreGState(context);


    //// Text Drawing
    CGRect textRect = CGRectMake(55, 54, 104, 21);
    UIBezierPath* textPath = [UIBezierPath bezierPathWithRect: textRect];
    CGContextSaveGState(context);
    CGContextSetShadowWithColor(context, textShadowOffset, textShadowBlurRadius, textShadow.CGColor);
    CGContextBeginTransparencyLayer(context, NULL);
    [textPath addClip];
    CGContextDrawLinearGradient(context, buttonGradient, CGPointMake(107, 54), CGPointMake(107, 75), 0);
    CGContextEndTransparencyLayer(context);
    CGContextRestoreGState(context);

    [strokeColor setStroke];
    textPath.lineWidth = 1;
    [textPath stroke];
    CGContextSaveGState(context);
    CGContextSetShadowWithColor(context, textShadowOffset, textShadowBlurRadius, textShadow.CGColor);
    [[UIColor whiteColor] setFill];
    [textContent drawInRect: textRect withFont: [UIFont boldSystemFontOfSize: [UIFont systemFontSize]] lineBreakMode: NSLineBreakByWordWrapping alignment: NSTextAlignmentCenter];
    CGContextRestoreGState(context);



    //// Cleanup
    CGGradientRelease(buttonGradient);
    CGGradientRelease(overlayGradient);
    CGGradientRelease(gradient);
    CGColorSpaceRelease(colorSpace);

    NSLog(@"drawRect exit");



}


@end
Jay
  • 6,572
  • 3
  • 37
  • 65
Timuçin
  • 4,653
  • 3
  • 25
  • 34

1 Answers1

2

You do not need to implement initWithFrame: when using a Storyboard. In fact, the storyboard will use initWithCoder: so it won't even be called.

I tested your code, and it works fine, however, you are not drawing in the top left corner, but somewhere in the middle of the view, so be sure to make the view large enough if you want to see your button.

Preferably draw in the top left corner.

Hjalmar
  • 989
  • 8
  • 16
  • Thanks for the explanation. I want to use storyboard to resize or move my button. So, aren't those hardcoded width,height or coordinates useless in drawRect method? – Timuçin Apr 13 '13 at 11:03
  • I'm not sure what you mean by "useless", but the button will be drawn in the view where ever you draw it. You can't resize or move the button itself in a storyboard. Only the view that contains it. Thus, I recommend drawing the button in the top left corner. Then things will become a lot easier. – Hjalmar Apr 13 '13 at 11:19