Skip to content

GestureDetector

A widget that detects gestures.

Tap & Double Tap

Tap / Double Tap / Long PressReady
vue
<template>
  <GestureDetector
    @tap="handleTap"
    @double-tap="handleDoubleTap"
    @long-press="handleLongPress"
    behavior="opaque"
  >
    <Container
      :width="200"
      :height="100"
      alignment="center"
      :decoration="BoxDecoration({ borderRadius: BorderRadius.all(8), color: boxColor })"
    >
      <Column mainAxisAlignment="center">
        <Text data="Tap / Double Tap / Long Press" />
        <Text :data="statusText" :style="TextStyle({ fontSize: 12 })" />
      </Column>
    </Container>
  </GestureDetector>
</template>

<script setup lang="ts">
import { ref } from "vue";
import {
  GestureDetector,
  Container,
  Column,
  Text,
  BoxDecoration,
  BorderRadius,
  TextStyle,
} from "fluekit";

const boxColor = ref("teal");
const statusText = ref("Ready");

const handleTap = () => {
  console.log("tap");
  boxColor.value = "green";
  statusText.value = "Tapped!";
  setTimeout(() => (boxColor.value = "teal"), 200);
};

const handleDoubleTap = () => {
  boxColor.value = "purple";
  statusText.value = "Double Tapped!";
  setTimeout(() => (boxColor.value = "teal"), 500);
};

const handleLongPress = () => {
  boxColor.value = "red";
  statusText.value = "Long Pressed!";
  setTimeout(() => (boxColor.value = "teal"), 500);
};
</script>

Pan (Drag)

Drag
vue
<template>
  <Container :height="300" :width="300" color="#f9f9f9" clipBehavior="hardEdge">
    <Stack fit="expand">
      <Positioned :left="panPos.x" :top="panPos.y">
        <GestureDetector
          @pan-start="handlePanStart"
          @pan-update="handlePanUpdate"
          @pan-end="handlePanEnd"
          behavior="opaque"
        >
          <Container
            :width="80"
            :height="80"
            alignment="center"
            :decoration="
              BoxDecoration({
                color: isPanning ? 'orange' : 'blue',
                borderRadius: BorderRadius.all(40),
                boxShadow: isPanning
                  ? [
                      BoxShadow({
                        color: 'rgba(0,0,0,0.2)',
                        blurRadius: 10,
                        spreadRadius: 2,
                      }),
                    ]
                  : [],
              })
            "
          >
            <Text data="Drag" />
          </Container>
        </GestureDetector>
      </Positioned>
    </Stack>
  </Container>
</template>

<script setup lang="ts">
import {
  Container,
  GestureDetector,
  Positioned,
  Stack,
  Text,
  BoxDecoration,
  BorderRadius,
  BoxShadow,
} from "fluekit";
import { ref } from "vue";

const panPos = ref({ x: 20, y: 50 });
const isPanning = ref(false);

const handlePanStart = () => {
  isPanning.value = true;
};

const handlePanUpdate = (detail: any) => {
  // detail.delta 是增量
  panPos.value.x += detail.delta.x;
  panPos.value.y += detail.delta.y;
};

const handlePanEnd = () => {
  isPanning.value = false;
};
</script>

Hit Test Behavior

Control how the gesture detector behaves during hit testing.

Opaque
DeferToChild
Click boxes above
vue
<template>
  <Row :gap="20">
    <GestureDetector @tap="() => logBehavior('Opaque')" behavior="opaque">
      <Container :width="100" :height="100" color="rgba(0,0,0,0.1)">
        <Center><Text data="Opaque" /></Center>
      </Container>
    </GestureDetector>
    <GestureDetector @tap="() => logBehavior('deferToChild')" behavior="deferToChild">
      <Container :width="100" :height="100" color="rgba(0,0,0,0.1)">
        <Center><Text data="DeferToChild" /></Center>
      </Container>
    </GestureDetector>
  </Row>
  <Text :data="behaviorLog" :style="TextStyle({ color: 'grey', fontSize: 12 })" />
</template>

<script setup lang="ts">
import { ref } from "vue";
import { Row, GestureDetector, Container, Center, Text, TextStyle } from "fluekit";

const behaviorLog = ref("Click boxes above");
const logBehavior = (type: string) => {
  behaviorLog.value = `Last clicked: ${type} at ${new Date().toLocaleTimeString()}`;
};
</script>

Text Node Support

Detect gestures on plain text nodes.

Click this plain text!
vue
<template>
  <GestureDetector @tap="() => logBehavior('Text Node Tapped')">
    Click this plain text!
  </GestureDetector>
</template>

<script setup lang="ts">
import { GestureDetector } from "fluekit";

const logBehavior = (type: string) => {
  console.log(type);
  alert(type);
};
</script>

API

GestureDetector

Props

NameTypeDefaultDescription
behavior'deferToChild' | 'opaque' | 'translucent''deferToChild'How this gesture detector should behave during hit testing.

Events

NameDescription
clickTriggered when the widget is clicked.
tapTriggered when the widget is tapped.
double-tapTriggered when the widget is double tapped.
long-pressTriggered when the widget is long pressed.
pan-startTriggered when a pan gesture starts.
pan-updateTriggered when a pan gesture updates.
pan-endTriggered when a pan gesture ends.

Slots

NameDescription
defaultThe widget below this widget in the tree.