容器中的TextField - 键盘隐藏文本

时间:2016-11-25 09:39:10

标签: javafx gluon-mobile

我在底部的容器(VBox)中有一个TextField。当我选择TextField输入一些文本时,它会隐藏在键盘(iPhone)后面。我把VBox放在ScrollPane中,但仍然是一样的。

我能以某种方式获得键盘以获得它的高度吗?如何放置未被键盘覆盖的TextField?

感谢您的帮助。

1 个答案:

答案 0 :(得分:4)

此时,JavaFX或JavaFXPorts中没有内置方法来获取(本机)iOS软键盘。

获取键盘并查明是否有任何节点(例如TextField将被其覆盖)的解决方案将需要来自Gluon Charm Down library中可用的Service ,但现在没有这样的KeyboardService

根据this等原生解决方案,当键盘显示或隐藏时,很容易收到通知。因此,我们可以使用这些侦听器并将高度值发送回JavaFX层。

因此,考虑如何在Charm Down库中创建服务,让我们创建KeyboardService

由于这有点超出范围,我已使用所需文件创建了此gist

按照以下步骤使其正常工作:

  1. 创建胶子项目
  2. 使用适用于IDE的最新版Gluon插件创建Gluon项目(单视图)。

    1. 添加KeyboardService界面
    2. 添加包com.gluonhq.charm.down.plugins。添加课程KeyboardServicelink)和KeyboardServiceFactorylink)。

      public interface KeyboardService {
          public ReadOnlyFloatProperty visibleHeightProperty();
      }
      
      1. iOS实施
      2. 在iOS包下添加服务IOSKeyboardServicelink)的iOS实现。

        public class IOSKeyboardService implements KeyboardService {
        
            static {
                System.loadLibrary("Keyboard");
                initKeyboard();
            }
        
            private static ReadOnlyFloatWrapper height = new ReadOnlyFloatWrapper();
        
            @Override
            public ReadOnlyFloatProperty visibleHeightProperty() {
                return height.getReadOnlyProperty();
            }
        
            // native
            private static native void initKeyboard();
        
            private void notifyKeyboard(float height) {
                Platform.runLater(() -> this.height.setValue(height));
            }
        
        }
        
        1. 原生代码
        2. native下创建/src/ios文件夹并添加Keyboard.hlink)文件:

          #import <UIKit/UIKit.h>
          #include "jni.h"
          
          @interface Keyboard : UIViewController {}
          @end
          
          void sendKeyboard();
          

          Keyboard.mlink)文件:

          static int KeyboardInited = 0;
          jclass mat_jKeyboardServiceClass;
          jmethodID mat_jKeyboardService_notifyKeyboard = 0;
          Keyboard *_keyboard;
          CGFloat currentKeyboardHeight = 0.0f;
          
          JNIEXPORT void JNICALL Java_com_gluonhq_charm_down_plugins_ios_IOSKeyboardService_initKeyboard
          (JNIEnv *env, jclass jClass)
          {
              if (KeyboardInited)
              {
                  return;
              }
              KeyboardInited = 1;
          
              mat_jKeyboardServiceClass = (*env)->NewGlobalRef(env, (*env)->FindClass(env, "com/gluonhq/charm/down/plugins/ios/IOSKeyboardService"));
              mat_jKeyboardService_notifyKeyboard = (*env)->GetMethodID(env, mat_jKeyboardServiceClass, "notifyKeyboard", "(F)V");
              GLASS_CHECK_EXCEPTION(env);
          
              _keyboard = [[Keyboard alloc] init];
          }
          
          void sendKeyboard() {
              GET_MAIN_JENV;
              (*env)->CallVoidMethod(env, mat_jKeyboardServiceClass, mat_jKeyboardService_notifyKeyboard, currentKeyboardHeight);
          }
          
          @implementation Keyboard 
          
          - (void) startObserver 
          {
              [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
              [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
          }
          
          - (void) stopObserver 
          {
              [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillShowNotification object:nil];
              [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillHideNotification object:nil];
          }
          
          - (void)keyboardWillShow:(NSNotification*)notification {
              NSDictionary *info = [notification userInfo];
              CGSize kbSize = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size;
              currentKeyboardHeight = kbSize.height;
              sendKeyboard();
          }
          
          - (void)keyboardWillHide:(NSNotification*)notification {
              currentKeyboardHeight = 0.0f;
              sendKeyboard();
          }
          
          @end
          

          1. 构建本机库
          2. 在具有最新版XCode的Mac上,您可以构建本机库libKeyboard.a。为此,您需要将xcodebuild任务添加到项目的build.gradle文件中(link)。它基于Charm Down中的ios-build.gradle file

            task xcodebuild {
                doLast {
                    xcodebuildIOS("$project.buildDir","$project.projectDir", "Keyboard")
                }
            }
            

            保存项目,并从项目根目录下的命令行运行./gradlew clean build xcodebuild

            如果一切就绪,您应该在libKeyboard.a下找到build/native。复制文件,在jniLibs下创建文件夹src/ios,然后将其粘贴到那里。

            1. 实施服务
            2. TextField添加BasicView,并将对齐方式更改为BOTTOM-CENTER

              VBox controls = new VBox(15.0, label, button, new TextField());
              controls.setAlignment(Pos.BOTTOM_CENTER);
              

              实施服务:

              Services.get(KeyboardService.class).ifPresent(keyboard -> {
                  keyboard.visibleHeightProperty().addListener((obs, ov, nv) -> 
                      setTranslateY(-nv.doubleValue()));
              });
              
              1. 部署并运行
              2. 你应该拥有一切。插上iPhone / iPad,然后运行./gradlew --info launchIOSDevice

                当textField获得焦点时,软键盘会显示,并且视图会被翻译,因此textField完全可见:

                希望这项服务在某些时候会包含在Charm Down中。但这也是如何添加自定义服务的一个很好的例子。还要注意Charm Down项目是开源的,所以任何贡献都是好的。