Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flutter: How can I prevent default behaviour on key press?

I'm trying to intercept when a user presses the volume buttons to perform a specific action and prevent the default behaviour (volume changes).

This is the code I have so far:

RawKeyboard.instance.addListener(_keyboardListener);

void _keyboardListener(RawKeyEvent e) {
  if(e.runtimeType == RawKeyUpEvent) {
    RawKeyEventDataAndroid eA = e.data;
    if(eA.keyCode == 24) { //volume up key
      _goNextPage();
    }
    if(eA.keyCode == 25) { //volume down key
      _goPrevPage();
    }
  }
}

How would I go about preventing the volume from changing (and stopping the volume slider from appearing at the top)?

A Javascript analogous would be calling event.preventDefault() on the key event.

This seems to be a rather trivial matter, but I haven't been able to find any answers in the docs.

Thanks.

like image 994
joseph Avatar asked Nov 26 '18 00:11

joseph


2 Answers

I've faced a similar problem and what to share how I solved it.

To stop the propagation we have to return true from onKey method of a FocusNode in the focus nodes tree. To achieve this I've wrapped my app body with FocusScope and Focus widgets like this:

MaterialApp(
      home: Scaffold(
          body: FocusScope(
              autofocus: true,
              child: Focus(
                  autofocus: true,
                  canRequestFocus: true,
                  onKey: (data, event) {
                    if (event.isKeyPressed(LogicalKeyboardKey.audioVolumeUp)) {
                      print("Volume up");
                      return true;
                    }
                    if (event
                        .isKeyPressed(LogicalKeyboardKey.audioVolumeDown)) {
                      print("Volume down");
                      return true;
                    }
                    return false;
                  },
                  child: Text(text: "Hallochen")))))
like image 139
Sergey Yamshchikov Avatar answered Nov 17 '22 21:11

Sergey Yamshchikov


Thanks to Sergey's answer I was able to solve the issue as well. In my case, I wanted to create a ListView, with pull to refresh (RefreshIndicator) that will work for both mobile devices and web.

I tried to implement a refresh indicator which will appear when the user clicks F5 to refresh the web page, but I had to prevent the browser from actually refreshing the page.

Here's an example of my implementation, which prevents refresh from occuring when the user clicks F5.

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';


class ExamplePage extends StatefulWidget {
  @override
  _ExamplePageState createState() => _ExamplePageState();
}

class _ExamplePageState extends State<ExamplePage> {
  final GlobalKey<AnimatedListState> listKey = GlobalKey<AnimatedListState>();
  final GlobalKey<RefreshIndicatorState> _refreshIndicatorKey = new GlobalKey<RefreshIndicatorState>();
  
  List items = [];

  Future<void> _pullRefresh() async {
    await Future.delayed(Duration(milliseconds: 1000));
  }
  
  @override
  Widget build(BuildContext context) {
    return FocusScope(
      autofocus: true,
      child: Focus(
        autofocus: true,
        canRequestFocus: true,
        onKey: (data, event) {
          if (event
              .isKeyPressed(LogicalKeyboardKey.f5)) {
            _refreshIndicatorKey.currentState!.show();
            return KeyEventResult.handled;
          }
          return KeyEventResult.ignored;
        },
        child: Container(
            padding: EdgeInsets.all(15.0),
            child: RefreshIndicator(
              key: _refreshIndicatorKey,
              onRefresh: _pullRefresh,
              child: AnimatedList(
                key: listKey,
                initialItemCount: items.length,
                itemBuilder: (context, index, animation) {
                  return _buildItem(context, index, animation);
                },
              ),
            ),
        ),
      ),
    );
  }
  
    Widget _buildItem(
      BuildContext context, int index, Animation<double> animation) {
    return Text("Example");
    }
}
like image 1
morha13 Avatar answered Nov 17 '22 22:11

morha13