Use the CustomKeyboardHandler module to support your own custom keyboard implementation in your application. This module acts as a bridge between the RN/JS layer and the native layer. When enabled, it blocks the native device’s software keyboard, if one is available on the device, and instead surfaces the keyboard requests to the JavaScript (JS) layer via CustomKeyboardHandler, to be handled by your custom keyboard implementation. It also allows text input to be passed back to the current target keyboard input receiver.
This allows your application to specify its own keyboard implementation for devices that don’t have their own keyboard implementation, as well as allowing you to replace any existing platform keyboard, if desired.
You can enable and disable your custom keyboard as needed. Toggling between the native software keyboard and your own, as needed.
CustomKeyboardEvent
Parameters/Events: SHOW_CUSTOM_KEYBOARD_EVENT: string
Emitted when a view/input receiver is requesting the keyboard to be shown and expecting text. The parameters include:
receiverText
- The text currently within the receiver requesting the keyboard.receiverMaxCharacterCount
- Max character count of the receiver requesting the keyboardcursorPositionInText
- The current position of the cursor in the text of the receiver.receiverScreenRect
- Represents a RECT structure of the pos and dimensions of the receiver.Parameters/Events: HIDE_CUSTOM_KEYBOARD_EVENT: string
Emitted when the keyboard is being requested to be closed.
enableCustomKeyboard()
CustomKeyboardHandlerModule.enableCustomKeyboard(enableCustomKeyboard);
enableCustomKeyboard : boolean
addEventListener()
addEventListener(type: CustomKeyboardEventName, handler: Function)
Parameters/Events: type: CustomKeyboardEventName
The name of the custom keyboard event being listened to.
Parameters/Events: handler: Function
The function that is called to handle the event.
removeEventListener()
removeEventListener(type: CustomKeyboardEventName, handler: Function)
Parameters/Events: type: CustomKeyboardEventName
The name of the custom keyboard event being listened to.
Parameters/Events: handler: Function
The function that is called to handle the event.
setTextToCurrentReceiver()
setTextToCurrentReceiver(inputText: string)
Parameters/Events: inputText: string
The text string to apply to the current input receiver connected to the custom keyboard.
closeCustomKeyboard()
HIDE_CUSTOM_KEYBOARD_EVENT
to close the keyboard.closeCustomKeyboard()
The following is a simple example showing a very basic integration to set up a custom keyboard implementation by tying into the events and methods provided by CustomKeyboardHandler to launch your keyboard when needed and to set the keyboard’s generated text to the target input receiver:
import React, { Component } from 'react';
import {
AppRegistry,
StyleSheet,
Text,
TextInput,
View,
} from 'react-native'
import {
ButtonRef,
Composition,
CustomKeyboardHandler,
FocusManager,
TextInputRef,
TextRef,
ViewRef
} from '@youi/react-native-youi'
const buttons = [
{
name: 'OneKey',
char: '1',
},
{
name: 'TwoKey',
char: '2',
},
{
name: 'ThreeKey',
char: '3',
},
{
name: 'AKey',
char: 'A',
},
{
name: 'BKey',
char: 'B',
},
{
name: 'CKey',
char: 'C',
},
{
name: 'DKey',
char: 'D',
},
{
name: 'EKey',
char: 'E',
},
{
name: 'FKey',
char: 'F',
},
];
class MyKeyboard extends Component {
state = {
value: this.props.value,
receiverText: this.props.receiverText,
receiverMaxCharacterCount: this.props.receiverMaxCharacterCount,
cursorPositionInText: this.props.cursorPositionInText,
receiverPosX: this.props.receiverPosX,
receiverPosY: this.props.receiverPosY,
receiverWidth: this.props.receiverWidth,
receiverHeight: this.props.receiverHeight,
};
componentDidMount() {
setTimeout(() => {
FocusManager.setFocusable(this.root, true);
FocusManager.enableFocus(this.root, true);
FocusManager.setFocusRoot(this.root, true);
FocusManager.focus(this.AKey);
});
}
render() {
const charButtons = buttons.map((button) => {
return (
<ButtonRef
name={button.name}
onClick={() => {
this.setState({
value: this.state.value + button.char,
});
}}
/>
);
});
return (
<View style={styles.keyboard}>
<View style={styles.eventLogsContainer}>
<Text style={styles.eventLogText}>{"receiverText: \"" + this.state.receiverText + "\""}</Text>
<Text style={styles.eventLogText}>{"receiverMaxCharLimit: " + this.state.receiverMaxCharacterCount}</Text>
<Text style={styles.eventLogText}>{"receiverCursorTextPos: " + this.state.cursorPositionInText}</Text>
<Text style={styles.eventLogText}>{"receiverViewPos: (" + this.state.receiverPosX + "," + this.state.receiverPosY + ")"}</Text>
<Text style={styles.eventLogText}>{"receiverViewDimensions: (" + this.state.receiverWidth + "," + this.state.receiverHeight + ")"}</Text>
</View>
<Composition source="Keyboard_MainComp">
<TextRef name="PLACEHOLDER" text={this.state.value} />
{charButtons}
<ButtonRef
name="BackspaceKey"
onClick={() => {
if (this.state.value.length > 0) {
this.setState({
value: this.state.value.substr(0, this.state.value.length -1),
});
}
}}
/>
<ButtonRef
name="ClearKey"
onClick={() => {
this.setState({
value: '',
});
}}
/>
<ButtonRef
name="DoneKey"
onClick={() => {
console.log("Done! Send '" + this.state.value + "' to the Keyboard manager.");
this.props.onDone(this.state.value);
}}
/>
<ButtonRef
name="CancelKey"
onClick={() => {
console.log("Cancel! Tell the Keyboard manager to close us.");
this.setState({
value: ''
});
this.props.onCancel();
}}
/>
</Composition>
</View>
);
}
}
export default class TestCustomKeyboard extends Component {
constructor(props){
super(props);
this.state = {
keyboardVisible: false,
inputText: '',
text: 'Useless Placeholder. isFocused should print true.',
text2: 'This text should never change.',
text3: '',
text4: 'onKeyPress tester.',
text5: 'This text field will not be editable. You will not be able to focus it or enter text.',
text6: '',
currentReceiverData: {
receiverText:'',
receiverMaxCharacterCount: 0,
cursorPositionInText: 0,
receiverScreenRect : {
x: 0,
y: 0,
width: 0,
height: 0
}
},
}
CustomKeyboardHandler.enableCustomKeyboard(true);
CustomKeyboardHandler.addEventListener('SHOW_CUSTOM_KEYBOARD_EVENT', this.onShowCustomKeyboard);
CustomKeyboardHandler.addEventListener('HIDE_CUSTOM_KEYBOARD_EVENT', this.onHideCustomKeyboard);
}
onShowCustomKeyboard = (args) => {
this.setState({keyboardVisible: true,
currentReceiverData: args});
}
onHideCustomKeyboard = (args) => {
this.setState({keyboardVisible: false});
}
handleKeyboardDone = (enteredText) => {
CustomKeyboardHandler.setTextToCurrentReceiver(enteredText);
this.setState({
keyboardVisible: false,
inputText: enteredText,
});
CustomKeyboardHandler.closeCustomKeyboard();
}
render() {
let keyboard = this.state.keyboardVisible ? <MyKeyboard
onDone={this.handleKeyboardDone}
onCancel={() => {this.setState({keyboardVisible: false});}}
value={this.state.currentReceiverData.receiverText}
receiverText = {this.state.currentReceiverData.receiverText}
receiverMaxCharacterCount = {this.state.currentReceiverData.receiverMaxCharacterCount}
cursorPositionInText = {this.state.currentReceiverData.cursorPositionInText}
receiverPosX = {this.state.currentReceiverData.receiverScreenRect.x}
receiverPosY = {this.state.currentReceiverData.receiverScreenRect.y}
receiverWidth = {this.state.currentReceiverData.receiverScreenRect.width}
receiverHeight = {this.state.currentReceiverData.receiverScreenRect.height}
/> : <View />;
return (
<View style={styles.mainContainer}>
<View style={{backgroundColor: 'gray'}}>
<View style={{backgroundColor: 'transparent'}}>
<TextInput ref={(a) => {this.textinput = a;}}
style={{height: 40, borderColor: 'gray', borderWidth: 1}}
onChangeText={(t) => {
this.setState({text: t});
console.log("isFocused? " + this.textinput.isFocused());
}}
onChange={() => console.log("OnChange called.")}
onFocus={() => {
console.log("onFocus called.")
CustomKeyboardHandler.setTextReceivedHandler((enteredText) => {
this.setState({text: enteredText});
});
}}
onEndEditing={() => console.log("onEndEditing called.")}
onSubmitEditing={() => console.log("onSubmitEditing called.")}
value={this.state.text}
/>
<TextInput
style={{height: 40, borderColor: 'gray', borderWidth: 1}}
value={this.state.text2}
/>
<TextInput
style={{height: 40, borderColor: 'gray', borderWidth: 1}}
onChangeText={(t) => {
this.setState({text3: t})
}}
onFocus={() => {
CustomKeyboardHandler.setTextReceivedHandler((enteredText) => {
this.setState({text3: enteredText});
});
}}
value={this.state.text3}
placeholder={'This is placeholder text.'}
placeholderTextColor={'blue'}
/>
<TextInput
style={{height: 40, color: 'red', backgroundColor: 'yellow'}}
value={'This text should be red and the background should be yellow.'}
/>
<TextInput
style={{height: 40, fontSize: 20}}
value={'This text should be size 20.'}
/>
<TextInput
style={{height: 40, fontFamily: 'yi_Futura-Regular.ttf'}}
value={'This text should display Futura.'}
/>
<TextInput
style={{height: 40, fontSize: 20}}
value={this.state.text4}
onKeyPress={(k) =>{
console.log("onKeyPress called with key [" + k.nativeEvent.key + "]");
}}
onChangeText={(t) => {
this.setState({text4: t})
}}
onFocus={() => {
CustomKeyboardHandler.setTextReceivedHandler((enteredText) => {
this.setState({text4: enteredText});
});
}}
/>
<TextInput
style={{height: 40, fontSize: 20}}
defaultValue={'The text here is the default entry. isFocused should print false.'}
onChangeText={(t) => {
console.log("isFocused? " + this.textinput.isFocused());
}}
/>
<TextInput
style={{height: 40, fontSize: 20}}
value={'This text field will not have a caret.'}
caretHidden={true}
/>
<TextInput
style={{height: 40, fontSize: 20}}
value={this.state.text5}
editable={false}
onChangeText={(t) => {
this.setState({text5: t})
}}
onFocus={() => {
CustomKeyboardHandler.setTextReceivedHandler((enteredText) => {
this.setState({text5: enteredText});
});
}}
/>
<TextInput
style={{height: 40, borderColor: 'gray', borderWidth: 1}}
onChangeText={(t) => {
this.setState({text6: t})
}}
onFocus={() => {
CustomKeyboardHandler.setTextReceivedHandler((enteredText) => {
this.setState({text6: enteredText});
});
}}
value={this.state.text6}
placeholder={'This is a password field'}
placeholderTextColor={'blue'}
secureTextEntry={true}
/>
<TextInput
style={{height: 40, fontFamily: 'Charter'}}
value={'This text should display Charter Bold.'}
/>
<TextInput
style={{height: 40, fontSize: 20}}
value={'clearTextOnFocus - This text field will clear on focus. Text will reappear after typing.'}
clearTextOnFocus={true}
/>
<TextInput
ref={(a) => {this.textinput2 = a;}}
style={{height: 40, fontSize: 20}}
value={'clear() - This text field will clear on focus. Text will reappear after typing.'}
onFocus={() =>
this.textinput2.clear()
}
/>
</View>
</View>
{keyboard}
</View>
);
}
}
const styles = StyleSheet.create({
mainContainer: {
flex: 1,
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'flex-start',
backgroundColor: '#d0d0d0'
},
container: {
flex: 1,
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#d0d0d0',
},
keyboard: {
backgroundColor: 'black',
position: 'absolute',
top: 0,
left: 0,
},
eventLogText: {
fontSize: 20,
textAlign: 'center',
margin: 0,
color: '#000',
},
eventLogsContainer: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#d0d0d0'
},
});
AppRegistry.registerComponent('TestCaseApp', () => TestCustomKeyboard);