容器中的 TextField - 键盘隐藏文本
TextField in a Container - Keyboard hides Text
我在底部的容器 (VBox) 中有一个 TextField。当我 select TextField 输入一些文本时,它会隐藏在键盘后面 (iPhone)。我将 VBox 放在 ScrollPane 中,但仍然相同。
我可以通过某种方式获取键盘的高度吗?如何放置未被键盘覆盖的 TextField?
感谢您的帮助。
此时,JavaFX 或 JavaFXPorts 中没有内置方法来获取(本机)iOS 软键盘。
获取键盘并找出是否有任何节点(如 TextField
将被其覆盖)的解决方案需要 Gluon Charm Down [=42] 中可用的 Service
=], 但目前还没有 KeyboardService
.
基于 this 等本机解决方案,当显示或隐藏键盘时很容易收到通知。所以我们可以利用这些侦听器并将高度值发送回 JavaFX 层。
所以让我们创建 KeyboardService
考虑到如何在 Charm Down 库中创建服务。
由于这有点超出此处的范围,我已经使用所需的文件创建了这个 gist。
按照以下步骤使其工作:
- 创建 Gluon 项目
使用最新版本的 Gluon 插件为您的 IDE 创建一个 Gluon 项目(单一视图)。
- 添加键盘服务接口
添加包 com.gluonhq.charm.down.plugins
。添加 类 KeyboardService
(link) and KeyboardServiceFactory
(link)。
public interface KeyboardService {
public ReadOnlyFloatProperty visibleHeightProperty();
}
- 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));
}
}
- 本机码
在 /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
- 构建本机库
在具有最新版本 XCode 的 Mac 上,您可以构建本机库 libKeyboard.a
。为此,您需要将 xcodebuild
任务添加到项目的 build.gradle
文件中(link). It is based on the 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
,然后将其粘贴到那里。
- 实施服务
将 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()));
});
- 部署和运行
你应该一切就绪。插入你的 iPhone/iPad 和 运行 ./gradlew --info launchIOSDevice
.
当 textField 获得焦点时,软键盘出现,视图被翻译,因此 textField 完全可见:
希望这项服务将来会包含在 Charm Down 中。但这也是您如何添加自定义服务的一个很好的例子。另请注意,Charm Down 项目是开源的,因此欢迎任何贡献。
我在底部的容器 (VBox) 中有一个 TextField。当我 select TextField 输入一些文本时,它会隐藏在键盘后面 (iPhone)。我将 VBox 放在 ScrollPane 中,但仍然相同。
我可以通过某种方式获取键盘的高度吗?如何放置未被键盘覆盖的 TextField?
感谢您的帮助。
此时,JavaFX 或 JavaFXPorts 中没有内置方法来获取(本机)iOS 软键盘。
获取键盘并找出是否有任何节点(如 TextField
将被其覆盖)的解决方案需要 Gluon Charm Down [=42] 中可用的 Service
=], 但目前还没有 KeyboardService
.
基于 this 等本机解决方案,当显示或隐藏键盘时很容易收到通知。所以我们可以利用这些侦听器并将高度值发送回 JavaFX 层。
所以让我们创建 KeyboardService
考虑到如何在 Charm Down 库中创建服务。
由于这有点超出此处的范围,我已经使用所需的文件创建了这个 gist。
按照以下步骤使其工作:
- 创建 Gluon 项目
使用最新版本的 Gluon 插件为您的 IDE 创建一个 Gluon 项目(单一视图)。
- 添加键盘服务接口
添加包 com.gluonhq.charm.down.plugins
。添加 类 KeyboardService
(link) and KeyboardServiceFactory
(link)。
public interface KeyboardService {
public ReadOnlyFloatProperty visibleHeightProperty();
}
- iOS实施
在 iOS 包下添加服务 IOSKeyboardService
(link).
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.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
- 构建本机库
在具有最新版本 XCode 的 Mac 上,您可以构建本机库 libKeyboard.a
。为此,您需要将 xcodebuild
任务添加到项目的 build.gradle
文件中(link). It is based on the 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
,然后将其粘贴到那里。
- 实施服务
将 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()));
});
- 部署和运行
你应该一切就绪。插入你的 iPhone/iPad 和 运行 ./gradlew --info launchIOSDevice
.
当 textField 获得焦点时,软键盘出现,视图被翻译,因此 textField 完全可见:
希望这项服务将来会包含在 Charm Down 中。但这也是您如何添加自定义服务的一个很好的例子。另请注意,Charm Down 项目是开源的,因此欢迎任何贡献。