Flutter: How To Use RawKeyboardListener Widget

syazwan nasir
4 min readAug 28, 2020

--

I make this article for me if I forgot how to use this Widget. For more detail check out the documentation from a flutter.

A RawKeyboardListener is useful for listening to raw key events and hardware buttons that are represented as keys. Typically used by games and other apps that use keyboards for purposes other than text entry.

When I create a website using flutter, it not scroll down when I press key arrow down or arrow up.

So my goal is when I press arrow down, it will scroll down a little bit and when I press up, it scrolls up.

So the website example already finishes and waiting to implement RawKeyboardListener.

Example Picture

Example website have scrolling

Example Code

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

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

class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
home: MyHomePage(),
);
}
}

class MyHomePage extends StatelessWidget {
final ScrollController _controller = ScrollController();

@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
child: Scrollbar(
controller: _controller,
isAlwaysShown: true,
child: ListView.builder(
controller: _controller,
itemCount: 10,
itemBuilder: (context, index) {
return Container(
height: MediaQuery.of(context).size.height,
width: double.infinity,
color: Colors.accents[Random().nextInt(Colors.accents.length)],
child: Center(
child: Text(
'${index + 1}',
style: TextStyle(fontSize: 200),
),
),
);
},
),
),
),
);
}
}

So firstly put RawKeyboardListener at top Container and under Scaffold(body: )

return Scaffold(
body: RawKeyboardListener(
focusNode: FocusNode(),
onKey: (RawKeyEvent event) {},
autofocus: true,
child: Container(
child: Scrollbar(
controller: _controller,
isAlwaysShown: true,
child: ListView.builder(
controller: _controller,
itemCount: 10,
itemBuilder: (context, index) {
return Container(
height: MediaQuery.of(context).size.height,
width: double.infinity,
color:
Colors.accents[Random().nextInt(Colors.accents.length)],
child: Center(
child: Text(
'${index + 1}',
style: TextStyle(fontSize: 200),
),
),
);
},
),
),
),
),
);

So you see 3 properties in there:

RawKeyboardListener(
focusNode: FocusNode(),
onKey: (RawKeyEvent event) {},
autofocus: true,
child: ...
)
  1. focusNode for Controls whether this widget has keyboard focus.
  2. autofocus will be selected as the initial focus when no other node in its scope is currently focused.
  3. onKey this is where the function Key event happen when we press Key

I focus onKey where can check what key you press and do some function when pressing Key

onKey: (RawKeyEvent event) {
print('Hello');
},

If you press any Key in your website, it will print hello twice, we don't want that and want print only once per press key, we use this code.

onKey: (RawKeyEvent event) {
if (event.runtimeType.toString() == 'RawKeyDownEvent') {
print('Hello')
}
},

It will representation of the runtime type of the object and print only once per press key.

So now we want to check what key you press, you can use this code:

print(event.logicalKey.keyLabel);

Ok now you can put a condition on it if you press this key, it will trigger the function. Like this

if(event.isKeyPressed(LogicalKeyboardKey.arrowDown)){}

So you put Keyboard key logic inside the parenthesis to check if you press keyboard same as the Keyboard key logic

event.isKeyPressed(//inside your keyboard key logic)

You can use LogicalKeyboardKey to check the condition but need to import this first.

import ‘package:flutter/services.dart’;

For more information, you can check this:

ok now we already know how to check condition if you press key same as the logic key. So we can try to finish it.

if (event.runtimeType.toString() == 'RawKeyDownEvent') {  if (event.isKeyPressed(LogicalKeyboardKey.arrowDown)) {
_controller.animateTo(_controller.offset + 100,
curve: Curves.linear, duration: Duration(milliseconds: 50));
}
if (event.isKeyPressed(LogicalKeyboardKey.arrowUp)) {
_controller.animateTo(_controller.offset - 100,
curve: Curves.linear, duration: Duration(milliseconds: 50));
}
}

so when you press arrow down _controller.offset will plus 100 and that makes scroll go down.

and when you press arrow up _controller.offset will minus 100, that makes scroll go up.

Final Code:

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

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

class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
home: MyHomePage(),
);
}
}

class MyHomePage extends StatelessWidget {
void onEventKey(RawKeyEvent event) async {
if (event.runtimeType.toString() == 'RawKeyDownEvent') {
if (event.isKeyPressed(LogicalKeyboardKey.arrowDown)) {
_controller.animateTo(_controller.offset + 100,
curve: Curves.linear, duration: Duration(milliseconds: 50));
}
if (event.isKeyPressed(LogicalKeyboardKey.arrowUp)) {
_controller.animateTo(_controller.offset - 100,
curve: Curves.linear, duration: Duration(milliseconds: 50));
}
}
}

final ScrollController _controller = ScrollController();

@override
Widget build(BuildContext context) {
return Scaffold(
body: RawKeyboardListener(
focusNode: FocusNode(),
onKey: onEventKey,
autofocus: true,
child: Container(
child: Scrollbar(
controller: _controller,
isAlwaysShown: true,
child: ListView.builder(
controller: _controller,
itemCount: 10,
itemBuilder: (context, index) {
return Container(
height: MediaQuery.of(context).size.height,
width: double.infinity,
color:
Colors.accents[Random().nextInt(Colors.accents.length)],
child: Center(
child: Text(
'${index + 1}',
style: TextStyle(fontSize: 200),
),
),
);
},
),
),
),
),
);
}
}

--

--