├── .gitattributes
├── android
├── gradle
│ └── wrapper
│ │ ├── gradle-wrapper.jar
│ │ └── gradle-wrapper.properties
├── src
│ └── main
│ │ ├── AndroidManifest.xml
│ │ └── java
│ │ └── com
│ │ ├── reactlibrary
│ │ └── RNAllmaxKeyboardPackage.java
│ │ └── facebook
│ │ └── react
│ │ └── uimanager
│ │ └── RNAllmaxKeyboardModule.java
├── build.gradle
├── gradlew.bat
└── gradlew
├── ios
├── RNAllmaxKeyboard.h
├── RNAllmaxKeyboardEventEmitter.h
├── RNAllmaxKeyboard.podspec
├── RNAllmaxKeyboardEventEmitter.m
├── RNAllmaxKeyboard.m
└── RNAllmaxKeyboard.xcodeproj
│ └── project.pbxproj
├── package.json
├── .gitignore
├── index.js
├── lib
├── TextField.ios.js
└── TextField.android.js
└── README.md
/.gitattributes:
--------------------------------------------------------------------------------
1 | *.pbxproj -text
--------------------------------------------------------------------------------
/android/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/naxel/react-native-keyboard/HEAD/android/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/android/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/ios/RNAllmaxKeyboard.h:
--------------------------------------------------------------------------------
1 | #import
2 | #import
3 | #import
4 |
5 | @interface RNAllmaxKeyboard : NSObject
6 |
7 | @end
8 |
--------------------------------------------------------------------------------
/ios/RNAllmaxKeyboardEventEmitter.h:
--------------------------------------------------------------------------------
1 | #import
2 | #import
3 | #import
4 |
5 | @interface RNAllmaxKeyboardEventEmitter : RCTEventEmitter
6 |
7 |
8 | @end
9 |
--------------------------------------------------------------------------------
/android/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Tue Aug 29 19:39:44 NOVT 2017
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip
7 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 |
2 | {
3 | "name": "react-native-allmax-keyboard",
4 | "version": "2.0.0",
5 | "description": "",
6 | "main": "index.js",
7 | "scripts": {
8 | "test": "echo \"Error: no test specified\" && exit 1"
9 | },
10 | "keywords": [
11 | "react-native"
12 | ],
13 | "author": "",
14 | "license": "",
15 | "peerDependencies": {
16 | "react-native": "^0.47.1"
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | # OSX
3 | #
4 | .DS_Store
5 |
6 | # node.js
7 | #
8 | node_modules/
9 | npm-debug.log
10 | yarn-error.log
11 |
12 |
13 | # Xcode
14 | #
15 | build/
16 | *.pbxuser
17 | !default.pbxuser
18 | *.mode1v3
19 | !default.mode1v3
20 | *.mode2v3
21 | !default.mode2v3
22 | *.perspectivev3
23 | !default.perspectivev3
24 | xcuserdata
25 | *.xccheckout
26 | *.moved-aside
27 | DerivedData
28 | *.hmap
29 | *.ipa
30 | *.xcuserstate
31 | project.xcworkspace
32 |
33 |
34 | # Android/IntelliJ
35 | #
36 | build/
37 | .idea
38 | .gradle
39 | local.properties
40 | *.iml
41 |
42 | # BUCK
43 | buck-out/
44 | \.buckd/
45 | *.keystore
46 |
--------------------------------------------------------------------------------
/android/build.gradle:
--------------------------------------------------------------------------------
1 |
2 | buildscript {
3 | repositories {
4 | jcenter()
5 | }
6 |
7 | dependencies {
8 | classpath 'com.android.tools.build:gradle:1.3.1'
9 | }
10 | }
11 |
12 | apply plugin: 'com.android.library'
13 |
14 | android {
15 | compileSdkVersion 23
16 | buildToolsVersion '25.0.0'
17 |
18 | defaultConfig {
19 | minSdkVersion 16
20 | targetSdkVersion 22
21 | versionCode 1
22 | versionName "1.0"
23 | }
24 | lintOptions {
25 | abortOnError false
26 | }
27 | }
28 |
29 | repositories {
30 | mavenCentral()
31 | }
32 |
33 | dependencies {
34 | compile 'com.facebook.react:react-native:+'
35 | }
36 |
--------------------------------------------------------------------------------
/ios/RNAllmaxKeyboard.podspec:
--------------------------------------------------------------------------------
1 |
2 | Pod::Spec.new do |s|
3 | s.name = "RNAllmaxKeyboard"
4 | s.version = "1.0.0"
5 | s.summary = "RNAllmaxKeyboard"
6 | s.description = <<-DESC
7 | RNAllmaxKeyboard
8 | DESC
9 | s.homepage = ""
10 | s.license = "MIT"
11 | # s.license = { :type => "MIT", :file => "FILE_LICENSE" }
12 | s.author = { "author" => "author@domain.cn" }
13 | s.platform = :ios, "7.0"
14 | s.source = { :git => "https://github.com/author/RNAllmaxKeyboard.git", :tag => "master" }
15 | s.source_files = "RNAllmaxKeyboard/**/*.{h,m}"
16 | s.requires_arc = true
17 |
18 |
19 | s.dependency "React"
20 | #s.dependency "others"
21 |
22 | end
23 |
24 |
--------------------------------------------------------------------------------
/android/src/main/java/com/reactlibrary/RNAllmaxKeyboardPackage.java:
--------------------------------------------------------------------------------
1 |
2 | package com.reactlibrary;
3 |
4 | import java.util.Arrays;
5 | import java.util.Collections;
6 | import java.util.List;
7 |
8 | import com.facebook.react.ReactPackage;
9 | import com.facebook.react.bridge.NativeModule;
10 | import com.facebook.react.bridge.ReactApplicationContext;
11 | import com.facebook.react.uimanager.RNAllmaxKeyboardModule;
12 | import com.facebook.react.uimanager.ViewManager;
13 |
14 | public class RNAllmaxKeyboardPackage implements ReactPackage {
15 | @Override
16 | public List createNativeModules(ReactApplicationContext reactContext) {
17 | return Arrays.asList(new RNAllmaxKeyboardModule(reactContext));
18 | }
19 |
20 | @Override
21 | public List createViewManagers(ReactApplicationContext reactContext) {
22 | return Collections.emptyList();
23 | }
24 | }
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import { AppRegistry, NativeModules } from 'react-native';
3 | import TextField from './lib/TextField';
4 |
5 | const { backSpace, insertText, switchSystemKeyboard, installKeyboard, done, clear, setHeight } = NativeModules.RNAllmaxKeyboard;
6 |
7 | const keyboardTypeRegistry = {};
8 |
9 | function registerKeyboard (keyboardType, keyboardProvider) {
10 | keyboardTypeRegistry[keyboardType] = keyboardProvider;
11 | }
12 |
13 | class CustomKeyboardContainer extends Component {
14 | render () {
15 | const { tag, keyboardType } = this.props;
16 | const factory = keyboardTypeRegistry[keyboardType];
17 | if (!factory) {
18 | console.warn(`Custom keyboard type ${keyboardType} not registered.`);
19 | return null;
20 | }
21 | const Keyboard = factory();
22 | return ;
23 | }
24 | }
25 |
26 | AppRegistry.registerComponent("AllMaxKeyboard", () => CustomKeyboardContainer);
27 |
28 | export {
29 | registerKeyboard,
30 | TextField,
31 | backSpace,
32 | insertText,
33 | done,
34 | clear, // only for Android
35 | installKeyboard,
36 | switchSystemKeyboard,
37 | setHeight
38 | }
39 |
--------------------------------------------------------------------------------
/ios/RNAllmaxKeyboardEventEmitter.m:
--------------------------------------------------------------------------------
1 | //
2 | // RNAllmaxKeyboardEventEmitter.m
3 | // RNAllmaxKeyboard
4 | //
5 | // Created by Oleg on 29.08.17.
6 | // Copyright © 2017 Facebook. All rights reserved.
7 | //
8 |
9 | #import "RNAllmaxKeyboardEventEmitter.h"
10 |
11 | @implementation RNAllmaxKeyboardEventEmitter
12 |
13 | @synthesize bridge = _bridge;
14 |
15 | - (instancetype)init
16 | {
17 | self = [super init];
18 | if (self) {
19 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(touchDownTextFieldWithNotification:) name:@"RNAllMaxKeyboardTouchDownTextField" object:nil];
20 | }
21 | return self;
22 | }
23 |
24 | - (void)dealloc
25 | {
26 | [[NSNotificationCenter defaultCenter] removeObserver:self];
27 | }
28 |
29 | - (dispatch_queue_t)methodQueue
30 | {
31 | return dispatch_get_main_queue();
32 | }
33 |
34 | RCT_EXPORT_MODULE(RNAllmaxKeyboardEventEmitter)
35 |
36 | - (NSArray *)supportedEvents
37 | {
38 | return @[@"TouchDownTextField"];
39 | }
40 |
41 | - (void)touchDownTextFieldWithNotification: (NSNotification *) notification {
42 | NSLog(@"%@", notification);
43 | [self sendEventWithName:@"TouchDownTextField" body:notification.userInfo];
44 | }
45 |
46 |
47 | @end
48 |
--------------------------------------------------------------------------------
/lib/TextField.ios.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import PropTypes from 'prop-types';
3 | import { findNodeHandle, NativeEventEmitter, NativeModules, TextInput } from 'react-native';
4 |
5 | const { installKeyboard, uninstall } = NativeModules.RNAllmaxKeyboard;
6 |
7 | const keyboardManagerEmitter = new NativeEventEmitter(NativeModules.RNAllmaxKeyboardEventEmitter);
8 |
9 | export default class TextField extends Component {
10 |
11 | static propTypes = {
12 | ...TextInput.propTypes,
13 | customKeyboardType: PropTypes.string.isRequired,
14 | mountInterval: PropTypes.number,
15 | touchOnFocus: PropTypes.func,
16 | onSuccessInstall: PropTypes.func,
17 | };
18 |
19 | static defaultProps = {
20 | mountInterval: 40,
21 | touchOnFocus: () => {},
22 | onSuccessInstall: () => {},
23 | };
24 |
25 | constructor (props) {
26 | super(props);
27 | this.subscription = keyboardManagerEmitter.addListener(
28 | 'TouchDownTextField',
29 | this.touchDownTextField
30 | );
31 | }
32 |
33 | touchDownTextField = ({ reactTag }) => {
34 | if (reactTag === findNodeHandle(this.inputRef) && this.props.touchOnFocus) {
35 | this.props.touchOnFocus()
36 | }
37 | };
38 |
39 | textInputRef = () => this.inputRef;
40 |
41 | componentWillReceiveProps (nextProps) {
42 | if (nextProps.keyboardHeight !== this.props.keyboardHeight) {
43 | installKeyboard(this.props.customKeyboardType, findNodeHandle(this.inputRef), nextProps.keyboardHeight, () => {});
44 | }
45 | }
46 |
47 | componentDidMount () {
48 | setTimeout(() => installKeyboard(
49 | this.props.customKeyboardType, findNodeHandle(this.inputRef), this.props.keyboardHeight, this.props.onSuccessInstall
50 | ), this.props.mountInterval);
51 | }
52 |
53 | componentWillUnmount () {
54 | uninstall(findNodeHandle(this.inputRef));
55 | this.subscription.remove();
56 | }
57 |
58 | render () {
59 | const { ...otherProps } = this.props;
60 | return (
61 | this.inputRef = ref}
63 | autoCorrect={false}
64 | {...otherProps}
65 | />
66 | );
67 | }
68 | }
--------------------------------------------------------------------------------
/android/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/lib/TextField.android.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import PropTypes from 'prop-types';
3 | import { findNodeHandle, NativeEventEmitter, NativeModules, TextInput, Alert } from 'react-native';
4 |
5 | const { installKeyboard, uninstall, setHeight } = NativeModules.RNAllmaxKeyboard;
6 |
7 | let keyboardManagerEmitter;
8 | keyboardManagerEmitter = new NativeEventEmitter(NativeModules.RNAllmaxKeyboard);
9 |
10 |
11 | export default class TextField extends Component {
12 |
13 | static propTypes = {
14 | ...TextInput.propTypes,
15 | customKeyboardType: PropTypes.string.isRequired,
16 | mountInterval: PropTypes.number,
17 | touchOnFocus: PropTypes.func,
18 | onChangeKeyboardHeight: PropTypes.func,
19 | onSuccessInstall: PropTypes.func,
20 | keyboardHeight: PropTypes.number,
21 | };
22 |
23 | static defaultProps = {
24 | touchOnFocus: () => {},
25 | onSuccessInstall: () => {},
26 | mountInterval: 80,
27 | keyboardHeight: 0,
28 | };
29 |
30 | constructor (props) {
31 | super(props);
32 | this.subscription = keyboardManagerEmitter.addListener(
33 | 'TouchDownTextField',
34 | this.touchDownTextField
35 | );
36 | this.subscription = keyboardManagerEmitter.addListener(
37 | 'onChangeKeyboardHeight',
38 | this.onChangeKeyboardHeight
39 | );
40 | this.installInterval = null;
41 | this.installCount = 0;
42 | }
43 |
44 | touchDownTextField = ({ reactTag }) => {
45 | if (reactTag === findNodeHandle(this.inputRef) && this.props.touchOnFocus) {
46 | this.props.touchOnFocus()
47 | }
48 | };
49 |
50 | onChangeKeyboardHeight = ({ reactTag, height }) => {
51 | if (reactTag === findNodeHandle(this.inputRef) && this.props.onChangeKeyboardHeight) {
52 | this.props.onChangeKeyboardHeight(height)
53 | }
54 | };
55 |
56 | textInputRef = () => this.inputRef;
57 |
58 | componentWillReceiveProps (nextProps) {
59 | if (nextProps.keyboardHeight !== this.props.keyboardHeight) {
60 | setHeight(findNodeHandle(this.inputRef), nextProps.keyboardHeight);
61 |
62 | }
63 | }
64 |
65 | // successCallback = () => {
66 | // clearInterval(this.installInterval);
67 | // }
68 | //
69 | // errorCallback = () => {
70 | // if (this.installCount > 5) {
71 | // clearInterval(this.installInterval);
72 | // }
73 | // this.installCount++
74 | // }
75 |
76 | errorCallback = (err) => {
77 | Alert.alert(
78 | 'error',
79 | `${err}`
80 | )
81 | };
82 |
83 | componentDidMount () {
84 | // this.installInterval = setInterval(() => {
85 | // installKeyboard(this.props.customKeyboardType, findNodeHandle(this.inputRef), 0, this.successCallback, this.errorCallback)
86 | // }, 10);
87 | installKeyboard(this.props.customKeyboardType, findNodeHandle(this.inputRef), 0, this.props.onSuccessInstall, this.errorCallback)
88 | }
89 |
90 | componentWillUnmount () {
91 | uninstall(findNodeHandle(this.inputRef));
92 | this.subscription.remove();
93 | }
94 |
95 | render () {
96 | const { ...otherProps } = this.props;
97 | return (
98 | this.inputRef = ref}
100 | autoCorrect={false}
101 | {...otherProps}
102 | />
103 | );
104 | }
105 | }
106 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 | # react-native-allmax-keyboard
3 |
4 | ## Getting started
5 |
6 | `$ npm install react-native-allmax-keyboard --save`
7 |
8 | ### Mostly automatic installation
9 |
10 | `$ react-native link react-native-allmax-keyboard`
11 |
12 | ### Manual installation
13 |
14 |
15 | #### iOS
16 |
17 | 1. In XCode, in the project navigator, right click `Libraries` ➜ `Add Files to [your project's name]`
18 | 2. Go to `node_modules` ➜ `react-native-allmax-keyboard` and add `RNAllmaxKeyboard.xcodeproj`
19 | 3. In XCode, in the project navigator, select your project. Add `libRNAllmaxKeyboard.a` to your project's `Build Phases` ➜ `Link Binary With Libraries`
20 | 4. Run your project (`Cmd+R`)<
21 |
22 | #### Android
23 |
24 | 1. Open up `android/app/src/main/java/[...]/MainActivity.java`
25 | - Add `import com.reactlibrary.RNAllmaxKeyboardPackage;` to the imports at the top of the file
26 | - Add `new RNAllmaxKeyboardPackage()` to the list returned by the `getPackages()` method
27 | 2. Append the following lines to `android/settings.gradle`:
28 | ```
29 | include ':react-native-allmax-keyboard'
30 | project(':react-native-allmax-keyboard').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-allmax-keyboard/android')
31 | ```
32 | 3. Insert the following lines inside the dependencies block in `android/app/build.gradle`:
33 | ```
34 | compile project(':react-native-allmax-keyboard')
35 | ```
36 |
37 | ## Usage
38 | ```javascript
39 | import { TextField, setHeight } from 'react-native-allmax-keyboard';
40 |
41 | ...
42 | {
44 | this.scoutInput = ref;
45 | }}
46 | onSuccessInstall={() => {
47 | this.setState({ androidPreloader: false });
48 | }}
49 | keyboardHeight={keyboardHeight}
50 | mountInterval={80}
51 | customKeyboardType={'NumPad'}
52 | placeholder="Barcode"
53 | returnKeyType="done"
54 | selectionColor={'rgba(0, 0, 0, .5)'}
55 | spellCheck={false}
56 | onSubmitEditing={() => {
57 | setHeight(findNodeHandle(this.scoutInput.textInputRef()), 0);
58 | if (isFetched !== 1) {
59 | return fetchByBarcode();
60 | } else if (isFetched === 1) {
61 | return setBarcode('');
62 | }
63 | return null;
64 | }}
65 | onChangeText={(newBarcode) => {
66 | setBarcode(newBarcode);
67 | }}
68 | value={newBarcode}
69 | style={styles.scan_textInput}
70 | touchOnFocus={() => {
71 | if (keyboardHeight === 0 && !this.state.androidPreloader) {
72 | setKeyboardHeight(this.keyboardHeight);
73 | }
74 | }}
75 | onChangeKeyboardHeight={(height) => {
76 | if (keyboardHeight !== height) {
77 | setKeyboardHeight(height);
78 | }
79 | }}
80 | underlineColorAndroid="transparent"
81 | blurOnSubmit={!externalScanner}
82 | dismissKeyboardAction={setKeyboardHeight}
83 | />
84 | ...
85 |
86 | ```
87 |
88 | ## Variables
89 | ```
90 | touchOnFocus: () => {}, // Input is touched
91 | onSuccessInstall: () => {}, // Callback when keyboard is mounted
92 | mountInterval: 80, // Interval to mount keyboard, only for iOS
93 | keyboardHeight: 0, // Keyboard height, default is 0
94 | ```
95 |
96 | ## Functions to use
97 | ```
98 | registerKeyboard, // Register in root container
99 | TextField, // TextInput
100 | backSpace, // Delete action
101 | insertText, // Insert action
102 | done, // Done action
103 | clear, // Clear all nodes, only for Android
104 | installKeyboard, // Don't use it
105 | switchSystemKeyboard, // Switch to system keyboard action
106 | setHeight // Set keyboard height
107 | ```
108 |
109 |
--------------------------------------------------------------------------------
/android/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # Attempt to set APP_HOME
46 | # Resolve links: $0 may be a link
47 | PRG="$0"
48 | # Need this for relative symlinks.
49 | while [ -h "$PRG" ] ; do
50 | ls=`ls -ld "$PRG"`
51 | link=`expr "$ls" : '.*-> \(.*\)$'`
52 | if expr "$link" : '/.*' > /dev/null; then
53 | PRG="$link"
54 | else
55 | PRG=`dirname "$PRG"`"/$link"
56 | fi
57 | done
58 | SAVED="`pwd`"
59 | cd "`dirname \"$PRG\"`/" >/dev/null
60 | APP_HOME="`pwd -P`"
61 | cd "$SAVED" >/dev/null
62 |
63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
64 |
65 | # Determine the Java command to use to start the JVM.
66 | if [ -n "$JAVA_HOME" ] ; then
67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
68 | # IBM's JDK on AIX uses strange locations for the executables
69 | JAVACMD="$JAVA_HOME/jre/sh/java"
70 | else
71 | JAVACMD="$JAVA_HOME/bin/java"
72 | fi
73 | if [ ! -x "$JAVACMD" ] ; then
74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
75 |
76 | Please set the JAVA_HOME variable in your environment to match the
77 | location of your Java installation."
78 | fi
79 | else
80 | JAVACMD="java"
81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
82 |
83 | Please set the JAVA_HOME variable in your environment to match the
84 | location of your Java installation."
85 | fi
86 |
87 | # Increase the maximum file descriptors if we can.
88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
89 | MAX_FD_LIMIT=`ulimit -H -n`
90 | if [ $? -eq 0 ] ; then
91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
92 | MAX_FD="$MAX_FD_LIMIT"
93 | fi
94 | ulimit -n $MAX_FD
95 | if [ $? -ne 0 ] ; then
96 | warn "Could not set maximum file descriptor limit: $MAX_FD"
97 | fi
98 | else
99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
100 | fi
101 | fi
102 |
103 | # For Darwin, add options to specify how the application appears in the dock
104 | if $darwin; then
105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
106 | fi
107 |
108 | # For Cygwin, switch paths to Windows format before running java
109 | if $cygwin ; then
110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
112 | JAVACMD=`cygpath --unix "$JAVACMD"`
113 |
114 | # We build the pattern for arguments to be converted via cygpath
115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
116 | SEP=""
117 | for dir in $ROOTDIRSRAW ; do
118 | ROOTDIRS="$ROOTDIRS$SEP$dir"
119 | SEP="|"
120 | done
121 | OURCYGPATTERN="(^($ROOTDIRS))"
122 | # Add a user-defined pattern to the cygpath arguments
123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
125 | fi
126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
127 | i=0
128 | for arg in "$@" ; do
129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
131 |
132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
134 | else
135 | eval `echo args$i`="\"$arg\""
136 | fi
137 | i=$((i+1))
138 | done
139 | case $i in
140 | (0) set -- ;;
141 | (1) set -- "$args0" ;;
142 | (2) set -- "$args0" "$args1" ;;
143 | (3) set -- "$args0" "$args1" "$args2" ;;
144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
150 | esac
151 | fi
152 |
153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
154 | function splitJvmOpts() {
155 | JVM_OPTS=("$@")
156 | }
157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
159 |
160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
161 |
--------------------------------------------------------------------------------
/ios/RNAllmaxKeyboard.m:
--------------------------------------------------------------------------------
1 | #import "RNAllmaxKeyboard.h"
2 | #import
3 | #import
4 | #import
5 | #import
6 | #import
7 |
8 | @implementation RNAllmaxKeyboard
9 |
10 | @synthesize bridge = _bridge;
11 |
12 | - (dispatch_queue_t)methodQueue
13 | {
14 | return dispatch_get_main_queue();
15 | }
16 |
17 | RCT_EXPORT_MODULE(RNAllmaxKeyboard)
18 |
19 | RCT_EXPORT_METHOD(installKeyboard:(nonnull NSString *)keyboardType
20 | forTextFieldbyReactTag:(nonnull NSNumber *)reactTag
21 | withHeight:(nonnull NSNumber *)keyboardHeight
22 | number:(RCTResponseSenderBlock)callback) {
23 | RCTBaseTextInputView *textInputView = (RCTBaseTextInputView*)[_bridge.uiManager viewForReactTag:reactTag];
24 | UITextField* textField = (UITextField*)[textInputView backedTextInputView];
25 | UIView* keyboardView = [[RCTRootView alloc]
26 | initWithBridge:[self.bridge valueForKey:@"parentBridge"]
27 | moduleName:@"AllMaxKeyboard"
28 | initialProperties:@{
29 | @"tag": reactTag,
30 | @"keyboardType": keyboardType
31 | }
32 | ];
33 |
34 | [keyboardView setFrame:CGRectMake(0, 0, 0, [keyboardHeight floatValue])];
35 | [textField setInputView:keyboardView];
36 | [textField setReturnKeyType:UIReturnKeyDone];
37 | [textField reloadInputViews];
38 | [textField addTarget:self action:@selector(touchDownTextField:) forControlEvents:UIControlEventTouchDown];
39 | callback(@[[NSNull null], [NSNumber numberWithInt:(10)]]);
40 | }
41 |
42 | RCT_EXPORT_METHOD(uninstall:(nonnull NSNumber *)reactTag)
43 | {
44 | RCTBaseTextInputView *textInputView = (RCTBaseTextInputView*)[_bridge.uiManager viewForReactTag:reactTag];
45 | UITextField* textField = (UITextField*)[textInputView backedTextInputView];
46 |
47 | [textField setInputView:nil];
48 | [textField setInputAccessoryView: nil];
49 | [textField reloadInputViews];
50 | }
51 |
52 | RCT_EXPORT_METHOD(setHeight:(nonnull NSNumber *)keyboardHeight
53 | forTextFieldbyReactTag:(nonnull NSNumber *)reactTag) {
54 | RCTBaseTextInputView *textInputView = (RCTBaseTextInputView*)[_bridge.uiManager viewForReactTag:reactTag];
55 | UITextField* textField = (UITextField*)[textInputView backedTextInputView];
56 | if (textField.inputView != nil) {
57 | [textField.inputView setFrame:CGRectMake(0, 0, 0, [keyboardHeight floatValue])];
58 | // [textField reloadInputViews];
59 | }
60 | }
61 |
62 | RCT_EXPORT_METHOD(insertText:(nonnull NSNumber *)reactTag withText:(NSString*)text) {
63 | RCTBaseTextInputView *textInputView = (RCTBaseTextInputView*)[_bridge.uiManager viewForReactTag:reactTag];
64 | UITextField* textField = (UITextField*)[textInputView backedTextInputView];
65 | NSLog(@"%@", textField.inputAccessoryView);
66 | UIView* accessoryView = textField.inputAccessoryView;
67 | [textField replaceRange:textField.selectedTextRange withText:text];
68 | [textField setInputAccessoryView:accessoryView];
69 | [textField reloadInputViews];
70 | }
71 |
72 | RCT_EXPORT_METHOD(backSpace:(nonnull NSNumber *)reactTag) {
73 | RCTBaseTextInputView *textInputView = (RCTBaseTextInputView*)[_bridge.uiManager viewForReactTag:reactTag];
74 | UITextField* textField = (UITextField*)[textInputView backedTextInputView];
75 |
76 | UITextRange* range = textField.selectedTextRange;
77 | if ([textField comparePosition:range.start toPosition:range.end] == 0) {
78 | range = [textField textRangeFromPosition:[textField positionFromPosition:range.start offset:-1] toPosition:range.start];
79 | }
80 | [textField replaceRange:range withText:@""];
81 | }
82 |
83 | RCT_EXPORT_METHOD(doDelete:(nonnull NSNumber *)reactTag) {
84 | RCTBaseTextInputView *textInputView = (RCTBaseTextInputView*)[_bridge.uiManager viewForReactTag:reactTag];
85 | UITextField* textField = (UITextField*)[textInputView backedTextInputView];
86 |
87 | UITextRange* range = textField.selectedTextRange;
88 | if ([textField comparePosition:range.start toPosition:range.end] == 0) {
89 | range = [textField textRangeFromPosition:range.start toPosition:[textField positionFromPosition: range.start offset: 1]];
90 | }
91 | [textField replaceRange:range withText:@""];
92 | }
93 |
94 | RCT_EXPORT_METHOD(moveLeft:(nonnull NSNumber *)reactTag) {
95 | RCTBaseTextInputView *textInputView = (RCTBaseTextInputView*)[_bridge.uiManager viewForReactTag:reactTag];
96 | UITextField* textField = (UITextField*)[textInputView backedTextInputView];
97 |
98 | UITextRange* range = textField.selectedTextRange;
99 | UITextPosition* position = range.start;
100 |
101 | if ([textField comparePosition:range.start toPosition:range.end] == 0) {
102 | position = [textField positionFromPosition: position offset: -1];
103 | }
104 |
105 | textField.selectedTextRange = [textField textRangeFromPosition: position toPosition:position];
106 | }
107 |
108 | RCT_EXPORT_METHOD(moveRight:(nonnull NSNumber *)reactTag) {
109 | RCTBaseTextInputView *textInputView = (RCTBaseTextInputView*)[_bridge.uiManager viewForReactTag:reactTag];
110 | UITextField* textField = (UITextField*)[textInputView backedTextInputView];
111 |
112 | UITextRange* range = textField.selectedTextRange;
113 | UITextPosition* position = range.end;
114 |
115 | if ([textField comparePosition:range.start toPosition:range.end] == 0) {
116 | position = [textField positionFromPosition: position offset: 1];
117 | }
118 |
119 | textField.selectedTextRange = [textField textRangeFromPosition: position toPosition:position];
120 | }
121 |
122 | RCT_EXPORT_METHOD(switchSystemKeyboard:(nonnull NSNumber*) reactTag) {
123 | RCTBaseTextInputView *textInputView = (RCTBaseTextInputView*)[_bridge.uiManager viewForReactTag:reactTag];
124 | UITextField* textField = (UITextField*)[textInputView backedTextInputView];
125 |
126 | UIView* inputView = textField.inputView;
127 | textField.inputView = nil;
128 | [textField reloadInputViews];
129 | textField.inputView = inputView;
130 | }
131 |
132 | RCT_EXPORT_METHOD(done:(nonnull NSNumber*) reactTag) {
133 | RCTBaseTextInputView *textInputView = (RCTBaseTextInputView*)[_bridge.uiManager viewForReactTag:reactTag];
134 | UITextField* textField = (UITextField*)[textInputView backedTextInputView];
135 |
136 | [textField sendActionsForControlEvents:UIControlEventEditingDidEndOnExit];
137 | [textField endEditing:YES];
138 | // [textField resignFirstResponder];
139 | // [textField becomeFirstResponder];
140 |
141 |
142 | }
143 |
144 | - (void)touchDownTextField: (UITextField *)textField {
145 | NSNumber* reactTag = [textField.superview valueForKey:@"reactTag"];
146 | [[NSNotificationCenter defaultCenter] postNotificationName:@"RNAllMaxKeyboardTouchDownTextField" object:textField userInfo:@{@"reactTag": reactTag}];
147 | }
148 |
149 |
150 | @end
151 |
--------------------------------------------------------------------------------
/ios/RNAllmaxKeyboard.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | B3E7B58A1CC2AC0600A0062D /* RNAllmaxKeyboard.m in Sources */ = {isa = PBXBuildFile; fileRef = B3E7B5891CC2AC0600A0062D /* RNAllmaxKeyboard.m */; };
11 | CE251E7A1F555A90002FA6DA /* RNAllmaxKeyboardEventEmitter.m in Sources */ = {isa = PBXBuildFile; fileRef = CE251E781F555A90002FA6DA /* RNAllmaxKeyboardEventEmitter.m */; };
12 | /* End PBXBuildFile section */
13 |
14 | /* Begin PBXCopyFilesBuildPhase section */
15 | 58B511D91A9E6C8500147676 /* CopyFiles */ = {
16 | isa = PBXCopyFilesBuildPhase;
17 | buildActionMask = 2147483647;
18 | dstPath = "include/$(PRODUCT_NAME)";
19 | dstSubfolderSpec = 16;
20 | files = (
21 | );
22 | runOnlyForDeploymentPostprocessing = 0;
23 | };
24 | /* End PBXCopyFilesBuildPhase section */
25 |
26 | /* Begin PBXFileReference section */
27 | 134814201AA4EA6300B7C361 /* libRNAllmaxKeyboard.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libRNAllmaxKeyboard.a; sourceTree = BUILT_PRODUCTS_DIR; };
28 | B3E7B5881CC2AC0600A0062D /* RNAllmaxKeyboard.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNAllmaxKeyboard.h; sourceTree = ""; };
29 | B3E7B5891CC2AC0600A0062D /* RNAllmaxKeyboard.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNAllmaxKeyboard.m; sourceTree = ""; };
30 | CE251E781F555A90002FA6DA /* RNAllmaxKeyboardEventEmitter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNAllmaxKeyboardEventEmitter.m; sourceTree = ""; };
31 | CE251E791F555A90002FA6DA /* RNAllmaxKeyboardEventEmitter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNAllmaxKeyboardEventEmitter.h; sourceTree = ""; };
32 | /* End PBXFileReference section */
33 |
34 | /* Begin PBXFrameworksBuildPhase section */
35 | 58B511D81A9E6C8500147676 /* Frameworks */ = {
36 | isa = PBXFrameworksBuildPhase;
37 | buildActionMask = 2147483647;
38 | files = (
39 | );
40 | runOnlyForDeploymentPostprocessing = 0;
41 | };
42 | /* End PBXFrameworksBuildPhase section */
43 |
44 | /* Begin PBXGroup section */
45 | 134814211AA4EA7D00B7C361 /* Products */ = {
46 | isa = PBXGroup;
47 | children = (
48 | 134814201AA4EA6300B7C361 /* libRNAllmaxKeyboard.a */,
49 | );
50 | name = Products;
51 | sourceTree = "";
52 | };
53 | 58B511D21A9E6C8500147676 = {
54 | isa = PBXGroup;
55 | children = (
56 | CE251E781F555A90002FA6DA /* RNAllmaxKeyboardEventEmitter.m */,
57 | CE251E791F555A90002FA6DA /* RNAllmaxKeyboardEventEmitter.h */,
58 | B3E7B5881CC2AC0600A0062D /* RNAllmaxKeyboard.h */,
59 | B3E7B5891CC2AC0600A0062D /* RNAllmaxKeyboard.m */,
60 | 134814211AA4EA7D00B7C361 /* Products */,
61 | );
62 | sourceTree = "";
63 | };
64 | /* End PBXGroup section */
65 |
66 | /* Begin PBXNativeTarget section */
67 | 58B511DA1A9E6C8500147676 /* RNAllmaxKeyboard */ = {
68 | isa = PBXNativeTarget;
69 | buildConfigurationList = 58B511EF1A9E6C8500147676 /* Build configuration list for PBXNativeTarget "RNAllmaxKeyboard" */;
70 | buildPhases = (
71 | 58B511D71A9E6C8500147676 /* Sources */,
72 | 58B511D81A9E6C8500147676 /* Frameworks */,
73 | 58B511D91A9E6C8500147676 /* CopyFiles */,
74 | );
75 | buildRules = (
76 | );
77 | dependencies = (
78 | );
79 | name = RNAllmaxKeyboard;
80 | productName = RCTDataManager;
81 | productReference = 134814201AA4EA6300B7C361 /* libRNAllmaxKeyboard.a */;
82 | productType = "com.apple.product-type.library.static";
83 | };
84 | /* End PBXNativeTarget section */
85 |
86 | /* Begin PBXProject section */
87 | 58B511D31A9E6C8500147676 /* Project object */ = {
88 | isa = PBXProject;
89 | attributes = {
90 | LastUpgradeCheck = 0610;
91 | ORGANIZATIONNAME = Facebook;
92 | TargetAttributes = {
93 | 58B511DA1A9E6C8500147676 = {
94 | CreatedOnToolsVersion = 6.1.1;
95 | };
96 | };
97 | };
98 | buildConfigurationList = 58B511D61A9E6C8500147676 /* Build configuration list for PBXProject "RNAllmaxKeyboard" */;
99 | compatibilityVersion = "Xcode 3.2";
100 | developmentRegion = English;
101 | hasScannedForEncodings = 0;
102 | knownRegions = (
103 | en,
104 | );
105 | mainGroup = 58B511D21A9E6C8500147676;
106 | productRefGroup = 58B511D21A9E6C8500147676;
107 | projectDirPath = "";
108 | projectRoot = "";
109 | targets = (
110 | 58B511DA1A9E6C8500147676 /* RNAllmaxKeyboard */,
111 | );
112 | };
113 | /* End PBXProject section */
114 |
115 | /* Begin PBXSourcesBuildPhase section */
116 | 58B511D71A9E6C8500147676 /* Sources */ = {
117 | isa = PBXSourcesBuildPhase;
118 | buildActionMask = 2147483647;
119 | files = (
120 | B3E7B58A1CC2AC0600A0062D /* RNAllmaxKeyboard.m in Sources */,
121 | CE251E7A1F555A90002FA6DA /* RNAllmaxKeyboardEventEmitter.m in Sources */,
122 | );
123 | runOnlyForDeploymentPostprocessing = 0;
124 | };
125 | /* End PBXSourcesBuildPhase section */
126 |
127 | /* Begin XCBuildConfiguration section */
128 | 58B511ED1A9E6C8500147676 /* Debug */ = {
129 | isa = XCBuildConfiguration;
130 | buildSettings = {
131 | ALWAYS_SEARCH_USER_PATHS = NO;
132 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
133 | CLANG_CXX_LIBRARY = "libc++";
134 | CLANG_ENABLE_MODULES = YES;
135 | CLANG_ENABLE_OBJC_ARC = YES;
136 | CLANG_WARN_BOOL_CONVERSION = YES;
137 | CLANG_WARN_CONSTANT_CONVERSION = YES;
138 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
139 | CLANG_WARN_EMPTY_BODY = YES;
140 | CLANG_WARN_ENUM_CONVERSION = YES;
141 | CLANG_WARN_INT_CONVERSION = YES;
142 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
143 | CLANG_WARN_UNREACHABLE_CODE = YES;
144 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
145 | COPY_PHASE_STRIP = NO;
146 | ENABLE_STRICT_OBJC_MSGSEND = YES;
147 | GCC_C_LANGUAGE_STANDARD = gnu99;
148 | GCC_DYNAMIC_NO_PIC = NO;
149 | GCC_OPTIMIZATION_LEVEL = 0;
150 | GCC_PREPROCESSOR_DEFINITIONS = (
151 | "DEBUG=1",
152 | "$(inherited)",
153 | );
154 | GCC_SYMBOLS_PRIVATE_EXTERN = NO;
155 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
156 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
157 | GCC_WARN_UNDECLARED_SELECTOR = YES;
158 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
159 | GCC_WARN_UNUSED_FUNCTION = YES;
160 | GCC_WARN_UNUSED_VARIABLE = YES;
161 | IPHONEOS_DEPLOYMENT_TARGET = 7.0;
162 | MTL_ENABLE_DEBUG_INFO = YES;
163 | ONLY_ACTIVE_ARCH = YES;
164 | SDKROOT = iphoneos;
165 | };
166 | name = Debug;
167 | };
168 | 58B511EE1A9E6C8500147676 /* Release */ = {
169 | isa = XCBuildConfiguration;
170 | buildSettings = {
171 | ALWAYS_SEARCH_USER_PATHS = NO;
172 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
173 | CLANG_CXX_LIBRARY = "libc++";
174 | CLANG_ENABLE_MODULES = YES;
175 | CLANG_ENABLE_OBJC_ARC = YES;
176 | CLANG_WARN_BOOL_CONVERSION = YES;
177 | CLANG_WARN_CONSTANT_CONVERSION = YES;
178 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
179 | CLANG_WARN_EMPTY_BODY = YES;
180 | CLANG_WARN_ENUM_CONVERSION = YES;
181 | CLANG_WARN_INT_CONVERSION = YES;
182 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
183 | CLANG_WARN_UNREACHABLE_CODE = YES;
184 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
185 | COPY_PHASE_STRIP = YES;
186 | ENABLE_NS_ASSERTIONS = NO;
187 | ENABLE_STRICT_OBJC_MSGSEND = YES;
188 | GCC_C_LANGUAGE_STANDARD = gnu99;
189 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
190 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
191 | GCC_WARN_UNDECLARED_SELECTOR = YES;
192 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
193 | GCC_WARN_UNUSED_FUNCTION = YES;
194 | GCC_WARN_UNUSED_VARIABLE = YES;
195 | IPHONEOS_DEPLOYMENT_TARGET = 7.0;
196 | MTL_ENABLE_DEBUG_INFO = NO;
197 | SDKROOT = iphoneos;
198 | VALIDATE_PRODUCT = YES;
199 | };
200 | name = Release;
201 | };
202 | 58B511F01A9E6C8500147676 /* Debug */ = {
203 | isa = XCBuildConfiguration;
204 | buildSettings = {
205 | HEADER_SEARCH_PATHS = (
206 | "$(inherited)",
207 | /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
208 | "$(SRCROOT)/../../../React/**",
209 | "$(SRCROOT)/../../react-native/React/**",
210 | );
211 | LIBRARY_SEARCH_PATHS = "$(inherited)";
212 | OTHER_LDFLAGS = "-ObjC";
213 | PRODUCT_NAME = RNAllmaxKeyboard;
214 | SKIP_INSTALL = YES;
215 | };
216 | name = Debug;
217 | };
218 | 58B511F11A9E6C8500147676 /* Release */ = {
219 | isa = XCBuildConfiguration;
220 | buildSettings = {
221 | HEADER_SEARCH_PATHS = (
222 | "$(inherited)",
223 | /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
224 | "$(SRCROOT)/../../../React/**",
225 | "$(SRCROOT)/../../react-native/React/**",
226 | );
227 | LIBRARY_SEARCH_PATHS = "$(inherited)";
228 | OTHER_LDFLAGS = "-ObjC";
229 | PRODUCT_NAME = RNAllmaxKeyboard;
230 | SKIP_INSTALL = YES;
231 | };
232 | name = Release;
233 | };
234 | /* End XCBuildConfiguration section */
235 |
236 | /* Begin XCConfigurationList section */
237 | 58B511D61A9E6C8500147676 /* Build configuration list for PBXProject "RNAllmaxKeyboard" */ = {
238 | isa = XCConfigurationList;
239 | buildConfigurations = (
240 | 58B511ED1A9E6C8500147676 /* Debug */,
241 | 58B511EE1A9E6C8500147676 /* Release */,
242 | );
243 | defaultConfigurationIsVisible = 0;
244 | defaultConfigurationName = Release;
245 | };
246 | 58B511EF1A9E6C8500147676 /* Build configuration list for PBXNativeTarget "RNAllmaxKeyboard" */ = {
247 | isa = XCConfigurationList;
248 | buildConfigurations = (
249 | 58B511F01A9E6C8500147676 /* Debug */,
250 | 58B511F11A9E6C8500147676 /* Release */,
251 | );
252 | defaultConfigurationIsVisible = 0;
253 | defaultConfigurationName = Release;
254 | };
255 | /* End XCConfigurationList section */
256 | };
257 | rootObject = 58B511D31A9E6C8500147676 /* Project object */;
258 | }
259 |
--------------------------------------------------------------------------------
/android/src/main/java/com/facebook/react/uimanager/RNAllmaxKeyboardModule.java:
--------------------------------------------------------------------------------
1 | package com.facebook.react.uimanager;
2 |
3 | import android.app.Activity;
4 | import android.os.Bundle;
5 | import android.os.Handler;
6 | import android.os.Looper;
7 | import android.os.ResultReceiver;
8 | import android.support.annotation.Nullable;
9 | import android.util.Log;
10 | import android.view.KeyEvent;
11 | import android.view.View;
12 | import android.view.ViewGroup;
13 | import android.view.inputmethod.InputMethodManager;
14 | import android.widget.EditText;
15 | import android.widget.RelativeLayout;
16 |
17 | import com.facebook.react.ReactApplication;
18 | import com.facebook.react.ReactRootView;
19 | import com.facebook.react.bridge.Arguments;
20 | import com.facebook.react.bridge.Callback;
21 | import com.facebook.react.bridge.ReactApplicationContext;
22 | import com.facebook.react.bridge.ReactContext;
23 | import com.facebook.react.bridge.ReactContextBaseJavaModule;
24 | import com.facebook.react.bridge.ReactMethod;
25 | import com.facebook.react.bridge.WritableMap;
26 | import com.facebook.react.modules.core.DeviceEventManagerModule;
27 | import com.facebook.react.views.textinput.ReactEditText;
28 | import com.facebook.react.ReactInstanceManager;
29 |
30 | import java.lang.reflect.Method;
31 | import java.util.Map;
32 | import java.util.concurrent.ConcurrentHashMap;
33 |
34 | public class RNAllmaxKeyboardModule extends ReactContextBaseJavaModule {
35 | private static final String TAG = "RNAllmaxKeyboardModule";
36 | private static final int DEFAULT_TIMEOUT = 300;
37 | private final ReactApplicationContext reactContext;
38 |
39 | private Method setShowSoftInputOnFocusMethod;
40 | private Method setSoftInputShownOnFocusMethod;
41 |
42 | private ConcurrentHashMap edits = new ConcurrentHashMap();
43 | private ConcurrentHashMap keyboardLayouts = new ConcurrentHashMap();
44 | private Handler mHandler = new Handler(Looper.getMainLooper());
45 |
46 | public RNAllmaxKeyboardModule(ReactApplicationContext reactContext) {
47 | super(reactContext);
48 | this.reactContext = reactContext;
49 | initReflectMethod();
50 | }
51 |
52 | private void initReflectMethod () {
53 | Class cls = ReactEditText.class;
54 | try {
55 | setShowSoftInputOnFocusMethod = cls.getMethod("setShowSoftInputOnFocus", boolean.class);
56 | setShowSoftInputOnFocusMethod.setAccessible(true);
57 | } catch (Exception e) {
58 | Log.i(TAG, "initReflectMethod 1 err=" + e.getMessage());
59 | }
60 | try {
61 | setSoftInputShownOnFocusMethod = cls.getMethod("setSoftInputShownOnFocus", boolean.class);
62 | setSoftInputShownOnFocusMethod.setAccessible(true);
63 | } catch (Exception e) {
64 | Log.i(TAG, "initReflectMethod 2 err=" + e.getMessage());
65 | }
66 | }
67 |
68 | private ReactEditText getEditById(int id) throws IllegalViewOperationException {
69 | UIViewOperationQueue uii = this.getReactApplicationContext().getNativeModule(UIManagerModule.class).getUIImplementation().getUIViewOperationQueue();
70 | return (ReactEditText) uii.getNativeViewHierarchyManager().resolveView(id);
71 | }
72 |
73 | private void showKeyboard (final Activity activity, final int tag) {
74 | final ResultReceiver receiver = new ResultReceiver(mHandler) {
75 | @Override
76 | protected void onReceiveResult(int resultCode, Bundle resultData) {
77 | if (resultCode == InputMethodManager.RESULT_UNCHANGED_HIDDEN || resultCode == InputMethodManager.RESULT_HIDDEN) {
78 | mHandler.postDelayed(new Runnable() {
79 | @Override
80 | public void run() {
81 | final ReactEditText edit = edits.get(String.valueOf(tag));
82 | final RelativeLayout keyboardLayout = keyboardLayouts.get(String.valueOf(tag));
83 |
84 | if (keyboardLayout != null && edit != null && edit.isFocused()) {
85 | if (keyboardLayout.getParent() != null) {
86 | ((ViewGroup)keyboardLayout.getParent()).removeView(keyboardLayout);
87 | }
88 | activity.addContentView(keyboardLayout, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
89 | }
90 | }
91 | }, 5);
92 | }
93 | }
94 | };
95 |
96 | mHandler.post(new Runnable() {
97 | @Override
98 | public void run() {
99 | InputMethodManager im = ((InputMethodManager) getReactApplicationContext().getSystemService(Activity.INPUT_METHOD_SERVICE));
100 | im.hideSoftInputFromWindow(activity.getWindow().getDecorView().getWindowToken(), 0, receiver);
101 | }
102 | });
103 | }
104 |
105 | public void disableShowSoftInput(ReactEditText editText) {
106 | try {
107 | setShowSoftInputOnFocusMethod.invoke(editText, false);
108 | } catch (Exception e) {
109 | Log.i(TAG, "disableShowSoftInput 1 err=" + e.getMessage());
110 | }
111 |
112 | try {
113 | setSoftInputShownOnFocusMethod.invoke(editText, false);
114 | } catch (Exception e) {
115 | Log.i(TAG, "disableShowSoftInput 2 err=" + e.getMessage());
116 | }
117 | }
118 |
119 | private void setEditTextTagAndListener (final ReactEditText edit, final int tag, final String type, final int keyboardHeight) {
120 | final Activity activity = getCurrentActivity();
121 | if (edit == null || activity == null) {
122 | Log.e(TAG, "setEditTextListener error null, edit=" + edit);
123 | return;
124 | }
125 | disableShowSoftInput(edit);
126 | final RelativeLayout keyboardLayout = createCustomKeyboard(activity, tag, type, keyboardHeight);
127 |
128 | edits.put(String.valueOf(tag), edit);
129 | keyboardLayouts.put(String.valueOf(tag), keyboardLayout);
130 |
131 | final View.OnFocusChangeListener oldOnFocusChangeListener = edit.getOnFocusChangeListener();
132 | edit.setOnFocusChangeListener(new View.OnFocusChangeListener() {
133 | @Override
134 | public void onFocusChange(final View v, boolean hasFocus) {
135 | Log.i(TAG, "onFocusChange hasFocus=" + hasFocus );
136 | if (hasFocus) {
137 | showKeyboard(activity, tag);
138 | } else {
139 | if (keyboardLayout.getParent() != null) {
140 | ((ViewGroup) keyboardLayout.getParent()).removeView(keyboardLayout);
141 | }
142 | }
143 | oldOnFocusChangeListener.onFocusChange(v, hasFocus);
144 | }
145 | });
146 |
147 | edit.setOnClickListener(new View.OnClickListener(){
148 | @Override
149 | public void onClick(final View v) {
150 | WritableMap params = Arguments.createMap();
151 | params.putInt("reactTag", tag);
152 | sendEvent(reactContext, "TouchDownTextField", params);
153 | }
154 | });
155 | }
156 |
157 | @ReactMethod
158 | public void installKeyboard(final String type, final int tag, final int keyboardHeight, final @Nullable Callback successCallback, final @Nullable Callback errorCallback) {
159 | mHandler.post(new Runnable() {
160 | @Override
161 | public void run() {
162 | try {
163 | ReactEditText edit = getEditById(tag);
164 | setEditTextTagAndListener(edit, tag, type, keyboardHeight);
165 | if (successCallback != null) {
166 | successCallback.invoke();
167 | }
168 | } catch (IllegalViewOperationException e) {
169 | mHandler.postDelayed(new Runnable() {
170 | @Override
171 | public void run() {
172 | try {
173 | final ReactEditText edit = getEditById(tag);
174 | setEditTextTagAndListener(edit, tag, type, keyboardHeight);
175 | if (successCallback != null) {
176 | successCallback.invoke();
177 | }
178 | } catch (IllegalViewOperationException err) {
179 | Log.e(TAG, err.toString());
180 | if (errorCallback != null) {
181 | errorCallback.invoke(err.getMessage());
182 | }
183 | }
184 | }
185 | }, DEFAULT_TIMEOUT);
186 | }
187 | }
188 | });
189 | }
190 |
191 | private RelativeLayout createCustomKeyboard(Activity activity, int tag, String type, int keyboardHeight) {
192 | RelativeLayout keyboardLayout = new RelativeLayout(activity);
193 | ReactRootView rootView = new ReactRootView(this.getReactApplicationContext());
194 |
195 | Bundle bundle = new Bundle();
196 | bundle.putInt("tag", tag);
197 | bundle.putString("keyboardType", type);
198 | rootView.startReactApplication(
199 | ((ReactApplication) activity.getApplication()).getReactNativeHost().getReactInstanceManager(),
200 | "AllMaxKeyboard",
201 | bundle);
202 |
203 | final float scale = activity.getResources().getDisplayMetrics().density;
204 | RelativeLayout.LayoutParams lParams = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, Math.round(keyboardHeight * scale));
205 | lParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM, RelativeLayout.TRUE);
206 | if (rootView.getParent() != null) {
207 | ((ViewGroup)rootView.getParent()).removeView(rootView);
208 | }
209 | keyboardLayout.addView(rootView, lParams);
210 |
211 | WritableMap params = Arguments.createMap();
212 | params.putInt("reactTag", tag);
213 | params.putInt("height", keyboardHeight);
214 | sendEvent(reactContext, "onChangeKeyboardHeight", params);
215 |
216 | return keyboardLayout;
217 | }
218 |
219 | @ReactMethod
220 | public void uninstall(final int tag) {
221 | Log.v(TAG, String.format("uninstall: %d", tag));
222 | // mHandler.removeCallbacksAndMessages(null);
223 | mHandler.post(new Runnable() {
224 | @Override
225 | public void run() {
226 | final Activity activity = getCurrentActivity();
227 |
228 | if (!edits.containsKey(String.valueOf(tag))) {
229 | return;
230 | }
231 |
232 | ReactEditText edit = edits.get(String.valueOf(tag));
233 | RelativeLayout keyboardLayout = keyboardLayouts.get(String.valueOf(tag));
234 | ReactRootView rootView = (ReactRootView)keyboardLayout.getChildAt(0);
235 | edit.setOnFocusChangeListener(null);
236 | edit.setOnClickListener(null);
237 |
238 | if (keyboardLayout != null && keyboardLayout.getParent() != null) {
239 | ((ViewGroup) keyboardLayout.getParent()).removeView(keyboardLayout);
240 | }
241 |
242 | if (rootView != null/* && activity != null*/) {
243 | rootView.unmountReactApplication();
244 | // ((ReactApplication) activity.getApplication()).getReactNativeHost().getReactInstanceManager().detachRootView(rootView);
245 | }
246 | edits.remove(String.valueOf(tag));
247 | keyboardLayouts.remove(String.valueOf(tag));
248 | }
249 | });
250 | }
251 |
252 | @ReactMethod
253 | public void clear(final Callback successCallback, final Callback errorCallback) {
254 | mHandler.removeCallbacksAndMessages(null);
255 | mHandler.post(new Runnable() {
256 | @Override
257 | public void run() {
258 | try {
259 | for(Map.Entry entry : keyboardLayouts.entrySet()) {
260 | RelativeLayout keyboardLayout = entry.getValue();
261 | ReactRootView rootView = (ReactRootView)keyboardLayout.getChildAt(0);
262 | if (keyboardLayout != null && keyboardLayout.getParent() != null) {
263 | ((ViewGroup) keyboardLayout.getParent()).removeView(keyboardLayout);
264 | }
265 | if (rootView != null) {
266 | rootView.unmountReactApplication();
267 | }
268 | }
269 | for(Map.Entry entry : edits.entrySet()) {
270 | ReactEditText edit = entry.getValue();
271 | if (edit != null) {
272 | edit.setOnFocusChangeListener(null);
273 | edit.setOnClickListener(null);
274 | }
275 | }
276 | keyboardLayouts.clear();
277 | edits.clear();
278 | successCallback.invoke();
279 | } catch ( Exception e) {
280 | errorCallback.invoke(e.getMessage());
281 | }
282 | }
283 | });
284 | }
285 |
286 | @ReactMethod
287 | public void setHeight(final int tag, final int keyboardHeight) {
288 | Log.v(TAG, "setHeight");
289 | mHandler.post(new Runnable() {
290 | @Override
291 | public void run() {
292 |
293 | if (!edits.containsKey(String.valueOf(tag))) {
294 | return;
295 | }
296 | if (!keyboardLayouts.containsKey(String.valueOf(tag))) {
297 | return;
298 | }
299 | final Activity activity = getCurrentActivity();
300 | if (activity == null) {
301 | return;
302 | }
303 | final float scale = activity.getResources().getDisplayMetrics().density;
304 | RelativeLayout keyboardLayout = keyboardLayouts.get(String.valueOf(tag));
305 |
306 |
307 | RelativeLayout.LayoutParams lParams = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, Math.round(keyboardHeight*scale));
308 | lParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM, RelativeLayout.TRUE);
309 |
310 | if (keyboardLayout != null && keyboardLayout.getChildAt(0) != null) {
311 | keyboardLayout.updateViewLayout(keyboardLayout.getChildAt(0), lParams);
312 |
313 | WritableMap params = Arguments.createMap();
314 | params.putInt("reactTag", tag);
315 | params.putInt("height", keyboardHeight);
316 | sendEvent(reactContext, "onChangeKeyboardHeight", params);
317 | }
318 | }
319 | });
320 | }
321 |
322 | @ReactMethod
323 | public void insertText(final int tag, final String text) {
324 | mHandler.post(new Runnable() {
325 | @Override
326 | public void run() {
327 | final Activity activity = getCurrentActivity();
328 | if (!edits.containsKey(String.valueOf(tag))) {
329 | return;
330 | }
331 |
332 | final ReactEditText edit = edits.get(String.valueOf(tag));
333 |
334 | int start = Math.max(edit.getSelectionStart(), 0);
335 | int end = Math.max(edit.getSelectionEnd(), 0);
336 | edit.getText().replace(Math.min(start, end), Math.max(start, end),
337 | text, 0, text.length());
338 | }
339 | });
340 | }
341 |
342 | @ReactMethod
343 | public void backSpace(final int tag) {
344 | mHandler.post(new Runnable() {
345 | @Override
346 | public void run() {
347 | final Activity activity = getCurrentActivity();
348 | if (!edits.containsKey(String.valueOf(tag))) {
349 | return;
350 | }
351 |
352 | final ReactEditText edit = edits.get(String.valueOf(tag));
353 |
354 | int start = Math.max(edit.getSelectionStart(), 0);
355 | int end = Math.max(edit.getSelectionEnd(), 0);
356 | if (start != end) {
357 | edit.getText().delete(start, end);
358 | } else if (start > 0) {
359 | edit.getText().delete(start - 1, end);
360 | }
361 | }
362 | });
363 | }
364 |
365 | @ReactMethod
366 | public void doDelete(final int tag) {
367 | mHandler.post(new Runnable() {
368 | @Override
369 | public void run() {
370 | if (!edits.containsKey(String.valueOf(tag))) {
371 | return;
372 | }
373 |
374 | final ReactEditText edit = edits.get(String.valueOf(tag));
375 |
376 | int start = Math.max(edit.getSelectionStart(), 0);
377 | int end = Math.max(edit.getSelectionEnd(), 0);
378 | if (start != end) {
379 | edit.getText().delete(start, end);
380 | } else if (start > 0) {
381 | edit.getText().delete(start, end + 1);
382 | }
383 | }
384 | });
385 | }
386 |
387 | @ReactMethod
388 | public void moveLeft(final int tag) {
389 | mHandler.post(new Runnable() {
390 | @Override
391 | public void run() {
392 | final Activity activity = getCurrentActivity();
393 | if (!edits.containsKey(String.valueOf(tag))) {
394 | return;
395 | }
396 |
397 | final ReactEditText edit = edits.get(String.valueOf(tag));
398 |
399 | int start = Math.max(edit.getSelectionStart(), 0);
400 | int end = Math.max(edit.getSelectionEnd(), 0);
401 | if (start != end) {
402 | edit.setSelection(start, start);
403 | } else {
404 | edit.setSelection(start - 1, start - 1);
405 | }
406 | }
407 | });
408 | }
409 |
410 | @ReactMethod
411 | public void moveRight(final int tag) {
412 | mHandler.post(new Runnable() {
413 | @Override
414 | public void run() {
415 | final Activity activity = getCurrentActivity();
416 | if (!edits.containsKey(String.valueOf(tag))) {
417 | return;
418 | }
419 |
420 | final ReactEditText edit = edits.get(String.valueOf(tag));
421 |
422 | int start = Math.max(edit.getSelectionStart(), 0);
423 | int end = Math.max(edit.getSelectionEnd(), 0);
424 | if (start != end) {
425 | edit.setSelection(end, end);
426 | } else if (start > 0) {
427 | edit.setSelection(end + 1, end + 1);
428 | }
429 | }
430 | });
431 | }
432 |
433 | @ReactMethod
434 | public void switchSystemKeyboard(final int tag) {
435 | mHandler.post(new Runnable() {
436 | @Override
437 | public void run() {
438 | final Activity activity = getCurrentActivity();
439 | if (!edits.containsKey(String.valueOf(tag))) {
440 | return;
441 | }
442 | if (!keyboardLayouts.containsKey(String.valueOf(tag))) {
443 | return;
444 | }
445 | final ReactEditText edit = edits.get(String.valueOf(tag));
446 | final RelativeLayout keyboardLayout = keyboardLayouts.get(String.valueOf(tag));
447 |
448 | if (keyboardLayout.getParent() != null) {
449 | ((ViewGroup) keyboardLayout.getParent()).removeView(keyboardLayout);
450 | }
451 | mHandler.post(new Runnable() {
452 |
453 | @Override
454 | public void run() {
455 | ((InputMethodManager) getReactApplicationContext().getSystemService(Activity.INPUT_METHOD_SERVICE)).showSoftInput(edit, InputMethodManager.SHOW_IMPLICIT);
456 | }
457 | });
458 | }
459 | });
460 | }
461 |
462 | @ReactMethod
463 | public void done(final int tag) {
464 | Log.v(TAG, "done");
465 | mHandler.post(new Runnable() {
466 | @Override
467 | public void run() {
468 | final Activity activity = getCurrentActivity();
469 | if (!edits.containsKey(String.valueOf(tag))) {
470 | return;
471 | }
472 |
473 | final ReactEditText edit = edits.get(String.valueOf(tag));
474 |
475 | edit.dispatchKeyEvent(new KeyEvent(0, 0, KeyEvent.ACTION_DOWN,
476 | KeyEvent.KEYCODE_ENTER, 0));
477 |
478 | }
479 | });
480 | }
481 |
482 | private void sendEvent(ReactContext reactContext,
483 | String eventName,
484 | @Nullable WritableMap params) {
485 | reactContext
486 | .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
487 | .emit(eventName, params);
488 | }
489 |
490 | @Override
491 | public String getName() {
492 | return "RNAllmaxKeyboard";
493 | }
494 | }
--------------------------------------------------------------------------------