Skip to main content

Capturing double-tap in FileMaker Go: Difficult but not impossible

N.B. The info in this article applies only to FileMaker 13 and 14. The problems that I complain of here may disappear, indeed, I hope they will disappear, in a future maintenance update to FileMaker 14. This info is good as of 5-20-15, but if you're reading this months later, check to see if the problems haven't since been fixed.

Written a database solution in FileMaker 13 or 14 that you are deploying on iOS devices, and want to distinguish double-taps from single-taps? For example, would you like a single tap on a record in list view simply to select the record, while a double-tap selects the record and views it in form view? Me, too.

So the way you're supposed to be able to do this is pretty straightforward (although it involves a little arithmetic). FileMaker Pro provides the basic tools in a layout script trigger OnGestureTap and a function Get(TriggerGestureInfo). In layout mode, you enable the OnGestureTap script trigger for the layout, and configure it to trigger a script. Let's call the script "respond to tap". The key line in the script should look something like this:

  Set Variable [ $gestureinfo ; Get(TriggerGestureInfo) ]
  Set Variable [ $tapcount ; GetValue ( $gestureinfo ; 2 ) ]

The function returns, in a return-delimited list, five pieces of info, of which the second — the one we're interested in — tells you how many taps were recorded. If it's 2, you branch to what you want to do when user double-taps. If it's not 2, you do nothing or something else.

Does it actually, you know, work?

Ah, but the problem is, it doesn't seem to work. When I first tried it myself, my script was triggered every single time by the first click, so the tap-count always returned 1. I asked the all-seeing, all-knowing Google for help and found that I was not alone in this experience. 

But it's not exactly a bug. It's a mistake, but not a bug. I was finally able to generate a double-tap. Not by doing what I expect my users to do, i.e. tapping twice fast with the same finger. I did it by tapping twice with two different fingers, as if I were playing 32nd notes on the piano. 

So the OnGestureTap trigger works, kind of. It simply has way too narrow an event window for normal humans. Those engineers at FileMaker must really tap fast. 

So where does that leave us?

I've written FileMaker Inc to complain that the event window for OnGestureTap is too short, and I reckon others have too. I assume that the engineers will sooner or later realize that they need to lengthen the event window that the OnGestureTap trigger responds to.

In the meantime? Well, you can create a workaround using a variables and the Get(CurrentTimeUTCMilliseconds) function. For this purpose, Get(CurrentTimeUTCMilliseconds) is basically like Get(CurrentTimestamp), just 1000 times more precise. Your script now looks something like this

  Set Variable [ $$TAPTIME[2] ; Get(CurrentTimeUTCMilliseconds ) ]
  Set Variable [ $timesincelasttap ; Case ( not IsEmpty ( $$TAPTIME[1] ) ; $$TAPTIME[2] - $$TAPTIME[1] ; "" ) ]
  Set Variable [ $$TAPTIME[1] ; $$TAPTIME[2] ]

And then you'd do something in an if statement with the value in that variable $timesincelasttap, for example, if it's less than 500 (i.e. less than half a second), you regard it as a double-tap and respond accordingly. Note that I used a single variable with two reps: rep 1 for the tap that triggered this script last time, rep 2 for the current tap. You could use two different variables  just as easily. Of course, variable for the previous tap needs to be a global variable so it sticks around for later reference. Oh, and don't use OnGestureTap with this, unless you're really trying to catch a double-tap anywhere on the layout. Instead, attach your script to a field or button that the user will be likely to tap.

Anyway, try it. It's a kludge but it works.

What record got tapped?

And I mentioned above that the OnGestureTap and Get(TriggerGestureInfo) tools are supposed to make it possible to tell when a user double-clicks on a record in a list, so you can do something like view that record in form view. But how do you do that, given that the OnGestureTap trigger is tied to the layout and not to a particular record or even to the body part? The answer is a bit depressing. And it involves arithmetic.

