Forum Archive

long touches and swipes

polymerchm

Can the gurus enlighten as how to do? I presume timers and touch.ids are involved but if you have a snippet or two to lead the way, would be much appreciated.

JonB

I have a few examples in uicomponents.

PopupButton
implements a long touch action.

There are probably lots of different types of behavior, this was trying to emulate the pythonista keyboard, where a long touch brings up another key row.

In the simplest form, touch_began starts a timer (you can just use ui.delay). The function that gets called sets a flag indicating long touch is active. That function could also do some other action -- like popping up a menu in this case.

touch_ended calls ui.cancel_delays() (to cancel any pending long touches in the case of a "short touch") and might take a different action depending on whether a long touch was active or not.

touch_moved could cancel the delay (if you only want a stationary long touch to activate). What made sense for this case was that small moves were still allowed to trigger a long touch, as long as the touch was still on the component when the timer went off (hence the touched flag, which also causes the draw method to highlight or unhighlight the component)

For simple swipe actions, you could simply look at the touch.prev_location and compare to touch.location in order to figure out the swipe direction, inside touch_moved. However if you want to do any sort of filtering on the total amount the finger has moved, you need to keep track of touches on your own (by touch_id if multitouch is enabled)

ZoomView shows an example of a multi-touch enabled view. Click the new window button; two-finger drag on the border move the window, pinching causes the window to zoom (i.e. touch two points on border and drag apart)

Note that most fancy touch events are completely broken in present('panel') mode, since you only get one touch_moved event, at which point things try to scroll back to the editor. ScrollView and WebView don't have this limitation, and so some tricky things can be done with ScrollView to simulate swipe events. For an example,

In stash, we implemented a scrollview which when swiping moves the cursor. Basically, scrollview_did_scroll grabs scrollview.content_offset, (keeping a running sum, perhaps), then resets content_offset back to (0,0,0,0), so that the scroll never actually gets rendered.

polymerchm

get this when I "long touch" one of the buttons:

Traceback (most recent call last):
  File "/var/mobile/Containers/Data/Application/3469D264-D1AC-451E-9E4A-B3E38AD33B7F/Documents/uicomponents/PopupButton.py", line 177, in touch_moved
    self.longtouchcleanuptimer.cancel()
AttributeError: 'PopupButton' object has no attribute 'longtouchcleanuptimer'

Running 1.6

Changing from 'panel' to 'sheet' presentation locks things up and requires a restart.

JonB

Whoops, I had a try/catch not checked in. Update has been pushed.