2016-11-25 67 views
3

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

我可以通过键盘获得它的高度吗?我如何放置没有从键盘覆盖的TextFields?

谢谢你的帮助。

回答

3

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

的解决方案,使键盘和找出是否有任何节点,就像一个TextField会被它覆盖,就需要从那些在胶子的魅力下library可用Service,但现在没有这样的KeyboardService

基于像this这样的原生解决方案,当显示或隐藏键盘时很容易得到通知。所以我们可以利用这些监听器并将高度值发送回JavaFX图层。

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

由于这里有点超出范围,所以我创建了这个带有所需文件的gist

按照以下步骤,使其工作:

  1. 创建一个胶子工程

创建一个胶子项目(单个视图)与你的IDE最新版本的胶子插件。

  • 添加KeyboardService接口
  • 添加包com.gluonhq.charm.down.plugins。添加类KeyboardServicelink)和KeyboardServiceFactorylink)。

    public interface KeyboardService { 
        public ReadOnlyFloatProperty visibleHeightProperty(); 
    } 
    
  • 的iOS实施
  • 根据iOS包添加了iOS执行服务IOSKeyboardServicelink)的。

    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)); 
        } 
    
    } 
    
  • 本地代码
  • /src/ios下创建native文件夹,并添加Keyboard.hlink)文件:

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

    Keyboard.mlink)file:

    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 
    

  • 构建本地库
  • 在Mac上使用最新版本的Xcode,你可以建立本地库libKeyboard.a。为此,您需要将xcodebuild任务添加到项目的build.gradle文件(link)。它基于Charm Down的ios-build.gradlefile

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

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

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

  • 实现服务
  • 添加TextFieldBasicView,改变对准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())); 
    }); 
    
  • 部署和运行
  • 您应该一切准备就绪。插入你的iPhone/iPad,并运行./gradlew --info launchIOSDevice

    当文本框获得焦点,软键盘显示出来,并且认为是翻译,所以文本字段是完全可见:

    希望这项服务将在一些被列入魅力向下点。但这也是您如何添加自定义服务的一个很好的例子。另外请注意,Charm Down项目是开源的,所以任何贡献都是很好的。

    +0

    太棒了!谢谢!! – tonimaroni

    +0

    嘿何塞。我今天才发现时间来实现上面的插件。完美描述和一切工作。 我有一个“发送”按钮右边的文本框。上面的解决方案,我必须按“发送”两次。第一次它删除键盘..然后我必须再次点击按钮才能完成他的工作。你有什么想法我需要改变,所以当键盘处于活动状态时,按下一个按钮将首次触发。谢谢。 – tonimaroni

    +0

    用'button.setOnMouseClicked()'替换'button.setOnAction()',应该可以。不知何故''fire()'事件被消耗,当键盘被解散和'onAction'没有被触发。 –