math_keyboard 0.1.1 math_keyboard: ^0.1.1 copied to clipboard
Math expression editing using an on-screen software keyboard or physical keyboard input in a typeset input field in Flutter.
#
math_keyboard
is a Flutter package that allows editing math expressions using a typeset input
field (so-called "math field") and a custom-made fully integrated math keyboard in Flutter only -
no plugins, no web views.
Features #
- Editing math expressions using a custom on-screen software keyboard
- Editing via physical keyboard input (with shortcuts for functions and constants)
- Support for both number and expression mode
- Advanced operators and trigonometric functions (e.g.
sqrt
,ln
,sin
, etc.) - View insets support (on-screen keyboard overlay pushes up e.g. the
body
inScaffold
) - Full focus tree integration: works with regular text fields, manual
FocusNode
s, tabbing, etc. - Autofocus support
- Form field support
- Decimal separator based on locale
- Converting TeX from and to math expressions
You can view all features in action in the demo app.
Usage #
To use this plugin, follow the installing guide.
Implementation #
The most basic way of integrating the math keyboard is by just adding a MathField
somewhere in your app. This works exactly like Flutter TextField
s do - even with the same
InputDecoration
decoration functionality!
@override
Widget build(BuildContext context) {
return MathField(
// No parameters are required.
keyboardType: MathKeyboardType.expression, // Specify the keyboard type (expression or number only).
variables: const ['x', 'y', 'z'], // Specify the variables the user can use (only in expression mode).
decoration: const InputDecoration(), // Decorate the input field using the familiar InputDecoration.
onChanged: (String value) {}, // Respond to changes in the input field.
onSubmitted: (String value) {}, // Respond to the user submitting their input.
autofocus: true, // Enable or disable autofocus of the input field.
);
}
Now, tapping inside of the math field (or focusing it via the focus tree) will automatically open up the math keyboard and start accepting physical keyboard input on desktop.
Note that physical keyboard input on mobile causes weird behavior due to a Flutter issue.
View insets #
A very useful feature of the math keyboard is the fact that it tries to mirror the regular software
keyboard as closely as possible. Part of that is reporting its size to the MediaQuery
in the
form of view insets. This will seamlessly integrate with widgets like Scaffold
and the existing
view insets reporting of software keyboards.
All you have to do to use this feature is making sure that your Scaffold
(that your MathField
s
live in) are wrapped in MathKeyboardViewInsets
:
@override
Widget build(BuildContext context) {
return MathKeyboardViewInsets(
child: Scaffold(
// ...
),
);
}
Please see the documentation for more advanced use cases - this part of the docs is quite detailed :)
Furthermore, the package provides some convenience functions for detecting whether a keyboard is showing:
MathKeyboardViewInsetsQuery.mathKeyboardShowingIn(context)
, which reports whether there is a math keyboard open in the currentcontext
.MathKeyboardViewInsetsQuery.keyboardShowingIn(context)
, which reports whether there is any keyboard open in the currentcontext
. Note that this function actually also provides advanced functionality for regular software keyboards :)
Form support #
In order to use a MathField
in a Flutter Form
, you can simply use a
MathFormField
in place of a regular MathField
. This mirrors the regular field
with extended functionality and behaves exactly like TextFormField
from the
framework. See the latter for advanced documentation.
@override
Widget build(BuildContext context) {
return MathFormField(
// ...
);
}
Custom controller #
You can always specify a custom MathFieldEditingController
. This
allows you to clear all input for example. Make sure to dispose the controller.
class FooState extends State<FooStatefulWidget> {
late final _controller = MathFieldEditingController();
@override
void dispose() {
_controller.dispose();
super.dispose();
}
void _onTapClear() {
_controller.clear();
}
@override
Widget build(BuildContext context) {
return MathField(
controller: _controller,
decoration: InputDecoration(
suffix: MouseRegion(
cursor: MaterialStateMouseCursor.clickable,
child: GestureDetector(
onTap: _onTapClear,
child: const Icon(
Icons.highlight_remove_rounded,
color: Colors.grey,
),
),
),
),
);
}
}
Custom focus node #
You can always specify your own FocusNode
if you wish to manage focus yourself. This
works like any other focus-based widget (like TextField
). Note that autofocus
still works when
supplying a custom focus node.
class FooState extends State<FooStatefulWidget> {
late final _focusNode = FocusNode(debugLabel: 'Foo');
@override
void dispose() {
_focusNode.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return MathField(
focusNode: _focusNode,
);
}
}
Decimal separators #
Note that not all countries use a dot .
as decimal separator (see reference).
If the locale obtained via Localizations.localeOf
uses a comma ,
as decimal
separator, both the separator in the math field as well as the symbol on the keyboard are adjusted.
Otherwise, a dot .
is used. You can override the locale using the
Localizations.override
widget (wrap your MathField
s with it).
Note that physical keyboard input always accepts both .
and ,
.
Math expressions #
To convert the TeX strings returned by the math keyboard into math expressions, you can make use
of the provided TeXParser
:
final mathExpression = TeXParser(texString).parse();
For the opposite operation, i.e. converting a math Expression
to TeX, you can make use
of the provided convertMathExpressionToTeXNode
:
final texNode = convertMathExpressionToTeXNode(expression);
Note that this returns an internal TeXNode
format, which you can convert to a TeX string:
final texString = texNode.buildTexString();