Imagine a large table view that’s mostly transparent, with some elements here and there. (Perhaps there’s a large gap between cells, or, picture the cells being mainly transparent with only a couple buttons or such.
Behind this mostly-transparent table is some other materials, say with some buttons.
How to make the table that
-
if you scroll it scrolls normally
-
if you tap on a button on a cell, that works normally
-
but if you tap on one of the buttons behind the table, the click is passed through and affects that button?
(By "click" I mean what we now call a "primary action triggered" – a "click on a UIButton".)
There are a number of different well-known techniques for passing touches (as such) through views in different situations,
etc.
But I’ve never been able to get the above three mentioned conditions working.
Summary: enable clicking on a UIButton behind a UITableView.
Is there a way?
It occurs to me that passing clicks through a scroll view, to buttons behind, is an almost identical problem.
A further challenge is the background buttons should "work fully properly in all phases", ie if you eg. hold down on one but then slide off it.
2
Answers
Wow just wow.
Here's a demo of the mind-blowing @HangarRash Solution:
Here is the complete Xcode project:
Interesting further issue:
Go to the view controller. Notice I set up some storyboard cells, which use the @HangarRash Technology™
Just toggle the code to use the storyboard cells ...
(Or use code like
if indexPath.item % 3 == 0 ...
to show a few of both cells on screen at the same time.)Notice "my" cells don't quite work in all situations.
I can't for the life of me figure out what I'm doing wrong, as the HR solution is clear and I seem to be implementing the steps needed. Maybe someone can see the issue.
Incredible solution! Note in particular the HR solution even achieves the "further challenge" mentioned at the end of the question.
† zip file download link may expire in 30 days - I know nothing about the web and file sharing - feel free to repost freely or edit this post or link freely
The following code demonstrates the ability to have a table view with a transparent background that allows you to tap on controls in the table view rows, it allows the table view to be scrolled, it allows table view rows to be selected, and it allows for controls behind the table view to be tapped as long as the tap is outside of any controls in a table view row.
The demonstration makes use of modern cell configuration using a custom
UIContentConfiguration
and customUIContentView
. It also makes use of a customUITableView
subclass.Both the custom table view subclass and the custom cell content view implement custom hit testing based on the solution provided by Pass touches through a UIViewController but with some modification.
Begin by creating a new iOS app project. Setup the project to be based on Swift and Storyboard.
The following code contains lots of comments. The majority of the code below is to setup a working demonstration. The important code is the custom
hitTest
method inPassTableView
andButtonContentView
. Just about everything can be changed as needed except those two methods.Add a new Swift file named
PassTableView.swift
with the following contents:Add another Swift file named
ButtonCell.swift
with the following contents:Last, replace the contents of the provided
ViewController.swift
with the following:The code supports iOS 15+. Adjust your app’s deployment target as needed.
Build and run the app. You will see a table view with 10 rows, each containing a button. You will also see two other buttons labeled "Background ButtonX". The two extra buttons are behind the transparent table view.
All table view interactions work as expected including scrolling and cell selection. Tapping any button, including the two behind the table view, will print a message to the console.
I already state this in the code comments but it is worth repeating. It’s critical that the view passed to the
touchDelegate
used by the table view and the cells must not be in the table view’s superview hierarchy, such asself.view
. ThetouchDelegate
must be a sibling (or cousin) view. Violating this condition will lead to infinite recursion when tapping outside of a control in a cell.