在 PhoneGap 应用程序中以编程方式在 iPhone 上显示软键盘?
Posted
技术标签:
【中文标题】在 PhoneGap 应用程序中以编程方式在 iPhone 上显示软键盘?【英文标题】:Programmatically show soft keyboard on iPhone in a PhoneGap application? 【发布时间】:2012-08-27 10:44:33 【问题描述】:我一直在寻找很长一段时间,但到目前为止,我还没有找到一个可行的解决方案,用于以编程方式显示软键盘的 PhoneGap / Cordova 应用程序。
场景:
我们有一个PhoneGap 应用程序——一个用jQuery Mobile 创建的网站——它在某一时刻向用户显示一个对话框。此对话框也是一个网页,只有一个 INPUT 文本框,用户应在其中输入代码。
问题:
显示代码对话框时,输入框使用 javascript 聚焦。但是,由于 iPhone 内部浏览器的限制,直到用户真正在输入文本框内单击时才会出现软键盘。
我们尝试了什么:
创建 hidden text box 并使其成为第一响应者 一旦输入通过 JavaScript 获得焦点,就让实际的 webview 成为第一响应者 使用 sendActionsForControlEvents 尝试将触摸事件传递到 web 视图(尽管如果有人有 PhoneGap 应用程序的工作代码,如果他们能分享它,我将不胜感激,因为我不是 ios 编码方面的专业人士)有什么想法吗?
编辑:此问题中提到的限制仅适用于 内置浏览器...如果您的目标是 Opera,您使用以下代码将成功:
var e = jQuery.Event("keydown", keyCode: 37 );
$('#element').focus().trigger(e);
EDIT2:这是可以在插件中使用的最终工作PhoneGap代码:
keyboardhelper.h
//
// keyboardHelper.h
// soft keyboard displaying plugin for PhoneGap
//
// Copyright 2012 Martin Ambrus.
//
#import <Foundation/Foundation.h>
#ifdef CORDOVA_FRAMEWORK
#import <Cordova/CDVPlugin.h>
#else
#import "CDVPlugin.h"
#endif
@interface keyboardHelper : CDVPlugin
NSString *callbackID;
@property (nonatomic, copy) NSString *callbackID;
- (void)showKeyboard:(NSMutableArray*)arguments withDict:(NSMutableDictionary*)options;
@end
keyboardhelper.m
//
// keyboardHelper.m
// soft keyboard displaying plugin for PhoneGap
//
// Copyright 2012 Martin Ambrus.
//
#import "keyboardHelper.h"
#import "AppDelegate.h"
@implementation keyboardHelper
@synthesize callbackID;
-(void)showKeyboard:(NSMutableArray*)arguments withDict:(NSMutableDictionary*)options
self.callbackID = [arguments pop];
//Get text field coordinate from webview. - You should do this after the webview gets loaded
//myCustomDiv is a div in the html that contains the textField.
int textFieldContainerHeightOutput = [[((AppDelegate *)[[UIApplication sharedApplication] delegate]).viewController.webView stringByEvaluatingJavaScriptFromString:@"document.getElementById(\"myCustomDiv\").offsetHeight;"] intValue];
int textFieldContainerWidthOutput = [[((AppDelegate *)[[UIApplication sharedApplication] delegate]).viewController.webView stringByEvaluatingJavaScriptFromString:@"document.getElementById(\"myCustomDiv\").offsetWidth;"] intValue];
int textFieldContainerYOffset = [[((AppDelegate *)[[UIApplication sharedApplication] delegate]).viewController.webView stringByEvaluatingJavaScriptFromString:@"document.getElementById(\"myCustomDiv\").offsetTop;"] intValue];
int textFieldContainerXOffset = [[((AppDelegate *)[[UIApplication sharedApplication] delegate]).viewController.webView stringByEvaluatingJavaScriptFromString:@"document.getElementById(\"myCustomDiv\").offsetLeft;"] intValue];
UITextField *myTextField = [[UITextField alloc] initWithFrame: CGRectMake(textFieldContainerXOffset, textFieldContainerYOffset, textFieldContainerWidthOutput, textFieldContainerHeightOutput)];
[((AppDelegate *)[[UIApplication sharedApplication] delegate]).viewController.webView addSubview:myTextField];
myTextField.delegate = self;
CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString: @"ok"];
[self writeJavascript:[pluginResult toSuccessCallbackString:self.callbackID]];
-(BOOL)textFieldShouldReturn:(UITextField *)textField
//here you create your request to the server
return NO;
-(BOOL)textFieldDidEndEditing:(UITextField *)textField
//here you create your request to the server
return NO;
@end
javascript
var keyboardHelper =
showKeyboard: function(types, success, fail)
return Cordova.exec(success, fail, "keyboardHelper", "showKeyboard", types);
;
【问题讨论】:
你试过$("#input_id").trigger("click")吗?我还没有,因为我在工作,但这是您可以尝试的更多选择。 是的,我们尝试过...这里不是关于 JavaScript,因为由于可用性和性能问题,编程事件永远不会触发移动设备上的软键盘...我正在寻找原生 iPhone可以在这里提供帮助的代码 我已经更新了问题以包含一个似乎不受键盘限制影响的 Opera Mobile 浏览器的解决方案 downvoter - 需要解释吗? 【参考方案1】:这些天您可以通过config.xml
条目解决问题,添加:
<preference name="keyboardDisplayRequiresUserAction" value="false" />
【讨论】:
很遗憾,您的示例会影响整个应用程序【参考方案2】:您可以在 webView 上使用 javascript 获取输入字段的坐标。然后,将您自己的 textField 放在它上面,并在它的委托方法 textFieldShouldReturn 中使用用户输入的代码向服务器发送请求。
//Get text field coordinate from webview. - You should do this after the webview gets loaded
//myCustomDiv is a div in the html that contains the textField.
int textFieldContainerHeightOutput = [[webView stringByEvaluatingJavaScriptFromString:@"document.getElementById(\"myCustomDiv\").offsetHeight;"] intValue];
int textFieldContainerWidthOutput = [[webView stringByEvaluatingJavaScriptFromString:@"document.getElementById(\"myCustomDiv\").offsetWidth;"] intValue];
int textFieldContainerYOffset = [[webView stringByEvaluatingJavaScriptFromString:@"document.getElementById(\"myCustomDiv\").offsetTop;"] intValue];
int textFieldContainerXOffset = [[webView stringByEvaluatingJavaScriptFromString:@"document.getElementById(\"myCustomDiv\").offsetLeft;"] intValue];
myTextField.frame = CGRectMake(textFieldContainerXOffset, textFieldContainerYOffset, textFieldContainerWidthOutput, textFieldContainerHeightOutput);
[webView addSubview:myTextField];
myTextField.delegate = self;
然后你实现 textFieldShouldReturn 并在那里创建你对服务器的请求。
-(BOOL)textFieldShouldReturn:(UITextField *)textField
//here you create your request to the server
return NO;
这是在现有项目中完成的,但不使用 PhoneGap。我希望你能根据自己的需要调整它。
要删除文本字段,您可以将其隐藏
myTextField.hidden = YES;
或
myTextField = nil;
或
[myTextField removeFromSuperView];
【讨论】:
谢谢...你能提供一个示例代码吗?我不知道如何为 PhoneGap 完成它,它也会使其他人受益...如果您的示例有效,如果此示例过期,我将为您获取 200 声望 我已经根据您的示例编辑了我的问题以包含完整的代码 - 它不起作用,但您能发现任何不寻常的东西会使其不起作用吗? 我向您展示的代码只是一个示例。您必须使其适应您自己的项目,而不是简单地复制/粘贴。例如,您必须输入自己的 id 才能使 javascript 工作。 大声笑,我不敢相信我忘记更改元素 ID...抱歉,这真的很愚蠢...再次测试 :))) 它似乎有效,还有一个问题 - 编辑完成后如何从屏幕上删除该文本字段?【参考方案3】:在 iOS 6 之前,Apple 只允许在用户交互后调出键盘。在 iOS 6 中,他们为 UIWebView 引入了以下属性,您只需将其设置为 NO。
"yourWebView".keyboardDisplayRequiresUserAction = NO;
Apple 默认将此设置为“是”。现在你可以在你的 JS 中调用focus()
,键盘就会出现。
【讨论】:
在什么文件中改变了这个?我在 UIWebView.h 中找到了对 keyboardDisplayRequiresUserAction 的引用,但无法编辑此文件。 只要你创建了一个 UIWebView 实例来调用它,你就可以调用它。我知道直到最近 Trigger.IO 才允许创建 UIWebView 实例,因此使用此方法是不可能的。我不确定 phoneGap 是否允许您这样做,但考虑到它拥有更多的追随者和更发达的产品,我想这是可能的。 @Horak 这个解决方案适用于 IOS,但我必须对 android 应用相同的解决方案。 @SaurabhAndroid,很抱歉,我没有使用 Android 的经验。【参考方案4】:您是否尝试过使用 Native Controls 并从 Javascript 调用它们?
这里有一些代码显示了在 Phonegap Cordova 应用程序(Phonegap 1.5)上使用本机控件
https://gist.github.com/1384250
希望它有助于解决问题:)
【讨论】:
插件+1,我不熟悉它......但是,我不知道如何使用它在屏幕上显示键盘,同时保持对我的网页输入的关注元素? 你说弹出的对话框是另一个网页,它应该有一个onLoad功能,你可以让键盘在对话框加载时出现。你怎么看? 当然,这不是问题 - 但是如何使用 NativeControls 显示键盘?我只在这个插件中看到标签控件,而不是显示控件的键盘【参考方案5】:我承认这是私人的,但它可能会帮助你:
@class UIKeyboard;
void showKeyboard()
static UIKeyboard *kb = nil;
if ([[UIKeyboard class] respondsToSelector:@selector(automaticKeyboard)])
kb = [UIKeyboard automaticKeyboard];
else
kb = [UIKeyboard activeKeyboard];
if (kb == nil)
kb = [[[UIKeyboard alloc] initWithDefaultSize] autorelease];
[[[UIApplication sharedApplication] keyWindow] addSubview:kb];
if ([kb respondsToSelector:@selector(orderInWithAnimation:)])
[kb orderInWithAnimation:YES];
else
[kb activate];
[kb minimize];
[kb maximize];
然后这样称呼它:
showKeyboard();
【讨论】:
我现在只想说,任何用于 App Store 的应用程序都无法做到这一点。 :) 我同意@JonathanGrynspan,但是如果你能指出我将如何或在哪里放置这个?我从来没有在 XCode 中写过任何类代码,所以我对如何使用这个 sn-p 有点茫然:P @Zathrus - 随心所欲。只需确保在要隐藏/显示键盘时调用此函数即可。 嗯,这就是问题所在 - 无论我把它放在哪里,我都会收到一条错误消息:D @H2CO3 你能提供样品吗?我对 PhoneGap / X-Code 编码本身一无所知,所以目前这对我来说是一项不可能完成的任务【参考方案6】:实际上我刚刚找到了一个解决方案。 正如 horak 所说和 described in this article 所说,无论有没有软键盘,现在都可以使用 iOS 6.0 实现这一点:KeyboardDisplayRequiresUserAction = NO;
从 Cordova 2.2 开始,上面提到的 iOS 属性可以简单地添加到 Cordova.plist 文件中:
KeyboardDisplayRequiresUserAction, boolean, NO
这为所有使用 Cordova 2.2 的人解决了所有问题。现在只需像前面讨论的那样调用 input.focus(),键盘就会自动出现。对于我们这些尚未将 Cordova 更新到当前最新版本 (2.2) 的人来说,幸运的是仍有可能。
使用cordova v.以编程方式在iPhone上显示键盘
第 1 步: 向 Cordova.plist 添加属性
转到您的项目 > 资源 > Cordova.plist。添加:KeyboardDisplayRequiresUserAction, boolean, NO
第 2 步: 将下面的代码 sn-p 添加到 CDVViewController.m
搜索“@interface CDVViewController”(或类似于查找上述文件)。对于 Cordova 2.1,请转到 第 240 行(其他所有人都转到 "IsAtLeastiOSVersion" if 语句之后的一行,抱歉不能比这更准确了。)将这段代码 sn-p 添加到 CDVViewController.m 的上述行中:
if (IsAtLeastiOSVersion(@"6.0"))
BOOL keyboardDisplayRequiresUserAction = YES; // KeyboardDisplayRequiresUserAction - defaults to YES
if ([self.settings objectForKey:@"KeyboardDisplayRequiresUserAction"] != nil)
if ([self.settings objectForKey:@"KeyboardDisplayRequiresUserAction"])
keyboardDisplayRequiresUserAction = [(NSNumber*)[self.settings objectForKey:@"KeyboardDisplayRequiresUserAction"] boolValue]; //JB-VAL121212
// property check for compiling under iOS < 6
if ([self.webView respondsToSelector:@selector(setKeyboardDisplayRequiresUserAction:)])
[self.webView setValue:[NSNumber numberWithBool:keyboardDisplayRequiresUserAction] forKey:@"keyboardDisplayRequiresUserAction"];
免责声明:这仅在 Cordova 2.1 上进行了测试,但是,它很可能仍然适用于 2.0 或 CDVViewController.m 文件附带的任何其他早期版本)
【讨论】:
【参考方案7】:您可以在输入字段上使用 FocusOut 事件,当按下 Done 键时会触发该事件。我可以在 IOS 6 及更高版本上使用它。我相信它也适用于以前的版本。
【讨论】:
据我所知,从 iOS 6 开始,您可以告诉系统是否要在本地显示键盘 'onFocus()' - 所以我想那里不需要 FocusOut?以上是关于在 PhoneGap 应用程序中以编程方式在 iPhone 上显示软键盘?的主要内容,如果未能解决你的问题,请参考以下文章
通过 Phonegap 在 Android 中以编程方式设置静音模式