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

标签 javafx gluon-mobile

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

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

感谢您的帮助。

最佳答案

目前,JavaFX 或 JavaFXPorts 中没有内置方法来获取( native )iOS 软键盘。

获取键盘并找出是否有任何节点(如 TextField)将被其覆盖的解决方案需要 Gluon Charm 中可用的Service向下library , 但目前还没有这样的 KeyboardService

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

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

因为这有点超出这里的范围,所以我创建了这个 gist与所需的文件。

按照以下步骤使其工作:

  1. 创建 Gluon 项目

使用适用于您的 IDE 的最新版本的 Gluon 插件创建一个 Gluon 项目(单一 View )。

  1. 添加KeyboardService接口(interface)

添加包com.gluonhq.charm.down.plugins。添加类 KeyboardService ( link ) 和 KeyboardServiceFactory ( link )。

public interface KeyboardService {
    public ReadOnlyFloatProperty visibleHeightProperty();
}
  1. iOS 实现

在 iOS 包下添加服务 IOSKeyboardService ( link ) 的 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. 原生代码

/src/ios 下创建一个 native 文件夹并添加 Keyboard.h ( link ) 文件:

#import <UIKit/UIKit.h>
#include "jni.h"

@interface Keyboard : UIViewController {}
@end

void sendKeyboard();

Keyboard.m ( link ) 文件:

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. 构建原生库

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

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

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

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

  1. 实现服务

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. 部署并运行

您应该已准备就绪。插入你的 iPhone/iPad,然后运行 ​​./gradlew --info launchIOSDevice

当 textField 获得焦点时,软键盘出现, View 被翻译,因此 textField 完全可见:

希望这项服务能在某个时候包含在 Charm Down 中。但这也是您如何添加自定义服务的一个很好的例子。另请注意,Charm Down 项目是开源的,因此欢迎任何贡献。

关于javafx - 容器中的 TextField - 键盘隐藏文本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40801771/

相关文章:

java - 我的代码是 View 、模型或 Controller 的一部分吗?

JavaFX 刷新 TableView 线程

android - 在Gluon Mobile上构建Android

javafx - 如何定义gluon应用程序版本

java - 错误 : JavaFX runtime components are missing - JavaFX 11 and OpenJDK 11 and Eclipse IDE

JavaFX 阻止非 UI 线程,直到 GUI 完成更新(暂停转换中)

Javafx 自定义 slider 值

android - Gluon 主页按钮事件

java - 如何在Gluon Mobile项目中更改jdk?

java - FX :deploy application not working but the Java jar is working - Gluon Project