在 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中以编程方式更改页面

通过 Phonegap 在 Android 中以编程方式设置静音模式

如何在 iPhone sdk 中以编程方式获取设备名称?

是否可以在C ++中以编程方式查询不同的DNS名称服务器,忽略系统设置?

如何在iphone中以编程方式更改按钮文本

使用 ioctl 在 C++ 中以编程方式添加路由