diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..47e0b4d --- /dev/null +++ b/.gitignore @@ -0,0 +1,71 @@ +# Miscellaneous +*.class +*.lock +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.buildlog/ +.history +.svn/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# Visual Studio Code related +.vscode/ + +# Flutter/Dart/Pub related +**/doc/api/ +.dart_tool/ +.flutter-plugins +.packages +.pub-cache/ +.pub/ +build/ + +# Android related +**/android/**/gradle-wrapper.jar +**/android/.gradle +**/android/captures/ +**/android/gradlew +**/android/gradlew.bat +**/android/local.properties +**/android/**/GeneratedPluginRegistrant.java + +# iOS/XCode related +**/ios/**/*.mode1v3 +**/ios/**/*.mode2v3 +**/ios/**/*.moved-aside +**/ios/**/*.pbxuser +**/ios/**/*.perspectivev3 +**/ios/**/*sync/ +**/ios/**/.sconsign.dblite +**/ios/**/.tags* +**/ios/**/.vagrant/ +**/ios/**/DerivedData/ +**/ios/**/Icon? +**/ios/**/Pods/ +**/ios/**/.symlinks/ +**/ios/**/profile +**/ios/**/xcuserdata +**/ios/.generated/ +**/ios/Flutter/App.framework +**/ios/Flutter/Flutter.framework +**/ios/Flutter/Generated.xcconfig +**/ios/Flutter/app.flx +**/ios/Flutter/app.zip +**/ios/Flutter/flutter_assets/ +**/ios/ServiceDefinitions.json +**/ios/Runner/GeneratedPluginRegistrant.* + +# Exceptions to above rules. +!**/ios/**/default.mode1v3 +!**/ios/**/default.mode2v3 +!**/ios/**/default.pbxuser +!**/ios/**/default.perspectivev3 +!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages diff --git a/.metadata b/.metadata new file mode 100644 index 0000000..c9e11e1 --- /dev/null +++ b/.metadata @@ -0,0 +1,10 @@ +# This file tracks properties of this Flutter project. +# Used by Flutter tool to assess capabilities and perform upgrades etc. +# +# This file should be version controlled and should not be manually edited. + +version: + revision: 59ce7d6bff0d0626ae4b90787bf993ebcdc4b110 + channel: dev + +project_type: package diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..9b7b76d --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,3 @@ +## [0.0.1] - 03/28/2019. + +* Inital release. diff --git a/README.md b/README.md new file mode 100644 index 0000000..e926dfa --- /dev/null +++ b/README.md @@ -0,0 +1,194 @@ + +
+

+FlutterBlue +

+
+

+FlutterBlue +

