1

I have added to a view an UIView and an UIButton that is placed below the view under left bottom corner.

I've added corner radius to the UIView object this way:

self.myView.layer.cornerRadius = self.myView.frame.size.width/2;
self.myView.layer.masksToBounds = YES;

Now it has the shape of a circle, and my button is visible. See the picture below: enter image description here

The problem is that I can't press the button (it's not highlighting). How can I make it touchable?

I know that placing the button to front will solve the problem, but I would like to know if is there a way to press it by keeping below the view.

iOS Dev
  • 4,143
  • 5
  • 30
  • 58

7 Answers7

2

This question was solved by following this link: Allowing interaction with a UIView under another UIView

The recursive hittest is the one I recommend using. But the accepted answer is quite interesting as well (making views transparant for touches or something).

Community
  • 1
  • 1
Totumus Maximus
  • 7,543
  • 6
  • 45
  • 69
2

You need to subclass UIView for use as your circle and overwrite the following method:

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event{
    CGFloat radius = self.frame.size.width/2;
    CGFloat distance = sqrtf(powf(point.x-self.frame.size.width/2, 2)+powf(point.y-self.frame.size.height/2, 2));
    if(distance<radius)
        return [super hitTest:point withEvent:event];
    return nil;
}

This makes the view only accept touches inside the circle. You may need to adjust the logic to fit your view.

robert
  • 2,822
  • 1
  • 16
  • 19
  • 1
    Instead of returning `self`, you should return the result of `[super hitTest:point withEvent:event]` to allow touches on the circle and its subviews. – meaning-matters Aug 22 '16 at 07:33
1

Your button is probably being covered. You could either add the button after, or use this method to bring it to the front, [parentView bringSubviewToFront:childView];

mginn
  • 16,036
  • 4
  • 26
  • 54
1

Setting the userInteractionEnabled property of your circle view to NO will pass the touch through to the button.

self.myView.userInteractionEnabled = NO;
hgwhittle
  • 9,316
  • 6
  • 48
  • 60
1

@robert's answer, with small correction, in swift:

override func hitTest(point: CGPoint, withEvent event: UIEvent?) -> UIView?
{
    let radius   = self.frame.size.width / 2
    let distance = sqrt(pow(point.x - self.frame.size.width  / 2, 2) +
                        pow(point.y - self.frame.size.height / 2, 2))

    return distance < radius ? super.hitTest(point, withEvent: event) : nil
}
meaning-matters
  • 21,929
  • 10
  • 82
  • 142
0

There are different ways; depends on what you mean by "touchable"

You can just add a target action to the button to allow operations to take place when pressing the button. You'd do this by saying

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

then you have to declare this method

- (void) methodForTouchingButton
{ NSLog(@"Button Touched!"); }

Another way you could do is try adding it to the top level view. Doing so would be

[self.myView addSubview:button];

and that should do it.

Hope this helps!!

user2277872
  • 2,963
  • 1
  • 21
  • 22
0

Put the button on top of the view, not underneath. The view is covering the button, even though you have a corner radius. Views use their frame rectangle to determine which view gets a tap.

Duncan C
  • 128,072
  • 22
  • 173
  • 272
  • I know that placing the button to front will solve the problem, but I would like to know if is there a way to press it by keeping below the view. – iOS Dev Jun 02 '14 at 14:05
  • If your view has user interaction enabled then it will get the touches rather than the button when the view covers the button. You might be able to code a custom view that has code to figure out that the tap is outside the circle and pass the touch event to the button. In that case you would probably want the button to be a subview of your circle view, and your circle view to be a custom class of your creation. – Duncan C Jun 02 '14 at 15:01