DialogsThe Android mini-app frameworkDrawingTaps, double-taps, and flings

Taps, double-taps, and flings

The mini-app framework distinguishes three kinds of gestures on the phone screen:

The frame-work currently does not support other gestures commonly used on smartphones, such as press (holding the finger on one position, often used to get a menu), or scroll (where you move the contents on the screen with your fingers).

Here is a small demo program where you can see the different gestures in action: (taps.kt):

//
// Tap, Double-tap, and Fling
//

import org.otfried.cs109.Context
import org.otfried.cs109.MiniApp

import org.otfried.cs109.Canvas
import org.otfried.cs109.Color
import org.otfried.cs109.DrawStyle
import org.otfried.cs109.TextAlign

class Main(val ctx: Context) : MiniApp {
  private var lastX = 0.0
  private var lastY = 0.0
  private var lastT = 0
  private var flingDir = 0.0

  init {
    ctx.setTitle("Tap and fling demo")
    ctx.onTap { x, y -> tapped(x, y, 1) }
    ctx.onDoubleTap { x, y -> tapped(x, y, 2) }
    ctx.onFling { x, y, dir, d -> flinged(dir) }
  }

  fun tapped(x: Double, y: Double, t: Int) {
    lastX = x
    lastY = y
    lastT = t
    ctx.update()
  }

  fun flinged(dir: Char) {
    when(dir) {
    'l' -> flingDir = 270.0
    'd' -> flingDir = 180.0
    'r' -> flingDir = 90.0
    else -> flingDir = 0.0
    }
    lastT = 4
    ctx.update()
  }
  

  override fun onDraw(canvas: Canvas) {
    canvas.clear(Color(255, 255, 192))
    if (lastT == 0)
      return
    canvas.setColor(Color.BLUE)
    canvas.setFont(32.0)
    canvas.drawText(when(lastT) {
      1 -> "tap"
      2 -> "double tap"
      3 -> "press"
      4 -> "fling"
      else -> ""
      }, canvas.width / 2.0, 60.0 + 20.0 * lastT, TextAlign.CENTER)
    if (lastT != 4)
      canvas.drawCircle(lastX, lastY, 30.0)
    else {
      canvas.translate(canvas.width / 2.0, canvas.height / 2.0)
      canvas.rotate(flingDir)
      canvas.beginShape()
      canvas.moveTo(-30.0, 0.0)
      canvas.lineTo(0.0, -40.0)
      canvas.lineTo(30.0, 0.0)
      canvas.lineTo(0.0, -100.0)
      canvas.closePath()
      canvas.drawShape()
    }
  }
}

As you can see, for each type of gesture you register a separate tap handler. The tap and double-tap handlers simply receive the coordinates of the tap. The fling handler receives four arguments: \(x\) and \(y\) are the start coordinate of the gesture, dir is a Char indicating the direction of the fling, namely one of u, d, l, or r (for up, down, left, right), and dist is the distance the finger moved on the screen. Note that the framework will only call the handler for fling gestures that are roughly horizontal or vertical—when you move your finger diagonally over the screen, no fling gesture is generated.

Each tap handler calls the update method of the context: This is what causes the onDraw method to be called again, so that the contents of the screen actually changes. Try removing the ctx.update() line—you'll see that while the tap handler is still called, the screen will never show the dots.

The emulator currently does not have a gesture recognizer: Instead of a double-click, you should click with the right mouse button. And instead of a fling gesture, press one of the four keys u, d, l, or r.

DialogsThe Android mini-app frameworkDrawingTaps, double-taps, and flings