简体   繁体   中英

iOS action:@selector issue when UIButton is added to another UIButton. Action only works where buttons intersect

I have a UIButton2 that is added on to UIButton1:

按钮相交

The action @selector only gets called where UIButton2 intersects UIButton1 (the "b"). So, a tap in the "a" or "c" area, the action method (addDockButtonTouchedDown) does NOT get called, but it does when you tap in the "b" section. Here's some code:

    // button1 is created elsewhere in the code and is a subclass of UIButton for UI layout (has a footer label and title label set). nothing fancy going on.  button1 userInteractionEnabled is set to yes 
    // button2 is below... 
    NSString *dockPath = [[NSBundle mainBundle] pathForResource:@"AddToMyDock" ofType:@"png"];
    UIImage *dockImage = [UIImage imageWithContentsOfFile:dockPath];
    CGRect rect = CGRectMake(-20.0f, -10.0f + dockImage.size.height+1, dockImage.size.width, dockImage.size.height);
    UIButton *button2 = [[UIButton alloc] initWithFrame:rect];
    button2.userInteractionEnabled = YES;
    button2.exclusiveTouch = YES;
    [button2 setBackgroundImage:dockImage forState:UIControlStateNormal];
    [button2 addTarget:self action:@selector(addDockButtonTouchedDown:)
         forControlEvents:UIControlEventTouchDown];
    [button1 addSubview:button2];

Any ideas why this is happening and how to fix it??? Please don't suggest to simply make button1 bigger.

First of all, adding a button as a subview of another button isn't really common design and I would avoid doing that. Simply create a container UIView that holds both buttons.

The problem you're seeing is because while your button may be displayed beyond the bounds of its superview (the other button), actions on the outside of button1's bounds won't be registered. The only reason you can see button2, is because clipsToBounds is set to NO on button1, which allows its subviews to be drawn outside of its bounds.

So, the only way to make your current solution work is indeed by making button1 bigger. However, the better option would be to create superview that's big enough to hold both buttons, and add both buttons to it.

It not works on "a" and "c" regions because the hit test for the touch event fails there when called for button1. You should subclass UIButton for button1 and override the hit test with something like this:

 - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
    if(CGRectContainsPoint(self.childButton.frame, point)) {
        return [self.childButton hitTest:[self convertPoint:point toView:self.childButton] withEvent:event];
    }
    return [super hitTest:point withEvent:event];
 }

Note: childButton is button2 in your example.

Note2: I think that however this should work, the ugliness of this is a sign of a design problem, but that's your business.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM