Home > Blockchain >  How can I check the screen click status?
How can I check the screen click status?

Time:08-13

If nothing is done on the screen, I want to print something on the screen some time after the last action. How can I do that? How can I check the screen click status?

CodePudding user response:

A naive approach could involve a Timer with dart:async.


import 'dart:async';

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: _SomeWidget(),
    );
  }
}

class _SomeWidget extends StatefulWidget {
  const _SomeWidget();

  @override
  State<_SomeWidget> createState() => _SomeWidgetState();
}

class _SomeWidgetState extends State<_SomeWidget> {
  late Timer _timer;

  @override
  void initState() {
    super.initState();
    // It's up to you if you want the timer to start immediately with some effects or not.
    _timer = Timer(const Duration(seconds: 1), () {});
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: GestureDetector(
        onTap: () {
          // i.e. from the first interaction and so on
          _timer.cancel();
          _timer = Timer(const Duration(seconds: 1), () {
            if (mounted) {
              // !
              ScaffoldMessenger.of(context).showSnackBar(
                const SnackBar(content: Text('Some message')),
              );
            }
          });
        },
        child: const Center(child: Text('My screen contents')),
      ),
    );
  }
}

The mounted check is very important, as Timer introduces an async gap, which may be dangerous when using context.

CodePudding user response:

You can add a Gesture detector at the top level and start a timer on tap and on completion you can fire an event like the following

GestureDetector(
 onTap: (){
   startTimer();
 }
 child: Column(
   children:[
    //all other widgets
   ]
 )
),

Then to define the timer

late Timer _timer; 
void startTimer()
{
 if(_timer != null && _timer.isActive) _timer.cancel();

_timer = Timer(
  const Duration(seconds: 30),
  () {
    print("inactive for 30 seconds");
  },
);
}

here in this case each time the user taps on the screen the timer is restarted and on 30th second the print is fired.

CodePudding user response:

You can wrap Scaffold with GestureDetector and use onPanDown to capture the screen event, onTap doesn't win on hit test if there are inner clickable buttons. Also use behavior: HitTestBehavior.translucent,

Another notable thing is here, it is needed to be check on every second, because the checkup unit is on second. You can create a wrapper widget from it.

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

  @override
  State<ScreenT> createState() => _ScreenTState();
}

class _ScreenTState extends State<ScreenT> {
  @override
  void dispose() {
    timer?.cancel();
    super.dispose();
  }

  Timer? timer;
  int maxDelaySec = 10;
  int idleScreenCounter = 0;

  @override
  void initState() {
    super.initState();
    initTimer();
  }

  initTimer() {
    timer = Timer.periodic(Duration(seconds: 1), (timer) {
      idleScreenCounter  ;
      setState(() {}); //
    });
  }

  onScreenTap() {
    print("tapped on Screen");
    idleScreenCounter = 0;
    setState(() {});
  }

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      behavior: HitTestBehavior.translucent,
      onPanDown: (_) => onScreenTap(),
      child: Scaffold(
        body: LayoutBuilder(
          builder: (context, constraints) => SizedBox(
            width: constraints.maxWidth,
            height: constraints.maxHeight,
            child: Center(
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  if (maxDelaySec - idleScreenCounter > 0)
                    SizedBox(
                      height: 200,
                      child: Text(
                          " Tap the screen within ${maxDelaySec - idleScreenCounter}"),
                    ),
                  if (maxDelaySec - idleScreenCounter < 0)
                    Container(
                      height: 100,
                      width: 100,
                      color: Colors.cyanAccent,
                      child: Text("Tap on screen"),
                    ),
                  GestureDetector(
                    behavior: HitTestBehavior.translucent,
                    onTap: () {
                      print("An action");
                    },
                    child: Text("A Button"),
                  ),
                  ElevatedButton(
                    onPressed: () {
                      print("act");
                    },
                    child: Text("Elev"),
                  )
                ],
              ),
            ),
          ),
        ),
      ),
    );
  }
}
  • Related