123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336 |
- part of cool_ui;
- typedef GetKeyboardHeight = double Function(BuildContext context);
- typedef KeyboardBuilder = Widget Function(BuildContext context,KeyboardController controller);
- class CoolKeyboard {
- static JSONMethodCodec _codec = const JSONMethodCodec();
- static KeyboardConfig _currentKeyboard;
- static Map<CKTextInputType,KeyboardConfig> _keyboards = {};
- static BuildContext _context;
- static OverlayEntry _keyboardEntry;
- static KeyboardController _keyboardController;
- static GlobalKey<KeyboardPageState> _pageKey;
- static bool isInterceptor = false;
- static double get keyboardHeight =>_keyboardHeight;
- static double _keyboardHeight;
- static init(BuildContext context){
- _context = context;
- interceptorInput();
- }
- static interceptorInput(){
- if(isInterceptor)
- return;
- isInterceptor = true;
- BinaryMessages.setMockMessageHandler("flutter/textinput", (ByteData data) async{
- var methodCall = _codec.decodeMethodCall(data);
- switch(methodCall.method){
- case 'TextInput.show':
- if(_currentKeyboard != null){
- openKeyboard();
- return _codec.encodeSuccessEnvelope(null);
- }else{
- return await _sendPlatformMessage("flutter/textinput", data);
- }
- break;
- case 'TextInput.hide':
- if(_currentKeyboard != null){
- hideKeyboard();
- return _codec.encodeSuccessEnvelope(null);
- }else{
- return await _sendPlatformMessage("flutter/textinput", data);
- }
- break;
- case 'TextInput.setEditingState':
- var editingState = TextEditingValue.fromJSON(methodCall.arguments);
- if(editingState != null && _keyboardController != null){
- _keyboardController.value = editingState;
- return _codec.encodeSuccessEnvelope(null);
- }
- break;
- case 'TextInput.clearClient':
- hideKeyboard(animation:true);
- clearKeyboard();
- break;
- case 'TextInput.setClient':
- var setInputType = methodCall.arguments[1]['inputType'];
- InputClient client;
- _keyboards.forEach((inputType,keyboardConfig){
- if(inputType.name == setInputType['name']){
- client = InputClient.fromJSON(methodCall.arguments);
- clearKeyboard();
- _currentKeyboard = keyboardConfig;
- _keyboardController = KeyboardController(client:client)..addListener((){
- var callbackMethodCall = MethodCall("TextInputClient.updateEditingState",[_keyboardController.client.connectionId,_keyboardController.value.toJSON()]);
- BinaryMessages.handlePlatformMessage("flutter/textinput", _codec.encodeMethodCall(callbackMethodCall), (data){});
- });
- }
- });
- if(client != null){
- await _sendPlatformMessage("flutter/textinput", _codec.encodeMethodCall(MethodCall('TextInput.hide')));
- return _codec.encodeSuccessEnvelope(null);
- }else{
- hideKeyboard(animation:false);
- clearKeyboard();
- }
- break;
- }
- ByteData response = await _sendPlatformMessage("flutter/textinput", data);
- return response;
- });
- }
- static Future<ByteData> _sendPlatformMessage(String channel, ByteData message) {
- final Completer<ByteData> completer = Completer<ByteData>();
- ui.window.sendPlatformMessage(channel, message, (ByteData reply) {
- try {
- completer.complete(reply);
- } catch (exception, stack) {
- FlutterError.reportError(FlutterErrorDetails(
- exception: exception,
- stack: stack,
- library: 'services library',
- context: 'during a platform message response callback',
- ));
- }
- });
- return completer.future;
- }
- static addKeyboard(CKTextInputType inputType,KeyboardConfig config){
- _keyboards[inputType] = config;
- }
- static openKeyboard(){
- if(_keyboardEntry != null)
- return;
- _pageKey = GlobalKey<KeyboardPageState>();
- _keyboardHeight = _currentKeyboard.getHeight(_context);
- _context.ancestorStateOfType(const TypeMatcher<KeyboardMediaQueryState>()).setState((){});
- var tempKey = _pageKey;
- _keyboardEntry = OverlayEntry(builder: (ctx) {
- if(_currentKeyboard != null && _keyboardHeight != null)
- {
- return KeyboardPage(
- key: tempKey,
- child: Builder(builder: (ctx){
- return _currentKeyboard.builder(ctx,_keyboardController);
- }),
- height:_keyboardHeight
- );
- }else{
- return Container();
- }
- });
- Overlay.of(_context).insert(_keyboardEntry);
- }
- static hideKeyboard({bool animation=true}){
- if(_keyboardEntry != null) {
- _keyboardHeight = null;
- _pageKey.currentState.animationController.addStatusListener((status) {
- if (status == AnimationStatus.dismissed ||
- status == AnimationStatus.completed) {
- if (_keyboardEntry != null) {
- _keyboardEntry.remove();
- _keyboardEntry = null;
- }
- }
- });
- if (animation)
- {
- _pageKey.currentState.exitKeyboard();
- }
- else{
- _keyboardEntry.remove();
- _keyboardEntry = null;
- }
- }
- _pageKey = null;
- _context.ancestorStateOfType(const TypeMatcher<KeyboardMediaQueryState>()).setState((){});
- }
- static clearKeyboard(){
- _currentKeyboard = null;
- if(_keyboardController != null){
- _keyboardController.dispose();
- _keyboardController = null;
- }
- }
- static sendPerformAction(TextInputAction action){
- var callbackMethodCall = MethodCall("TextInputClient.performAction",
- [
- _keyboardController.client.connectionId,
- action.toString()
- ]);
- BinaryMessages.handlePlatformMessage(
- "flutter/textinput", _codec.encodeMethodCall(callbackMethodCall), (
- data) {});
- }
- }
- class KeyboardConfig{
- final KeyboardBuilder builder;
- final GetKeyboardHeight getHeight;
- const KeyboardConfig({this.builder,this.getHeight});
- }
- class InputClient{
- final int connectionId;
- final TextInputConfiguration configuration;
- const InputClient({this.connectionId,this.configuration});
- factory InputClient.fromJSON(List<dynamic> encoded) {
- return InputClient(connectionId: encoded[0],configuration: TextInputConfiguration(
- inputType:CKTextInputType.fromJSON(encoded[1]['inputType']),
- obscureText:encoded[1]['obscureText'],
- autocorrect:encoded[1]['autocorrect'],
- actionLabel:encoded[1]['actionLabel'],
- inputAction:_toTextInputAction(encoded[1]['inputAction']),
- textCapitalization:_toTextCapitalization(encoded[1]['textCapitalization']),
- keyboardAppearance:_toBrightness(encoded[1]['keyboardAppearance'])
- ));
- }
- static TextInputAction _toTextInputAction(String action) {
- switch (action) {
- case 'TextInputAction.none':
- return TextInputAction.none;
- case 'TextInputAction.unspecified':
- return TextInputAction.unspecified;
- case 'TextInputAction.go':
- return TextInputAction.go;
- case 'TextInputAction.search':
- return TextInputAction.search;
- case 'TextInputAction.send':
- return TextInputAction.send;
- case 'TextInputAction.next':
- return TextInputAction.next;
- case 'TextInputAction.previuos':
- return TextInputAction.previous;
- case 'TextInputAction.continue_action':
- return TextInputAction.continueAction;
- case 'TextInputAction.join':
- return TextInputAction.join;
- case 'TextInputAction.route':
- return TextInputAction.route;
- case 'TextInputAction.emergencyCall':
- return TextInputAction.emergencyCall;
- case 'TextInputAction.done':
- return TextInputAction.done;
- case 'TextInputAction.newline':
- return TextInputAction.newline;
- }
- throw FlutterError('Unknown text input action: $action');
- }
- static TextCapitalization _toTextCapitalization(String capitalization){
- switch(capitalization){
- case 'TextCapitalization.none':
- return TextCapitalization.none;
- case 'TextCapitalization.characters':
- return TextCapitalization.characters;
- case 'TextCapitalization.sentences':
- return TextCapitalization.sentences;
- case 'TextCapitalization.words':
- return TextCapitalization.words;
- }
- throw FlutterError('Unknown text capitalization: $capitalization');
- }
- static Brightness _toBrightness(String brightness){
- switch(brightness){
- case 'Brightness.dark':
- return Brightness.dark;
- case 'Brightness.light':
- return Brightness.light;
- }
- throw FlutterError('Unknown Brightness: $brightness');
- }
- }
- class CKTextInputType extends TextInputType{
- final String name;
- const CKTextInputType({this.name,bool signed,bool decimal}) : super.numberWithOptions(signed:signed,decimal:decimal);
- @override
- Map<String, dynamic> toJson() {
- return <String, dynamic>{
- 'name': name,
- 'signed': signed,
- 'decimal': decimal,
- };
- }
- factory CKTextInputType.fromJSON(Map<String,dynamic> encoded) {
- return CKTextInputType(
- name: encoded['name'],
- signed: encoded['signed'],
- decimal: encoded['decimal']
- );
- }
- }
- class KeyboardPage extends StatefulWidget{
- final Widget child;
- final double height;
- const KeyboardPage({this.child,this.height,Key key}):super(key:key);
- @override
- State<StatefulWidget> createState() =>KeyboardPageState();
- }
- class KeyboardPageState extends State<KeyboardPage> with SingleTickerProviderStateMixin{
- AnimationController animationController;
- Animation<double> doubleAnimation;
- double bottom;
- @override
- void initState() {
- // TODO: implement initState
- super.initState();
- animationController = new AnimationController(duration: new Duration(milliseconds: 100),vsync: this)
- ..addListener(()=>setState((){}));
- doubleAnimation =
- new Tween(begin: 0.0, end: widget.height).animate(animationController)..addListener(()=>setState((){}));
- animationController.forward(from:0.0);
- }
- @override
- Widget build(BuildContext context) {
- return Positioned(
- child: IntrinsicHeight(
- child: widget.child
- ),
- bottom: (widget.height - doubleAnimation.value) * -1
- );
- }
- @override
- void dispose() {
- super.dispose();
- animationController.dispose();
- }
- exitKeyboard(){
- animationController.reverse();
- }
- }
|