UIButton
UIView
iOS Development
Transparency
User Interface

How can I click a button behind a transparent UIView?

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

A transparent UIView still participates in hit-testing, so it can block touches even when the user can see a button underneath it. If the overlay should not handle touches at all, disable interaction on the overlay. If only some parts of the overlay should pass touches through, customize hit-testing instead of relying on visual transparency.

The simplest fix: disable interaction on the overlay

If the transparent view is only decorative, the cleanest solution is:

swift
overlayView.isUserInteractionEnabled = false

That tells UIKit to ignore the overlay during hit-testing, so taps continue down to views behind it, including the button.

This is the best option for overlays used for:

  • gradients
  • dimming layers with no controls
  • status badges
  • purely visual containers

It is also the safest because it leaves the system hit-testing rules intact instead of trying to outsmart them.

Why transparency alone does not help

UIKit decides touch handling from the view hierarchy, bounds, visibility, and interaction settings. It does not say "this view is clear, so let the touch go through". A fully transparent view is still a real view.

That is why code like this can still block the button:

swift
overlayView.backgroundColor = .clear
overlayView.alpha = 1.0

The overlay is visually transparent, but it still wins the hit test if it sits on top and interaction is enabled.

Pass touches through selectively with a custom view

Sometimes the overlay needs to handle touches on some subviews, such as close buttons or drag handles, while allowing taps in the empty transparent area to hit the button underneath. In that case, create a passthrough view:

swift
1import UIKit
2
3final class PassthroughView: UIView {
4    override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
5        for subview in subviews where !subview.isHidden && subview.alpha > 0.01 && subview.isUserInteractionEnabled {
6            let convertedPoint = subview.convert(point, from: self)
7            if subview.point(inside: convertedPoint, with: event) {
8                return true
9            }
10        }
11        return false
12    }
13}

Use PassthroughView as the overlay class. With this implementation:

  • taps on interactive subviews inside the overlay are handled by those subviews
  • taps on empty transparent space return false
  • UIKit continues searching underlying views, so the button behind the overlay can receive the touch

This pattern is ideal for floating overlays that contain a few visible controls but should otherwise behave like they are not there.

Another option: override hitTest

If you want even finer control, override hitTest(_:with:) directly:

swift
1final class TransparentHitTestView: UIView {
2    override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
3        let hitView = super.hitTest(point, with: event)
4        return hitView === self ? nil : hitView
5    }
6}

This version says: if the overlay itself is the hit result, return nil so the touch passes through. If one of its interactive subviews is the hit result, keep it.

Both point(inside:with:) and hitTest(_:with:) can work. point(inside:with:) is often easier when the rule is "only interactive subviews should count". hitTest is useful when you need more customized routing.

Prefer layout changes when the overlay should not cover the button

Passing touches through works, but it is still a workaround for overlapping views. If the overlay and the button are conceptually separate controls, consider whether the layout should avoid overlap entirely. Cleaner view hierarchies are easier to maintain than clever hit-testing.

For example, if the overlay is only a label, icon, or blur effect that could be placed beside the button instead of above it, a layout adjustment is usually better than touch forwarding logic.

Common Pitfalls

The most common mistake is assuming .clear background color makes a view untouchable. It does not.

Another issue is disabling interaction on the overlay when the overlay actually contains controls. That fixes the button underneath, but it also disables the overlay's own buttons and gestures.

Developers also forget that subviews participate in hit-testing. If you implement a passthrough view, make sure interactive subviews still return true for touch handling, or nothing in the overlay will work.

Finally, do not combine too many overlapping gesture recognizers and custom hit-test overrides unless necessary. That can make touch behavior hard to reason about.

Summary

  • A transparent UIView still blocks touches unless you change hit-testing behavior.
  • If the overlay is purely visual, set isUserInteractionEnabled = false.
  • If only empty parts should pass touches through, use a passthrough view that customizes hit-testing.
  • Overriding point(inside:with:) or hitTest(_:with:) gives selective touch forwarding.
  • When possible, prefer cleaner layout over complex overlapping touch logic.

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.