Home > Software design >  UIButton in a custom UIView is not being triggered when tapped upon
UIButton in a custom UIView is not being triggered when tapped upon

Time:11-19

I've placed a UIButton inside a custom UIView, CustomButtonView. The UIButton is not responding to tap/click events, and its appropriate selector method is not being triggered. Here's my code below; what have I done wrong?

As well, the custom view has a background color of red. When I add the custom view to my view controller's view, the red rectangle displays. However, when I add my UIButton to my custom view (with the background color of red), only the UIButton displays, not the red rectangle. Why is this happening?

//
//  CustomButtonView.h
//
//

#import <UIKit/UIKit.h>

NS_ASSUME_NONNULL_BEGIN

@interface  CustomButtonView : UIView

@property (strong, nonatomic) UIImageView *buttonImageView;
@property (strong, nonatomic) UIButton *button;

@end

NS_ASSUME_NONNULL_END

//
//  CustomButtonView.m
//

#import "CustomButtonView.h"

@implementation CustomButtonView

- (instancetype)initWithFrame:(CGRect)frame{
    self = [super initWithFrame:frame];

    if (self) {
        self.backgroundColor = [UIColor redColor];
        _button = [UIButton buttonWithType:UIButtonTypeSystem];
        _button.backgroundColor = [UIColor greenColor];
        [_button setTitle:@"john doe" forState:UIControlStateNormal];
        [_button setTitle:@"john doe" forState:UIControlStateHighlighted];
        _button.translatesAutoresizingMaskIntoConstraints = NO;
        _button.titleLabel.font = [UIFont boldSystemFontOfSize:14.0];
        _button.titleLabel.textColor = [UIColor whiteColor];
        self.userInteractionEnabled = NO;
        self.button.userInteractionEnabled = YES;
        //[self addSubview:_button];
        //[_button.topAnchor constraintEqualToAnchor:self.topAnchor].active = YES;
        //[_button.leadingAnchor constraintEqualToAnchor:self.leadingAnchor].active = YES;
    }
    return self;

}

@end
//
//  ViewController.m
//  TestApp
//
//

#import "ViewController.h"
#import "CustomButtonView.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    self.view.backgroundColor = [UIColor yellowColor];
    _customButtonView = [[CustomButtonView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
    _customButtonView.backgroundColor = [UIColor redColor];
    _customButtonView.translatesAutoresizingMaskIntoConstraints = NO;
    [_customButtonView.button addTarget:self action:@selector(customButtonTapped:) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:_customButtonView];
}

- (void)customButtonTapped:(id)sender{
    NSLog(@"Button tapped!");
}

@end

Here are some screenshots, below. Please click on the links.

When I display the UIButton inside the custom-view, only the button displays. The red rectangle of the custom-view doesn't display.

When I simply add the custom-view to my view-controller (ie with no UIButton added to the custom view), the red rectangle of the custom-view displays.

CodePudding user response:

When you disable user interaction for a specific view then this user interaction is not forwarded to its subviews. Or in other words; for user interaction to work you need to make sure that all superviews in chain (superview of superview of superview) do have user interaction enabled.

In your case you have self.userInteractionEnabled = NO; which means that any subview of self (including your button) will not accept any user interaction.

Next to this issues it is still possible that other issues are present. For instance: A subview will accept user interaction only within physical area of all of its superviews. That means that if a button with frame { 0, 0, 100, 100 } is placed on a superview of size { 100, 50 } then only the top part of the button will be clickable.

As for the size changes this is a completely different story... You decided to disable translation of autoresizing mask on your custom view by writing _customButtonView.translatesAutoresizingMaskIntoConstraints = NO;. That means that you will not use frame in conjunction with other constraints. It means that whatever frame you set (in your case CGRectMake(0, 0, 100, 100)) this frame will be overridden by anything else that may effect the frame of your custom view.

In case where your button code is commented out there is no such thing that "may effect the frame of your custom view" and the view stays as size of { 100, 100 }. But as soon as you added a button you added additional constraints which most likely lead to resizing your button to sizeToFit and with it its superview which is your custom view.

To avoid this you need to either remove disabling of translation of autoresizing mask into constraint on your custom view. Or you need to define custom view size by adding constraints to it so that they are set to { 100, 100 }. You can simply constrain heightAnchor and widthAnchor to 100.

  • Related