0

Been looking for this answer for a while with no luck. From Google to StackOverflow. The only answers I have found so far tell people to call initWithFrame in a view instead of just init. I replaced all my calls to init in UIViews with initWithFrame but I'm not having any luck.

I'm not using IB.

Here is my whole code for that:

@interface UnlockKeyboard : UIView
{
    NSArray *buttons;
    UITextField *passcodeFields;

    UIImage *buttonBackgroundImage;
    UIImage *buttonBackgroundHighlightedImage;
    UIImage *middleButtonBackgroundImage;
    UIImage *middleButtonBackgroundImageHighlighted;
    UIImage *screenBackgroundImage;
    UIImage *keypadViewBackgroundImage;

    UIView *infoView;
    UIView *keypadView;
}
@property(nonatomic, retain)UIImage *buttonBackgroundImage;
@property(nonatomic, retain)UIImage *buttonBackgroundHighlightedImage;
@property(nonatomic, retain)UIImage *screenBackgroundImage;
@property(nonatomic, retain)UIImage* keypadViewBackgroundImage;

@end

@implementation UnlockKeyboard
@synthesize buttonBackgroundImage = _buttonBackgroundImage;
@synthesize buttonBackgroundHighlightedImage = _buttonBackgroundHighlightedImage;
@synthesize screenBackgroundImage = _screenBackgroundImage;
@synthesize keypadViewBackgroundImage = _keypadViewBackgroundImage;
-(id)init
{
    if((self = [super initWithFrame:CGRectMake(0, 0, 320, 480)]))
    {
        _unlockKeyboardBundle = [NSBundle bundleForClass:[self class]];
        buttonBackgroundImage = [UIImage imageWithContentsOfFile:[_unlockKeyboardBundle pathForResource:@"button" ofType:@"png"]];
        middleButtonBackgroundImage = [UIImage imageWithContentsOfFile:[_unlockKeyboardBundle pathForResource:@"middleButton" ofType:@"png"]];
        buttonBackgroundHighlightedImage = [UIImage imageWithContentsOfFile:[_unlockKeyboardBundle pathForResource:@"pushedButton" ofType:@"png"]];
        middleButtonBackgroundImageHighlighted = [UIImage imageWithContentsOfFile:[_unlockKeyboardBundle pathForResource:@"pushedButtonMiddle" ofType:@"png"]];
        keypadView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 200)];
        NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

        NSMutableArray *tempButtons = [NSMutableArray array];
        //self.frame = CGRectMake(320, 480, 0, 0);
        self.backgroundColor = [UIColor lightGrayColor];
        self.opaque = YES;

        UIButton *button1 = [UIButton buttonWithType:UIButtonTypeCustom];
        [button1 setTitle:@"1" forState:UIControlStateNormal];
        button1.frame = CGRectMake(0, 261, 106, 50);

        UIButton *button4 = [UIButton buttonWithType:UIButtonTypeCustom];
        [button4 setTitle:@"4" forState:UIControlStateNormal];
        button4.frame = CGRectMake(0, 311, 106, 50);

        UIButton *button7 = [UIButton buttonWithType:UIButtonTypeCustom];
        [button7 setTitle:@"7" forState:UIControlStateNormal];
        button7.frame = CGRectMake(0, 361, 106, 50);

        UIButton *hint = [UIButton buttonWithType:UIButtonTypeCustom];
        [hint setTitle:NSLocalizedString(@"Hint", @"Hint string") forState:UIControlStateNormal];
        hint.frame = CGRectMake(0, 411, 106, 50);

        UIButton *button2 = [UIButton buttonWithType:UIButtonTypeCustom];
        [button2 setTitle:@"2" forState:UIControlStateNormal];
        button2.frame = CGRectMake(106, 261, 108, 50);

        UIButton *button5 = [UIButton buttonWithType:UIButtonTypeCustom];
        [button5 setTitle:@"5" forState:UIControlStateNormal];
        button5.frame = CGRectMake(106, 311, 108, 50);

        UIButton *button8 = [UIButton buttonWithType:UIButtonTypeCustom];
        [button8 setTitle:@"8" forState:UIControlStateNormal];
        button8.frame = CGRectMake(106, 361, 108, 50);

        UIButton *button0 = [UIButton buttonWithType:UIButtonTypeCustom];
        [button0 setTitle:@"0" forState:UIControlStateNormal];
        button0.frame = CGRectMake(106, 411, 108, 50);

        UIButton *button3 = [UIButton buttonWithType:UIButtonTypeCustom];
        [button3 setTitle:@"3" forState:UIControlStateNormal];
        button3.frame = CGRectMake(214, 261, 106, 50);

        UIButton *button6 = [UIButton buttonWithType:UIButtonTypeCustom];
        [button6 setTitle:@"6" forState:UIControlStateNormal];
        button6.frame = CGRectMake(214, 311, 106, 50);

        UIButton *button9 = [UIButton buttonWithType:UIButtonTypeCustom];
        [button9 setTitle:@"9" forState:UIControlStateNormal];
        button9.frame = CGRectMake(214, 361, 106, 50);

        UIButton *cancelOrDelete = [UIButton buttonWithType:UIButtonTypeCustom];
        [cancelOrDelete setTitle:@"<-" forState:UIControlStateNormal];
        cancelOrDelete.frame = CGRectMake(214, 411, 108, 50);

        [tempButtons addObject:button1];
        [tempButtons addObject:button2];
        [tempButtons addObject:button3];
        [tempButtons addObject:button4];
        [tempButtons addObject:button5];
        [tempButtons addObject:button6];
        [tempButtons addObject:button7];
        [tempButtons addObject:button8];
        [tempButtons addObject:button9];
        [tempButtons addObject:button0];
        [tempButtons addObject:hint];
        [tempButtons addObject:cancelOrDelete];

        for(UIButton *theButton in tempButtons)
        {
            if([theButton.currentTitle isEqualToString:@"2"] || [theButton.currentTitle isEqualToString:@"5"] || [theButton.currentTitle isEqualToString:@"8"] || [theButton.currentTitle isEqualToString:@"0"])
            {
                [theButton setBackgroundImage:middleButtonBackgroundImage forState:UIControlStateNormal];
                [theButton setBackgroundImage:middleButtonBackgroundImageHighlighted forState:UIControlStateHighlighted];
            }else
            {
                [theButton setBackgroundImage:buttonBackgroundImage forState:UIControlStateNormal];
                [theButton setBackgroundImage:middleButtonBackgroundImageHighlighted forState:UIControlStateHighlighted];
            }
            [keypadView addSubview:theButton];
        }
        [self addSubview:keypadView];

        [pool drain];
    }
    return self;
}
-(void)dealloc
{
    [buttons release];
    [passcodeFields release];
    [buttonBackgroundImage release];
    [buttonBackgroundHighlightedImage release];
    [screenBackgroundImage release];
    [infoView release];
    [keypadView release];
    [super dealloc];
}

Like you can see, I subclass UIView with UnlockKeyboard. UnlockKeyboard should have another subview (keypadView) that will contain all the UIButtons. So all in all keyboardView is a subview of UnlockKeyboards, and all these buttons should be inside keyboardView. I can add them just fine, but when I try to tap them, their control state doesn't change. And yes, like you have see, I replaced all calls to init with initWithFrame when creating UIViews.

Any help with this will be really appreciated.

Andy Ibanez
  • 12,104
  • 9
  • 65
  • 100

4 Answers4

2

you need to add targets for the buttons so that they know what method to call when you push them. It would look something like this

[button addTarget:self action:@selector(method) forControlEvents:UIControlEventTouchUpInside];

where self is the instance that contains method, and method is the method that is run when the button is clicked.

Hope this works for you

Cheers,

~John

John Corbett
  • 1,595
  • 10
  • 19
  • My apologies, I forgot to add that the control state of the button doesn't change when I tap on them, so I'm assuming they are not receiving any touches (otherwise my buttons would change their image, but they don't). – Andy Ibanez Jul 26 '12 at 04:39
2

You need to set the image for control state, not the background image for control state:

[btn setImage: [UIImage imageNamed: @"image.png"] forState: UIControlStateNormal];

So it would look like:

[theButton setImage:middleButtonBackgroundImage forState:UIControlStateNormal];
            [theButton setBackgroundImage:middleButtonBackgroundImageHighlighted forState:UIControlStateHighlighted];
David van Dugteren
  • 3,879
  • 9
  • 33
  • 48
  • What I don't like about this is that it hides the button labels. setBackgroundImage works, and the button state changes when I don't add it to a subview. – Andy Ibanez Jul 26 '12 at 04:44
1

Since there's no target or action defined for the buttons, the buttons don't know what you want to do. If you did have an action, you could use the action method to change the state of the sender (the sender being the button).

Michael Dautermann
  • 88,797
  • 17
  • 166
  • 215
  • My apologies, I forgot to add that the control state of the button doesn't change when I tap on them, so I'm assuming they are not receiving any touches (otherwise my buttons would change their image, but they don't). – Andy Ibanez Jul 26 '12 at 04:39
  • @DavidvanDugteren's suggestion is good too (so +1 to him!), but you do need to set some kind of target and action for your buttons. Set a breakpoint in that action method and *then* you should see the button calling the action method. – Michael Dautermann Jul 26 '12 at 04:43
  • Yeah, I will write that eventually, but if my button state doesn't change it can just mean it's not receiving any touches, right? I just removed the buttons from the subview and added them to the main view and they change state just fine. – Andy Ibanez Jul 26 '12 at 04:46
  • ohhhh, perhaps you have "`userInteractionEnabled = NO`" set for the subview that includes your buttons then? turn it on explicitly and see what happens. – Michael Dautermann Jul 26 '12 at 04:48
  • if you just put a "`NSLog`" into a method and set your buttons to call "`target = self;`" and method as an action, do the NSLogs get called? – Michael Dautermann Jul 26 '12 at 04:55
  • Yep, the method isn't getting called. Looks like something's blocking it. I also learned that userInteractionEnabled should definitely set to no, otherwise the view itself will handle the events. I will try setting the main view's to "NO" (though I don't think it will work...), and see what happens. – Andy Ibanez Jul 26 '12 at 05:01
  • Nada still, but I noticed that for some reason my UIButtons aren't kept between the frames of the view (my buttons go down, the actual view stays up... I tested with backGround color). When I finally put both the view and the buttons at the same coordinates, the subview's background colors is on top of the actual buttons. I would think the buttons would go on top of the view and not the other way around. I think I'm getting somewhere with this but I'm not quite there yet. – Andy Ibanez Jul 26 '12 at 05:10
0

Figured it out. The way I was setting the button frames in regards to keypadView was complete messed up. I had forgotten to do some frame changes to my buttons when I decided to add them to the superview, so the buttons displayed correctly, "but their coordinates were not right" in regards to their touch events. So the actual button was for example in (3,4), but it's touchpoint was in (10,20).

Fixing the frames to play better with the superview fixed my issues

Andy Ibanez
  • 12,104
  • 9
  • 65
  • 100