diff --git a/README.md b/README.md
index 60ec0fa..2cf62db 100644
--- a/README.md
+++ b/README.md
@@ -22,7 +22,7 @@ This causes a lot of inconvenience for users, so this package allows adding func
- You can use it for Android, iOS or both platforms.
- Compatible with Dialog.
-Example of the custom footer:
+Example of the custom footer:
@@ -84,16 +84,14 @@ class _ContentState extends State {
KeyboardActionsItem(
focusNode: _nodeText1,
),
- KeyboardActionsItem(focusNode: _nodeText2, toolbarButtons: [
- (node) {
- return GestureDetector(
- onTap: () => node.unfocus(),
- child: Padding(
- padding: EdgeInsets.all(8.0),
- child: Icon(Icons.close),
- ),
- );
- }
+ KeyboardActionsItem(focusNode: _nodeText2, toolbarButtons: (node, _, __, ___) => [
+ GestureDetector(
+ onTap: () => node.unfocus(),
+ child: Padding(
+ padding: EdgeInsets.all(8.0),
+ child: Icon(Icons.close),
+ ),
+ ),
]),
KeyboardActionsItem(
focusNode: _nodeText3,
@@ -117,37 +115,33 @@ class _ContentState extends State {
focusNode: _nodeText4,
displayCloseWidget: false,
),
- KeyboardActionsItem(
+ KeyboardActionsItem(
focusNode: _nodeText5,
- toolbarButtons: [
+ toolbarButtons: (node, _, __, ___) => [
//button 1
- (node) {
- return GestureDetector(
- onTap: () => node.unfocus(),
- child: Container(
- color: Colors.white,
- padding: EdgeInsets.all(8.0),
- child: Text(
- "CLOSE",
- style: TextStyle(color: Colors.black),
- ),
+ GestureDetector(
+ onTap: () => node.unfocus(),
+ child: Container(
+ color: Colors.white,
+ padding: EdgeInsets.all(8.0),
+ child: Text(
+ "CLOSE",
+ style: TextStyle(color: Colors.black),
),
- );
- },
+ ),
+ ),
//button 2
- (node) {
- return GestureDetector(
- onTap: () => node.unfocus(),
- child: Container(
- color: Colors.black,
- padding: EdgeInsets.all(8.0),
- child: Text(
- "DONE",
- style: TextStyle(color: Colors.white),
- ),
+ GestureDetector(
+ onTap: () => node.unfocus(),
+ child: Container(
+ color: Colors.black,
+ padding: EdgeInsets.all(8.0),
+ child: Text(
+ "DONE",
+ style: TextStyle(color: Colors.white),
),
- );
- }
+ ),
+ )
],
),
KeyboardActionsItem(
@@ -413,4 +407,4 @@ class CounterKeyboard extends StatelessWidget
-You can follow me on twitter [@diegoveloper](https://www.twitter.com/diegoveloper)
+You can follow me on twitter [@diegoveloper](https://www.twitter.com/diegoveloper)
\ No newline at end of file
diff --git a/example/lib/content.dart b/example/lib/content.dart
index 64ed171..d910fa2 100644
--- a/example/lib/content.dart
+++ b/example/lib/content.dart
@@ -14,29 +14,18 @@ class Content extends StatefulWidget {
class _ContentState extends State {
final FocusNode _nodeText1 = FocusNode();
-
final FocusNode _nodeText2 = FocusNode();
-
final FocusNode _nodeText3 = FocusNode();
-
final FocusNode _nodeText4 = FocusNode();
-
final FocusNode _nodeText5 = FocusNode();
-
final FocusNode _nodeText6 = FocusNode();
-
final FocusNode _nodeText7 = FocusNode();
-
final FocusNode _nodeText8 = FocusNode();
-
final FocusNode _nodeText9 = FocusNode();
-
final FocusNode _nodeText10 = FocusNode();
final custom1Notifier = ValueNotifier("0");
-
final custom2Notifier = ValueNotifier(Colors.blue);
-
final custom3Notifier = ValueNotifier("");
/// Creates the [KeyboardActionsConfig] to hook up the fields
@@ -50,16 +39,14 @@ class _ContentState extends State {
KeyboardActionsItem(
focusNode: _nodeText1,
),
- KeyboardActionsItem(focusNode: _nodeText2, toolbarButtons: [
- (node) {
- return GestureDetector(
- onTap: () => node.unfocus(),
- child: Padding(
- padding: EdgeInsets.all(8.0),
- child: Icon(Icons.close),
- ),
- );
- }
+ KeyboardActionsItem(focusNode: _nodeText2, toolbarButtons: (node, _, __, ___) => [
+ GestureDetector(
+ onTap: () => node.unfocus(),
+ child: Padding(
+ padding: EdgeInsets.all(8.0),
+ child: Icon(Icons.close),
+ ),
+ ),
]),
KeyboardActionsItem(
focusNode: _nodeText3,
@@ -85,35 +72,31 @@ class _ContentState extends State {
),
KeyboardActionsItem(
focusNode: _nodeText5,
- toolbarButtons: [
+ toolbarButtons: (node, _, __, ___) => [
//button 1
- (node) {
- return GestureDetector(
- onTap: () => node.unfocus(),
- child: Container(
- color: Colors.white,
- padding: EdgeInsets.all(8.0),
- child: Text(
- "CLOSE",
- style: TextStyle(color: Colors.black),
- ),
+ GestureDetector(
+ onTap: () => node.unfocus(),
+ child: Container(
+ color: Colors.white,
+ padding: EdgeInsets.all(8.0),
+ child: Text(
+ "CLOSE",
+ style: TextStyle(color: Colors.black),
),
- );
- },
+ ),
+ ),
//button 2
- (node) {
- return GestureDetector(
- onTap: () => node.unfocus(),
- child: Container(
- color: Colors.black,
- padding: EdgeInsets.all(8.0),
- child: Text(
- "DONE",
- style: TextStyle(color: Colors.white),
- ),
+ GestureDetector(
+ onTap: () => node.unfocus(),
+ child: Container(
+ color: Colors.black,
+ padding: EdgeInsets.all(8.0),
+ child: Text(
+ "DONE",
+ style: TextStyle(color: Colors.white),
),
- );
- }
+ ),
+ )
],
),
KeyboardActionsItem(
diff --git a/example/lib/sample.dart b/example/lib/sample.dart
index b5618a3..779fae5 100644
--- a/example/lib/sample.dart
+++ b/example/lib/sample.dart
@@ -33,6 +33,7 @@ class Sample extends StatelessWidget {
tapOutsideBehavior: TapOutsideBehavior.opaqueDismiss,
config: KeyboardActionsConfig(
keyboardSeparatorColor: Colors.purple,
+ keyboardSeparatorThickness: 5,
actions: [
KeyboardActionsItem(
focusNode: _focusNodeName,
diff --git a/example/lib/sample3.dart b/example/lib/sample3.dart
index 308df75..a9c89a1 100644
--- a/example/lib/sample3.dart
+++ b/example/lib/sample3.dart
@@ -3,8 +3,7 @@ import 'package:keyboard_actions/keyboard_actions.dart';
/// Sample [Widget] demonstrating the usage of [KeyboardActionsConfig.defaultDoneWidget].
class Sample3 extends StatelessWidget {
- final _focusNodes =
- Iterable.generate(7).map((_) => FocusNode()).toList();
+ final _focusNodes = Iterable.generate(7).map((_) => FocusNode()).toList();
@override
Widget build(BuildContext context) {
@@ -19,10 +18,8 @@ class Sample3 extends StatelessWidget {
tapOutsideBehavior: TapOutsideBehavior.translucentDismiss,
config: KeyboardActionsConfig(
// Define ``defaultDoneWidget`` only once in the config
- defaultDoneWidget: _buildMyDoneWidget(),
- actions: _focusNodes
- .map((focusNode) => KeyboardActionsItem(focusNode: focusNode))
- .toList(),
+ defaultDoneWidget: _buildMyDoneWidget,
+ actions: _focusNodes.map((focusNode) => KeyboardActionsItem(focusNode: focusNode)).toList(),
),
child: ListView.separated(
itemBuilder: (ctx, idx) => TextField(
@@ -42,14 +39,20 @@ class Sample3 extends StatelessWidget {
}
/// Returns the custom [Widget] to be rendered as the *"Done"* button.
- Widget _buildMyDoneWidget() {
- return Row(
- mainAxisAlignment: MainAxisAlignment.spaceBetween,
- children: [
- Text('My Done Widget'),
- const SizedBox(width: 10.0),
- Icon(Icons.arrow_drop_down, size: 20.0),
- ],
+ Widget _buildMyDoneWidget(void Function() closeAction) {
+ return Padding(
+ padding: const EdgeInsets.all(5.0),
+ child: InkWell(
+ onTap: closeAction,
+ child: Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: [
+ Text('My Done Widget'),
+ const SizedBox(width: 10.0),
+ Icon(Icons.arrow_drop_down, size: 20.0),
+ ],
+ ),
+ ),
);
}
}
diff --git a/example/lib/sample4.dart b/example/lib/sample4.dart
index e7c2e01..c6c4ae5 100644
--- a/example/lib/sample4.dart
+++ b/example/lib/sample4.dart
@@ -23,31 +23,23 @@ class Sample4 extends StatelessWidget {
toolbarAlignment: MainAxisAlignment.spaceAround,
focusNode: _focusSample,
displayArrows: false,
- toolbarButtons: [
- (_) {
- return IconButton(
- icon: Icon(Icons.format_bold),
- onPressed: () {},
- );
- },
- (_) {
- return IconButton(
- icon: Icon(Icons.format_italic),
- onPressed: () {},
- );
- },
- (_) {
- return IconButton(
+ toolbarButtons: (_, __, ___, ____) => [
+ IconButton(
+ icon: Icon(Icons.format_bold),
+ onPressed: () {},
+ ),
+ IconButton(
+ icon: Icon(Icons.format_italic),
+ onPressed: () {},
+ ),
+ IconButton(
icon: Icon(Icons.format_underline),
onPressed: () {},
- );
- },
- (_) {
- return IconButton(
- icon: Icon(Icons.format_strikethrough),
- onPressed: () {},
- );
- },
+ ),
+ IconButton(
+ icon: Icon(Icons.format_strikethrough),
+ onPressed: () {},
+ ),
],
),
],
diff --git a/example/lib/sample5.dart b/example/lib/sample5.dart
index a993e0c..8f55843 100644
--- a/example/lib/sample5.dart
+++ b/example/lib/sample5.dart
@@ -1,10 +1,10 @@
import 'package:flutter/material.dart';
import 'package:keyboard_actions/keyboard_actions.dart';
-/// Sample [Widget] demonstrating the usage of [KeyboardActionsConfig.defaultDoneWidget].
+/// Sample [Widget] demonstrating the usage of [KeyboardActionsConfig.defaultDoneWidget],
+/// [KeyboardActionsItem.toolbarButtons] and other customizations.
class Sample5 extends StatelessWidget {
- final _focusNodes =
- Iterable.generate(7).map((_) => FocusNode()).toList();
+ final _focusNodes = Iterable.generate(7).map((_) => FocusNode()).toList();
@override
Widget build(BuildContext context) {
@@ -21,12 +21,47 @@ class Sample5 extends StatelessWidget {
child: KeyboardActions(
tapOutsideBehavior: TapOutsideBehavior.translucentDismiss,
config: KeyboardActionsConfig(
+ defaultBarHeight: 70,
+ defaultDoneWidget: _buildMyDoneWidget,
// Define ``defaultDoneWidget`` only once in the config
- defaultDoneWidget: _buildMyDoneWidget(),
- actions: _focusNodes
- .map((focusNode) =>
- KeyboardActionsItem(focusNode: focusNode))
- .toList(),
+ defaultPreviousWidget: (defaultPrevious) => _buildMyPreviousWidget(defaultPrevious),
+ defaultNextWidget: (defaultNext) => _buildMyNextWidget(defaultNext),
+ actions: _focusNodes.map((focusNode) {
+ //For the last field, we want different arrows as well, different from the default we built
+ if (_focusNodes.indexOf(focusNode) == 0) {
+ return KeyboardActionsItem(
+ focusNode: focusNode,
+ displayArrows: false,
+ displayDoneButton: false,
+ toolbarAlignment: MainAxisAlignment.center,
+ toolbarButtons: (node, closeAction, previousAction, nextAction) => [
+ SizedBox(
+ width: 80,
+ child: IconButton(
+ icon: Icon(Icons.keyboard_arrow_up),
+ tooltip: 'Custom Previous',
+ iconSize: 38,
+ color: Colors.orange,
+ disabledColor: Colors.red.shade900,
+ onPressed: previousAction,
+ ),
+ ),
+ SizedBox(
+ width: 80,
+ child: IconButton(
+ icon: Icon(Icons.keyboard_arrow_down),
+ tooltip: 'Custom Previous',
+ iconSize: 38,
+ color: Colors.red,
+ disabledColor: Colors.red.shade900,
+ onPressed: nextAction,
+ ),
+ ),
+ ],
+ );
+ }
+ return KeyboardActionsItem(focusNode: focusNode);
+ }).toList(),
),
child: ListView.separated(
itemBuilder: (ctx, idx) => TextField(
@@ -38,8 +73,7 @@ class Sample5 extends StatelessWidget {
labelText: "Field ${idx + 1}",
),
),
- separatorBuilder: (ctx, idx) =>
- const SizedBox(height: 10.0),
+ separatorBuilder: (ctx, idx) => const SizedBox(height: 10.0),
itemCount: _focusNodes.length,
),
),
@@ -62,14 +96,44 @@ class Sample5 extends StatelessWidget {
}
/// Returns the custom [Widget] to be rendered as the *"Done"* button.
- Widget _buildMyDoneWidget() {
- return Row(
- mainAxisAlignment: MainAxisAlignment.spaceBetween,
- children: [
- Text('My Done Widget'),
- const SizedBox(width: 10.0),
- Icon(Icons.arrow_drop_down, size: 20.0),
- ],
+ Widget _buildMyDoneWidget(void Function() closeAction) {
+ return Padding(
+ padding: const EdgeInsets.all(5.0),
+ child: InkWell(
+ onTap: closeAction,
+ child: Row(
+ mainAxisAlignment: MainAxisAlignment.spaceBetween,
+ children: [
+ Text('My Done Widget'),
+ const SizedBox(width: 10.0),
+ Icon(Icons.arrow_drop_down, size: 20.0),
+ ],
+ ),
+ ),
+ );
+ }
+
+ /// Returns the custom [Widget] to be rendered as the *"Previous"* button.
+ Widget _buildMyPreviousWidget(void Function() previousAction) {
+ return IconButton(
+ icon: Icon(Icons.arrow_upward),
+ tooltip: 'New Default Previous',
+ iconSize: 24,
+ color: Colors.green,
+ disabledColor: Colors.blueGrey,
+ onPressed: previousAction, //You're able to do other things here before calling default Previous
+ );
+ }
+
+ /// Returns the custom [Widget] to be rendered as the *"Next"* button.
+ Widget _buildMyNextWidget(void Function() nextAction) {
+ return IconButton(
+ icon: Icon(Icons.arrow_downward),
+ tooltip: 'New Default Next',
+ iconSize: 24,
+ color: Colors.green,
+ disabledColor: Colors.blueGrey,
+ onPressed: nextAction,
);
}
}
diff --git a/lib/keyboard_actions.dart b/lib/keyboard_actions.dart
index 310133b..787652f 100644
--- a/lib/keyboard_actions.dart
+++ b/lib/keyboard_actions.dart
@@ -411,7 +411,7 @@ class KeyboardActionstate extends State
}
double newOffset = _currentAction!.displayActionBar
- ? _kBarSize
+ ? (config?.defaultBarHeight ?? _kBarSize)
: 0; // offset for the actions bar
final keyboardHeight = EdgeInsets.fromWindowPadding(
@@ -498,18 +498,27 @@ class KeyboardActionstate extends State
/// Build the keyboard action bar based on the current [config].
Widget _buildBar(bool displayArrows) {
+ final closeAction = () {
+ if (_currentAction?.onTapAction != null) {
+ _currentAction!.onTapAction!();
+ }
+ _clearFocus();
+ };
+ final previousAction = _previousIndex != null ? _onTapUp : null;
+ final nextAction = _nextIndex != null ? _onTapDown : null;
+
return AnimatedCrossFade(
duration: _timeToDismiss,
crossFadeState:
_isShowing ? CrossFadeState.showFirst : CrossFadeState.showSecond,
firstChild: Container(
- height: _kBarSize,
+ height: config!.defaultBarHeight ?? _kBarSize,
width: MediaQuery.of(context).size.width,
decoration: BoxDecoration(
border: Border(
top: BorderSide(
- color: widget.config.keyboardSeparatorColor,
- width: 1.0,
+ color: config!.keyboardSeparatorColor,
+ width: config!.keyboardSeparatorThickness,
),
),
),
@@ -521,55 +530,47 @@ class KeyboardActionstate extends State
_currentAction?.toolbarAlignment ?? MainAxisAlignment.end,
children: [
if (config!.nextFocus && displayArrows) ...[
- IconButton(
+ config!.defaultPreviousWidget?.call(previousAction) ?? IconButton(
icon: Icon(Icons.keyboard_arrow_up),
tooltip: 'Previous',
iconSize: IconTheme.of(context).size!,
color: IconTheme.of(context).color,
disabledColor: Theme.of(context).disabledColor,
- onPressed: _previousIndex != null ? _onTapUp : null,
+ onPressed: previousAction,
),
- IconButton(
+ config!.defaultNextWidget?.call(nextAction) ?? IconButton(
icon: Icon(Icons.keyboard_arrow_down),
tooltip: 'Next',
iconSize: IconTheme.of(context).size!,
color: IconTheme.of(context).color,
disabledColor: Theme.of(context).disabledColor,
- onPressed: _nextIndex != null ? _onTapDown : null,
+ onPressed: nextAction,
),
const Spacer(),
],
if (_currentAction?.displayDoneButton != null &&
_currentAction!.displayDoneButton &&
(_currentAction!.toolbarButtons == null ||
- _currentAction!.toolbarButtons!.isEmpty))
- Padding(
+ _currentAction!.toolbarButtons!(_currentAction!.focusNode, closeAction, previousAction, nextAction).isEmpty))
+ config?.defaultDoneWidget?.call(closeAction) ?? Padding(
padding: const EdgeInsets.all(5.0),
child: InkWell(
- onTap: () {
- if (_currentAction?.onTapAction != null) {
- _currentAction!.onTapAction!();
- }
- _clearFocus();
- },
+ onTap: closeAction,
child: Container(
- padding:
+ padding:
EdgeInsets.symmetric(vertical: 8.0, horizontal: 12.0),
- child: config?.defaultDoneWidget ??
- Text(
- "Done",
- style: TextStyle(
- fontSize: 16.0,
- fontWeight: FontWeight.w500,
- ),
+ child:Text(
+ "Done",
+ style: TextStyle(
+ fontSize: 16.0,
+ fontWeight: FontWeight.w500,
),
+ ),
),
),
),
if (_currentAction?.toolbarButtons != null)
- ..._currentAction!.toolbarButtons!
- .map((item) => item(_currentAction!.focusNode))
- .toList()
+ ..._currentAction!.toolbarButtons!(_currentAction!.focusNode, closeAction, previousAction, nextAction)
],
),
),
diff --git a/lib/keyboard_actions_config.dart b/lib/keyboard_actions_config.dart
index 10309bd..4af0f80 100644
--- a/lib/keyboard_actions_config.dart
+++ b/lib/keyboard_actions_config.dart
@@ -19,12 +19,24 @@ class KeyboardActionsConfig {
/// Elevation of the Custom keyboard buttons
final double? keyboardBarElevation;
+ /// Thickness of the line separator between keyboard and content, defaults to 1.0
+ final double keyboardSeparatorThickness;
+
/// Color of the line separator between keyboard and content
final Color keyboardSeparatorColor;
+ /// The height to be optionally used instead of the Default bar height, defaults to 45
+ final double? defaultBarHeight;
+
/// A [Widget] to be optionally used instead of the "Done" button
/// which dismisses the keyboard.
- final Widget? defaultDoneWidget;
+ final Widget? Function(void Function()? closeAction)? defaultDoneWidget;
+
+ /// A [Widget] to be optionally used instead of the "Previous" button.
+ final Widget? Function(void Function()? previousAction)? defaultPreviousWidget;
+
+ /// A [Widget] to be optionally used instead of the "Next" button.
+ final Widget? Function(void Function()? nextAction)? defaultNextWidget;
const KeyboardActionsConfig({
this.keyboardActionsPlatform = KeyboardActionsPlatform.ALL,
@@ -32,7 +44,11 @@ class KeyboardActionsConfig {
this.actions,
this.keyboardBarColor,
this.keyboardBarElevation,
+ this.keyboardSeparatorThickness = 1.0,
this.keyboardSeparatorColor = Colors.transparent,
+ this.defaultBarHeight,
this.defaultDoneWidget,
+ this.defaultPreviousWidget,
+ this.defaultNextWidget,
});
}
diff --git a/lib/keyboard_actions_item.dart b/lib/keyboard_actions_item.dart
index 9c0a248..7992e1b 100644
--- a/lib/keyboard_actions_item.dart
+++ b/lib/keyboard_actions_item.dart
@@ -1,6 +1,6 @@
import 'package:flutter/material.dart';
-typedef ButtonBuilder = Widget Function(FocusNode focusNode);
+typedef ButtonsBuilder = List Function(FocusNode focusNode, void Function() closeAction, void Function()? previousAction, void Function()? nextAction);
///Class to define the `focusNode` that you pass to your `TextField` too and other params to customize
///the bar that will appear over your keyboard
@@ -10,7 +10,7 @@ class KeyboardActionsItem {
/// Optional widgets to display to the right of the bar/
/// NOTE: `toolbarButtons` override the Done button by default
- final List? toolbarButtons;
+ final ButtonsBuilder? toolbarButtons;
/// true [default] to display the Done button
final bool displayDoneButton;