I've implemented an emoji "quick reaction" feature for our messaging feature within our app (using Swift). The reaction UI/UX is supposed to match that of the quick emoji reaction via long press gesture in iMessage almost exactly, aside from which reactions we chose to display.
We've implemented this feature using the func tableView(_ tableView: UITableView, previewForHighlightingContextMenuWithConfiguration ...)
. Within this delegate function we create a container view that has a snapshot of the message TableViewCell with the reaction UIView inserted right above the snapshot, like it does visually in iMessage.
This container is passed in to the UITargetedPreview(view: /*here*/, parameters: parameters, target: previewTarget)
constructor and is then returned for the aforementioned delegate function.
This works functionally, but here are some issues with this UI/UX wise that is different than iMessage, which I will describe:
-
When the user "long presses" to trigger the ContextMenu, it reacts to the press very quickly, i.e duration of fingertip "pressing" is short as ~0.25 seconds, where as a traditional UIGestureRecognizer takes longer than ~1.0 seconds. We'd like to make the required duration of physical "pressing" to be more around 0.5 - 1.0 seconds like in iMessage.
-
When the user initiates the ContextMenu within iMessage, the reactions view and the ContextMenu appear at the same exact time. In our implementation, presuming because the cell snapshot and reaction view are within the same container, they both appear prior to the context menu. The reason why this happens makes sense to me, however I would like to know how iMessage implements the Context Menu functionality in iMessage, such that the reaction view appears with the Context Menu. The user seeing only the message first, then both menu elements.
Note: We use the UITargetedPreview
so that we can specify a .clear
background color for the targetView, as the same UI/UX as in iMessage. We did not find another way to implement that design.
In conclusion, in what way does iMessage present Context Menu's such that the the following feature requirements are fullfilled: Background is clear between the reaction view, the message, and the context menu. The duration of gesture press that is required to trigger the menu being more than ~0.5 seconds. As well as the message cell appearing first, and then subsequently the reaction view + context menu together?
I was able to solve the second problem listed (#2.) by used the UITableViewDelegate method func tableView(_ tableView: UITableView, willDisplayContextMenu configuration: UIContextMenuConfiguration, animator: UIContextMenuInteractionAnimating?)
. I did this by setting the reaction's view isHidden
property to true
during setup and then subsequently adding an animation to the animator of the delegate function willDisplayContextMenu
to set isHidden
back to false
. This makes it so the reaction view appears at the same time as the ContextMenu!
As for the duration of the long press, I have decided that was ancillary and of low priority which. with this above solution, is not as much of importance. Hope this helps some devs out there.