To make it easy, let's imagine that you've got a list layout that has no header or navigation part, nothing but a body part. So record 1 is displayed at the top of the screen. And say the body part is 100 pixels high. So the first record in the current found set the first 100 pixels at the top of the display, the second record occupies the next 100 pixels, and so on. The curious thing here is that these are virtual pixels that extend to the bottom of the list, not just to the bottom of the screen. So if you've got 500 records in the list, the last record occupies the last 100 pixels of a virtual area that is 500 x 100 pixels high. Anyway, just use GetValue ( Get ( TriggerGestureInfo ) ; 5 ) to get the y-coordinate or vertical pixel the user clicked on and do the math to figure out what record that must be. For example, if it's pixel 247, that would be record #3. Follow that up with a Go To Record [recordnumber] script step, and take it from there.

Why is this approach depressing? It's not because it involves arithmetic or because arithmetic is hard. It's because this script is going to break if you make even a minor adjustment to the size of the parts in your layout. So keep that in mind. I really wish that the OnGestureTap trigger could be attached to an element like a field or a button inside the body part, instead of being attached to the entire layout.


If you decide to use the kludge, you will quickly discover that there's one other problem, which is that this approach doesn't prevent other things from happening in response to a double tap. Specifically, a double tap is likely to zoom the display from 100% to 200% (or from whatever to whatever else). So you need to deal with that little problem. Can be done in a couple different ways and I leave it to you to figure them out.

Keep in mind that if you attach an OnGestureTap trigger to a layout, you are now trapping for and responding to (or not responding to, which is itself a kind of response) every single tap on that layout, including all the benign taps like user clicking on button. I think this stuff worked better in HyperCard, where we could decide whether to pass a click through to the layer behind the initial object or not.


Popular posts from this blog

Setting up OAUTH with Google in FileMaker 16

Setting up OAuth with Google in FileMaker 16Posted by William Porter Intended audience: Intermediate to Advanced FileMaker developers Date of publication: 2017-June-06
Updated: 2018-June-06
One of the many exciting features in FileMaker 16 (released May 2017) is OAuth or Open Authentication. Open Authentication allows users to connect to a FileMaker database after authenticating with an external (non-FileMaker) account. At the present time, FileMaker supports OAuth through Google, Amazon and Microsoft.
If you're a developer there are two main questions to answer. First, should I do this? And second, how do I do it? I'll answer the first question later. It's important.
But the other question--How do I setup OAuth?--is answered in the attached document. I wrote this tutorial with the help of my friend and colleague Taylor Sharpe of Taylor Made Services, also here in Dallas. We provide step-by-step instructions on how to get your users authenticating into your FileMaker databas…

Virtual List Basics

The conceptThe basic trick behind virtual lists is the wonderful GetValue() function. GetValue() takes two parameters: A list of return-delimited values A number specifying which value in the list to get

For example say you have a field in a single record called “List of Values” and it contains the following:

When that record is selected, GetValue ( MYTABLE::List of Values ; 4 ) will return “Doorknob”.

The brilliant idea is to replace the list of values stored in a field with a list in a global variable.

The basic implementation, part oneCreate a table called VIRTUALLIST. In it, define these two fields: VALUE NUMBER: a number field Value_calc: calc field returning text value, = “GetValue ( $$VALUES; VALUENUMBER )”. Make sure that this value is an unstored calculation.

Go to the layout for the VIRTUALLIST table and create some records. Later you can create hundreds or thousands, but right now just ten will do. Use ReplaceFieldContents to po…

Getting out of fullscreen mode in FileMaker Pro

In version 2 of Acquittal, our criminal defense case management app, we're doing some nifty stuff with windows, and that means we're finding out that even in FileMaker Pro 15, we still don't have quite all the tools we'd like for managing windows.  One problem is how to trap for the possibility that the user has switched into fullscreen mode. The other problem is how to get out of it.

Is this window in fullscreen mode?
This one's not too hard. This calc formula seems to do the trick:

Get ( WindowHeight ) = Get ( ScreenHeight ) and
Get ( WindowWidth ) = Get ( ScreenWidth)

That will return true if the window is in fullscreen mode, false if it's not.

Why does this matter? Because there are certain things that you can't do with a window if it's in fullscreen mode. In Acquittal, for example, there are times when we want to generate a second "sidecar" window, then display the main and sidecar windows side-by-side. Can't do it if the main window …