+
+ +# virtual_keyboard + +## Introduction +A simple package for dispaying virtual keyboards on a devices like kiosks and ATMs. The library is written in Dart and has no native code dependancy. + +Virtual keyboard provides a core set of functionality to display onscreen virtual keyboards. Managing the events sould be done on the project level. + +## Reference + +### VirtualKeyboard +Flutter widget to show virtual keyboards. +```dart +// Keyboard Type: Can be Numeric or Alphanumeric. +VirtualKeyboardType type +``` +```dart +// Callback for Key press event. Called with pressed `Key` object. +Function onKeyPress; +``` +```dart +// Virtual keyboard height. Default is 300. +double height; +``` +```dart +// Color for key texts and icons. +Color textColor; +``` +```dart +// Font size for keyboard keys. +double fontSize;; +``` + +### VirtualKeyboardType +enum of Available Virtual Keyboard Types. +```dart +// Numeric only. +VirtualKeyboardType.Numeric +``` +```dart +// Alphanumeric: letters`[A-Z]` + numbers`[0-9]` + `@` + `.`. +VirtualKeyboardType.Alphanumeric +``` + +### VirtualKeyboardKey +Virtual Keyboard key. +```dart +// The text of the key. +String text +``` +```dart +// The capitalized text of the key. +String capsText; +``` +```dart +// Action or String +VirtualKeyboardKeyType keyType; +``` +```dart +// Action of the key. +VirtualKeyboardKeyAction action; +``` +### VirtualKeyboardKeyType +Type for virtual keyboard key. + +```dart +// Can be an action key - Return, Backspace, etc. +VirtualKeyboardKeyType.Action +``` +```dart +// Keys that have text values - letters, numbers, comma ... +VirtualKeyboardKeyType.String +``` + +### VirtualKeyboardKeyAction +```dart +/// Virtual keyboard actions. +enum VirtualKeyboardKeyAction { Backspace, Return, Shift, Space } +``` + +## Usage + +#### Show Alphanumeric keyboard with default view +```dart +// Wrap the keyboard with Container to set background color. +Container( + // Keyboard is transparent + color: Colors.deepPurple, + child: VirtualKeyboard( + // Default height is 300 + height: 350, + // Default is black + textColor: Colors.white, + // Default 14 + fontSize: 20, + // [A-Z, 0-9] + type: VirtualKeyboardType.Alphanumeric, + // Callback for key press event + onKeyPress: _onKeyPress), + ) +``` + +#### Show Numeric keyboard with default view +```dart +Container( + // Keyboard is transparent + color: Colors.red, + child: VirtualKeyboard( + // [0-9] + . + type: VirtualKeyboardType.Numeric, + // Callback for key press event + onKeyPress: (key) => print(key.text)), + ) +``` + +#### Show Alphanumeric keyboard with customized keys + +```dart + Container( + color: Colors.deepPurple, + child: VirtualKeyboard( + height: keyboardHeight, + textColor: Colors.white, + fontSize: 20, + builder: _builder, + type: VirtualKeyboardType.Numeric, + onKeyPress: _onKeyPress), + ) + + /// Builder for keyboard keys. + Widget _builder(BuildContext context, VirtualKeyboardKey key) { + Widget keyWidget; + + switch (key.keyType) { + case VirtualKeyboardKeyType.String: + // Draw String key. + keyWidget = _keyboardDefaultKey(key); + break; + case VirtualKeyboardKeyType.Action: + // Draw action key. + keyWidget = _keyboardDefaultActionKey(key); + break; + } + + return keyWidget; + } +``` + +#### onKeyPressed event basic ussage example +```dart +// Just local variable. Use Text widget or similar to show in UI. +String text; + + /// Fired when the virtual keyboard key is pressed. +_onKeyPress(VirtualKeyboardKey key) { +if (key.keyType == VirtualKeyboardKeyType.String) { + text = text + (shiftEnabled ? key.capsText : key.text); +} else if (key.keyType == VirtualKeyboardKeyType.Action) { + switch (key.action) { + case VirtualKeyboardKeyAction.Backspace: + if (text.length == 0) return; + text = text.substring(0, text.length - 1); + break; + case VirtualKeyboardKeyAction.Return: + text = text + '\n'; + break; + case VirtualKeyboardKeyAction.Space: + text = text + key.text; + break; + case VirtualKeyboardKeyAction.Shift: + shiftEnabled = !shiftEnabled; + break; + default: + } +} +// Update the screen +setState(() {}); +} +``` + +- [Gurgen Hovhannisyan](https://github.com/gurgenDP) +- [Digital Pomegranate](https://digitalpomegranate.com) +- [LICENSE - MIT](https://github.com/gurgenDP/virtual_keyboard/blob/master/LICENSE) + diff --git a/lib/src/key.dart b/lib/src/key.dart new file mode 100644 index 0000000..27f7d05 --- /dev/null +++ b/lib/src/key.dart @@ -0,0 +1,14 @@ +part of virtual_keyboard; + + + +/// Virtual Keyboard key +class VirtualKeyboardKey { + final String text; + final String capsText; + final VirtualKeyboardKeyType keyType; + final VirtualKeyboardKeyAction action; + + VirtualKeyboardKey( + {this.text, this.capsText, @required this.keyType, this.action}); +} diff --git a/lib/src/key_action.dart b/lib/src/key_action.dart new file mode 100644 index 0000000..1631600 --- /dev/null +++ b/lib/src/key_action.dart @@ -0,0 +1,4 @@ +part of virtual_keyboard; + +/// Virtual keyboard actions. +enum VirtualKeyboardKeyAction { Backspace, Return, Shift, Space } \ No newline at end of file diff --git a/lib/src/key_type.dart b/lib/src/key_type.dart new file mode 100644 index 0000000..2c7b57a --- /dev/null +++ b/lib/src/key_type.dart @@ -0,0 +1,8 @@ +part of virtual_keyboard; + +/// Type for virtual keyboard key. +/// +/// `Action` - Can be action key - Return, Backspace, etc. +/// +/// `String` - Keys that have text value - `Letters`, `Numbers`, `@` `.` +enum VirtualKeyboardKeyType { Action, String } \ No newline at end of file diff --git a/lib/src/keyboard.dart b/lib/src/keyboard.dart new file mode 100644 index 0000000..192bf2b --- /dev/null +++ b/lib/src/keyboard.dart @@ -0,0 +1,237 @@ +part of virtual_keyboard; + + + +/// The default keyboard height. Can we overriden by passing +/// `height` argument to `VirtualKeyboard` widget. +const double _virtualKeyboardDefaultHeight = 300; + +/// Virtual Keyboard widget. +class VirtualKeyboard extends StatefulWidget { + /// Keyboard Type: Should be inited in creation time. + final VirtualKeyboardType type; + + /// Callback for Key press event. Called with pressed `Key` object. + final Function onKeyPress; + + /// Virtual keyboard height. Default is 300 + final double height; + + /// Color for key texts and icons. + final Color textColor; + + // Font size for keyboard keys. + final double fontSize; + + // The builder function will be called for each Key object. + final Widget Function(BuildContext context, VirtualKeyboardKey key) builder; + + VirtualKeyboard( + {@required this.type, + @required this.onKeyPress, + this.builder, + this.height = _virtualKeyboardDefaultHeight, + this.textColor = Colors.black, + this.fontSize = 14}); + + @override + State createState() { + return _VirtualKeyboardState( + type: type, + onKeyPress: onKeyPress, + builder: builder, + height: height, + textColor: textColor, + fontSize: fontSize); + } +} + +/// Holds the state for Virtual Keyboard class. +class _VirtualKeyboardState extends State { + final VirtualKeyboardType type; + final Function onKeyPress; + // The builder function will be called for each Key object. + final Widget Function(BuildContext context, VirtualKeyboardKey key) builder; + final double height; + final Color textColor; + final double fontSize; + + _VirtualKeyboardState( + {this.type, + this.onKeyPress, + this.height, + this.builder, + this.textColor, + this.fontSize}); + + // Text Style for keys. + TextStyle textStyle; + + // True if shift is enabled. + bool isShiftEnabled = false; + + @override + void initState() { + super.initState(); + + // Init the Text Style for keys. + textStyle = TextStyle( + fontSize: fontSize, + color: textColor, + ); + } + + @override + Widget build(BuildContext context) { + return type == VirtualKeyboardType.Numeric ? _numeric() : _alphanumeric(); + } + + Widget _alphanumeric() { + return Container( + height: height, + width: MediaQuery.of(context).size.width, + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.center, + children: _rows(), + ), + ); + } + + Widget _numeric() { + return Container( + height: height, + width: MediaQuery.of(context).size.width, + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.center, + children: _rows(), + ), + ); + } + + /// Returns the rows for keyboard. + List _rows() { + // Get the keyboard Rows + List> keyboardRows = + type == VirtualKeyboardType.Numeric + ? _getKeyboardRowsNumeric() + : _getKeyboardRows(); + + // Generate keyboard row. + List rows = List.generate(keyboardRows.length, (int rowNum) { + return Material( + color: Colors.transparent, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + crossAxisAlignment: CrossAxisAlignment.center, + // Generate keboard keys + children: List.generate( + keyboardRows[rowNum].length, + (int keyNum) { + // Get the VirtualKeyboardKey object. + VirtualKeyboardKey virtualKeyboardKey = + keyboardRows[rowNum][keyNum]; + + Widget keyWidget; + + // Check if builder is specified. + // Call builder function if specified or use default + // Key widgets if not. + if (builder == null) { + // Check the key type. + switch (virtualKeyboardKey.keyType) { + case VirtualKeyboardKeyType.String: + // Draw String key. + keyWidget = _keyboardDefaultKey(virtualKeyboardKey); + break; + case VirtualKeyboardKeyType.Action: + // Draw action key. + keyWidget = _keyboardDefaultActionKey(virtualKeyboardKey); + break; + } + } else { + // Call the builder function, so the user can specify custom UI for keys. + keyWidget = builder(context, virtualKeyboardKey); + + if (keyWidget == null) { + throw 'builder function must return Widget'; + } + } + + return keyWidget; + }, + ), + ), + ); + }); + + return rows; + } + + /// Creates default UI element for keyboard Key. + Widget _keyboardDefaultKey(VirtualKeyboardKey key) { + return Expanded( + child: InkWell( + onTap: () { + onKeyPress(key); + }, + child: Container( + height: height / _keyRows.length, + child: Center( + child: Text( + isShiftEnabled ? key.capsText : key.text, + style: textStyle, + )), + ), + )); + } + + /// Creates default UI element for keyboard Action Key. + Widget _keyboardDefaultActionKey(VirtualKeyboardKey key) { + // Holds the action key widget. + Widget actionKey; + + // Switch the action type to build action Key widget. + switch (key.action) { + case VirtualKeyboardKeyAction.Backspace: + actionKey = Icon( + Icons.backspace, + color: textColor, + ); + break; + case VirtualKeyboardKeyAction.Shift: + actionKey = Icon(Icons.arrow_upward, color: textColor); + break; + case VirtualKeyboardKeyAction.Space: + actionKey = actionKey = Icon(Icons.space_bar, color: textColor); + break; + case VirtualKeyboardKeyAction.Return: + actionKey = Icon( + Icons.keyboard_return, + color: textColor, + ); + break; + } + + return Expanded( + child: InkWell( + onTap: () { + if (key.action == VirtualKeyboardKeyAction.Shift) { + setState(() { + isShiftEnabled = !isShiftEnabled; + }); + } + + onKeyPress(key); + }, + child: Container( + height: height / _keyRows.length, + child: Center( + child: actionKey, + ), + ), + ), + ); + } +} diff --git a/lib/src/rows.dart b/lib/src/rows.dart new file mode 100644 index 0000000..09267db --- /dev/null +++ b/lib/src/rows.dart @@ -0,0 +1,224 @@ +part of virtual_keyboard; + +/// Keys for Virtual Keyboard's rows. +const List _keyRows = [ + // Row 1 + const [ + '1', + '2', + '3', + '4', + '5', + '6', + '7', + '8', + '9', + '0', + ], + // Row 2 + const [ + 'q', + 'w', + 'e', + 'r', + 't', + 'y', + 'u', + 'i', + 'o', + 'p', + ], + // Row 3 + const [ + 'a', + 's', + 'd', + 'f', + 'g', + 'h', + 'j', + 'k', + 'l', + ';', + '\'', + ], + // Row 4 + const [ + 'z', + 'x', + 'c', + 'v', + 'b', + 'n', + 'm', + ',', + '.', + '/', + ], + // Row 5 + const [ + '@', + '_', + ] +]; + +/// Keys for Virtual Keyboard's rows. +const List _keyRowsNumeric = [ + // Row 1 + const [ + '1', + '2', + '3', + ], + // Row 1 + const [ + '4', + '5', + '6', + ], + // Row 1 + const [ + '7', + '8', + '9', + ], + // Row 1 + const [ + '.', + '0', + ], +]; + +/// Returns a list of `VirtualKeyboardKey` objects for Numeric keyboard. +List _getKeyboardRowKeysNumeric(rowNum) { + // Generate VirtualKeyboardKey objects for each row. + return List.generate(_keyRowsNumeric[rowNum].length, (int keyNum) { + // Get key string value. + String key = _keyRowsNumeric[rowNum][keyNum]; + + // Create and return new VirtualKeyboardKey object. + return VirtualKeyboardKey( + text: key, + capsText: key.toUpperCase(), + keyType: VirtualKeyboardKeyType.String, + ); + }); +} + +/// Returns a list of `VirtualKeyboardKey` objects. +List _getKeyboardRowKeys(rowNum) { + // Generate VirtualKeyboardKey objects for each row. + return List.generate(_keyRows[rowNum].length, (int keyNum) { + // Get key string value. + String key = _keyRows[rowNum][keyNum]; + + // Create and return new VirtualKeyboardKey object. + return VirtualKeyboardKey( + text: key, + capsText: key.toUpperCase(), + keyType: VirtualKeyboardKeyType.String, + ); + }); +} + +/// Returns a list of VirtualKeyboard rows with `VirtualKeyboardKey` objects. +List> _getKeyboardRows() { + // Generate lists for each keyboard row. + return List.generate(_keyRows.length, (int rowNum) { + // Will contain the keyboard row keys. + List rowKeys = []; + + // We have to add Action keys to keyboard. + switch (rowNum) { + case 1: + // String keys. + rowKeys = _getKeyboardRowKeys(rowNum); + + // 'Backspace' button. + rowKeys.add( + VirtualKeyboardKey( + keyType: VirtualKeyboardKeyType.Action, + action: VirtualKeyboardKeyAction.Backspace), + ); + break; + case 2: + // String keys. + rowKeys = _getKeyboardRowKeys(rowNum); + + // 'Return' button. + rowKeys.add( + VirtualKeyboardKey( + keyType: VirtualKeyboardKeyType.Action, + action: VirtualKeyboardKeyAction.Return, + text: '\n', + capsText: '\n'), + ); + break; + case 3: + // Left Shift + rowKeys.add( + VirtualKeyboardKey( + keyType: VirtualKeyboardKeyType.Action, + action: VirtualKeyboardKeyAction.Shift), + ); + + // String keys. + rowKeys.addAll(_getKeyboardRowKeys(rowNum)); + + // Right Shift + rowKeys.add( + VirtualKeyboardKey( + keyType: VirtualKeyboardKeyType.Action, + action: VirtualKeyboardKeyAction.Shift), + ); + break; + case 4: + // String keys. + rowKeys = _getKeyboardRowKeys(rowNum); + + // Insert the space key into second position of row. + rowKeys.insert( + 1, + VirtualKeyboardKey( + keyType: VirtualKeyboardKeyType.Action, + text: ' ', + capsText: ' ', + action: VirtualKeyboardKeyAction.Space), + ); + + break; + default: + rowKeys = _getKeyboardRowKeys(rowNum); + } + + return rowKeys; + }); +} + +/// Returns a list of VirtualKeyboard rows with `VirtualKeyboardKey` objects. +List> _getKeyboardRowsNumeric() { + // Generate lists for each keyboard row. + return List.generate(_keyRowsNumeric.length, (int rowNum) { + // Will contain the keyboard row keys. + List rowKeys = []; + + // We have to add Action keys to keyboard. + switch (rowNum) { + case 3: + // String keys. + rowKeys.addAll(_getKeyboardRowKeysNumeric(rowNum)); + + // Right Shift + rowKeys.add( + VirtualKeyboardKey( + keyType: VirtualKeyboardKeyType.Action, + action: VirtualKeyboardKeyAction.Backspace), + ); + break; + default: + rowKeys = _getKeyboardRowKeysNumeric(rowNum); + } + + return rowKeys; + }); +} diff --git a/lib/src/type.dart b/lib/src/type.dart new file mode 100644 index 0000000..82ab2fb --- /dev/null +++ b/lib/src/type.dart @@ -0,0 +1,6 @@ +part of virtual_keyboard; + +/// Available Virtual Keyboard Types: +/// `Numeric` - Numeric only. +/// `Alphanumeric` - Alphanumeric: letters`[A-Z]` + numbers`[0-9]` + `@` + `.`. +enum VirtualKeyboardType { Numeric, Alphanumeric } diff --git a/lib/virtual_keyboard.dart b/lib/virtual_keyboard.dart new file mode 100644 index 0000000..18b1093 --- /dev/null +++ b/lib/virtual_keyboard.dart @@ -0,0 +1,10 @@ +library virtual_keyboard; + +import 'package:flutter/material.dart'; + +part './src/key_action.dart'; +part './src/key_type.dart'; +part './src/key.dart'; +part './src/keyboard.dart'; +part './src/rows.dart'; +part './src/type.dart'; diff --git a/pubspec.yaml b/pubspec.yaml new file mode 100644 index 0000000..1e79dd1 --- /dev/null +++ b/pubspec.yaml @@ -0,0 +1,53 @@ +name: virtual_keyboard +description: Platform independent virtual Keyboard. +version: 0.0.1 +author: Gurgen Hovhannisyan +homepage: https://github.com/gurgenDP/virtual_keyboard + +environment: + sdk: ">=2.1.0 <3.0.0" + +dependencies: + flutter: + sdk: flutter + +dev_dependencies: + flutter_test: + sdk: flutter + +# For information on the generic Dart part of this file, see the +# following page: https://www.dartlang.org/tools/pub/pubspec + +# The following section is specific to Flutter. +flutter: + + # To add assets to your package, add an assets section, like this: + # assets: + # - images/a_dot_burr.jpeg + # - images/a_dot_ham.jpeg + # + # For details regarding assets in packages, see + # https://flutter.io/assets-and-images/#from-packages + # + # An image asset can refer to one or more resolution-specific "variants", see + # https://flutter.io/assets-and-images/#resolution-aware. + + # To add custom fonts to your package, add a fonts section here, + # in this "flutter" section. Each entry in this list should have a + # "family" key with the font family name, and a "fonts" key with a + # list giving the asset and other descriptors for the font. For + # example: + # fonts: + # - family: Schyler + # fonts: + # - asset: fonts/Schyler-Regular.ttf + # - asset: fonts/Schyler-Italic.ttf + # style: italic + # - family: Trajan Pro + # fonts: + # - asset: fonts/TrajanPro.ttf + # - asset: fonts/TrajanPro_Bold.ttf + # weight: 700 + # + # For details regarding fonts in packages, see + # https://flutter.io/custom-fonts/#from-packages diff --git a/screen1.png b/screen1.png new file mode 100644 index 0000000..a22282f Binary files /dev/null and b/screen1.png differ diff --git a/screen2.png b/screen2.png new file mode 100644 index 0000000..43a7a86 Binary files /dev/null and b/screen2.png differ diff --git a/test/virtual_keyboard_test.dart b/test/virtual_keyboard_test.dart new file mode 100644 index 0000000..cfe9d74 --- /dev/null +++ b/test/virtual_keyboard_test.dart @@ -0,0 +1,13 @@ +import 'package:flutter_test/flutter_test.dart'; + +import 'package:virtual_keyboard/virtual_keyboard.dart'; + +void main() { + test('creates keyboard widget with Alphanumeric type', () { + final keyboard = VirtualKeyboard( + type: VirtualKeyboardType.Alphanumeric, + onKeyPress: () => null, + ); + expect(keyboard.type, VirtualKeyboardType.Alphanumeric); + }); +}