Home > front end >  How to recognize diagonal swipes in flutter?
How to recognize diagonal swipes in flutter?

Time:06-30

I attempted to detect diagonal swipe direction using GestureDetector. I used the onPanStart method to detect the screen's corners. However, it is not perfect because it only considers the beginning of the gesture.

Right now, if I swipe bottom left to top right in the top right corner or part, it gives me the incorrect top right direction. In this case, the correct direction should be bottom left.

So, how can we identify diagonal swipe direction using GestureDetector or any other method?

I looked at several other StackOverflow posts, but they only detect top, left, right, and bottom directions.

Here is an example of code.

class _HomePageState extends State<HomePage> {
  @override
  Widget build(BuildContext context) {
    final screenSize = MediaQuery.of(context).size;
    String? swipeDirection;

    return Scaffold(
        body: SafeArea(
      child: Scaffold(
        backgroundColor: Colors.black,
        body: GestureDetector(
          child: Container(),
          onPanStart: (details) {
            final halfScreenWidth = screenSize.width / 2;
            final halfScreenHeight = screenSize.height / 2;
            final position = details.localPosition;

            if ((position.dx < halfScreenWidth) &&
                (position.dy < halfScreenHeight)) {
              swipeDirection = 'topLeft';
            } else if ((position.dx > halfScreenWidth) &&
                (position.dy < halfScreenHeight)) {
              swipeDirection = 'topRight';
            } else if ((position.dx < halfScreenWidth) &&
                (position.dy > halfScreenHeight)) {
              swipeDirection = 'bottomLeft';
            } else {
              swipeDirection = 'bottomRight';
            }
          },
        ),
      ),
    ));
  }
}

CodePudding user response:

You can use pan update to find the position of the pointer the same manner you did for pan start and get the starting and ending points. Then on pan end execute with the final results

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: MyHome(),
    );
  }
}

class MyHome extends StatefulWidget {
  const MyHome({Key? key}) : super(key: key);

  @override
  State<MyHome> createState() => _MyHomeState();
}

class _MyHomeState extends State<MyHome> {
  String? swipeStart;
  String? swipeEnd;
  @override
  void initState() {
    // TODO: implement initState
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    final screenSize = MediaQuery.of(context).size;
    return SafeArea(
      child: Scaffold(
        backgroundColor: Colors.black,
        body: GestureDetector(
          child: Container(
            width: MediaQuery.of(context).size.width,
            height: MediaQuery.of(context).size.height,
            color: Colors.grey,
          ),
          onPanStart: (details) {
            final halfScreenWidth = screenSize.width / 2;
            final halfScreenHeight = screenSize.height / 2;
            final position = details.localPosition;

            if ((position.dx < halfScreenWidth) &&
                (position.dy < halfScreenHeight)) {
              swipeStart = 'topLeft';
            } else if ((position.dx > halfScreenWidth) &&
                (position.dy < halfScreenHeight)) {
              swipeStart = 'topRight';
            } else if ((position.dx < halfScreenWidth) &&
                (position.dy > halfScreenHeight)) {
              swipeStart = 'bottomLeft';
            } else {
              swipeStart = 'bottomRight';
            }
            // print(swipeStart);
          },
          onPanUpdate: (details) {
            final halfScreenWidth = screenSize.width / 2;
            final halfScreenHeight = screenSize.height / 2;
            final position = details.localPosition;

            if ((position.dx < halfScreenWidth) &&
                (position.dy < halfScreenHeight)) {
              swipeEnd = 'topLeft';
            } else if ((position.dx > halfScreenWidth) &&
                (position.dy < halfScreenHeight)) {
              swipeEnd = 'topRight';
            } else if ((position.dx < halfScreenWidth) &&
                (position.dy > halfScreenHeight)) {
              swipeEnd = 'bottomLeft';
            } else {
              swipeEnd = 'bottomRight';
            }
            //print(swipeEnd);
          },
          onPanEnd: (details) {
            print("Final direction was from $swipeStart to $swipeEnd");
          },
        ),
      ),
    );
  }
}

I have printed output like this

flutter: Final direction was from topLeft to bottomRight
flutter: Final direction was from bottomLeft to topRight

EDIT

You can find the offset when the pan starts and updates. Then on pan end calculate the direction like this

import 'dart:math';

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: MyHome(),
    );
  }
}

class MyHome extends StatefulWidget {
  const MyHome({Key? key}) : super(key: key);

  @override
  State<MyHome> createState() => _MyHomeState();
}

class _MyHomeState extends State<MyHome> {
  String? horizontalDirection;
  String? verticalDirection;
  late Offset startPoint;
  late Offset endPoint;
  @override
  void initState() {
    // TODO: implement initState
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return SafeArea(
      child: Scaffold(
        backgroundColor: Colors.black,
        body: GestureDetector(
          child: Container(
            width: MediaQuery.of(context).size.width,
            height: MediaQuery.of(context).size.height,
            color: Colors.grey,
          ),
          onPanStart: (details) {
            startPoint = details.localPosition;
          },
          onPanUpdate: (details) {
            endPoint = details.localPosition;
          },
          onPanEnd: (details) {
            if (startPoint.dx < endPoint.dx) {
              horizontalDirection = "right";
            } else {
              horizontalDirection = "left";
            }

            if (startPoint.dy < endPoint.dy) {
              verticalDirection = "bottom";
            } else {
              verticalDirection = "top";
            }
            print("Final direction was $horizontalDirection$verticalDirection");
          },
        ),
      ),
    );
  }
}

CodePudding user response:

Looking into the GestureDetector widget there isn't any kind of feature your'e searching for. Also there is no other widget in my mind which is able to do that.

Maybe you can try to add the following: Save the position of the onPanStart of one of the directions. Add onPanEnd and do the exact same you did for onPanStart and also save these positions. Now add onPanUpdate and with this you will compare the first and last point which was recognized. If you are working with screensizes as I can see, you can divide your screen in 4 blocks (top, left, right, bottom) and with the informations of the first and last position you can detect the diagonal swipe

  • Related