我在底部的容器(VBox)中有一个TextField。当我选择TextField输入一些文本时,它会隐藏在键盘(iPhone)后面。我把VBox放在ScrollPane中,但仍然一样。容器中的TextField - 键盘隐藏文本
我可以通过键盘获得它的高度吗?我如何放置没有从键盘覆盖的TextFields?
谢谢你的帮助。
我在底部的容器(VBox)中有一个TextField。当我选择TextField输入一些文本时,它会隐藏在键盘(iPhone)后面。我把VBox放在ScrollPane中,但仍然一样。容器中的TextField - 键盘隐藏文本
我可以通过键盘获得它的高度吗?我如何放置没有从键盘覆盖的TextFields?
谢谢你的帮助。
此时,JavaFX或JavaFXPorts中没有内置方法来获取(本地)iOS软键盘。
的解决方案,使键盘和找出是否有任何节点,就像一个TextField
会被它覆盖,就需要从那些在胶子的魅力下library可用Service
,但现在没有这样的KeyboardService
。
基于像this这样的原生解决方案,当显示或隐藏键盘时很容易得到通知。所以我们可以利用这些监听器并将高度值发送回JavaFX图层。
因此,让我们创建KeyboardService
,考虑如何在Charm Down库中创建服务。
由于这里有点超出范围,所以我创建了这个带有所需文件的gist。
按照以下步骤,使其工作:
创建一个胶子项目(单个视图)与你的IDE最新版本的胶子插件。
添加包com.gluonhq.charm.down.plugins
。添加类KeyboardService
(link)和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)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.gradle
file。
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
。
当文本框获得焦点,软键盘显示出来,并且认为是翻译,所以文本字段是完全可见:
希望这项服务将在一些被列入魅力向下点。但这也是您如何添加自定义服务的一个很好的例子。另外请注意,Charm Down项目是开源的,所以任何贡献都是很好的。
太棒了!谢谢!! – tonimaroni
嘿何塞。我今天才发现时间来实现上面的插件。完美描述和一切工作。 我有一个“发送”按钮右边的文本框。上面的解决方案,我必须按“发送”两次。第一次它删除键盘..然后我必须再次点击按钮才能完成他的工作。你有什么想法我需要改变,所以当键盘处于活动状态时,按下一个按钮将首次触发。谢谢。 – tonimaroni
用'button.setOnMouseClicked()'替换'button.setOnAction()',应该可以。不知何故''fire()'事件被消耗,当键盘被解散和'onAction'没有被触发。 –