27

我一直在寻找很长时间,到目前为止,我还没有遇到一个可以以编程方式显示软键盘的 PhoneGap / Cordova 应用程序的工作解决方案。

设想:

我们有一个PhoneGap 应用程序——一个用jQuery Mobile 创建的网站——它在某一时刻向用户显示一个对话框。此对话框也是一个网页,并且有一个单一的 INPUT 文本框,用户应在其中输入代码。

问题:

当显示代码对话框时,输入框使用 JavaScript 聚焦。然而,由于 iPhone 内部浏览器的限制,软键盘直到用户真正点击输入文本框后才会出现。

我们尝试了什么:

  • 创建一个隐藏的文本框并使其成为第一响应者
  • 一旦输入通过 JavaScript 获得焦点,使实际的webview 成为第一响应者
  • 使用sendActionsForControlEvents尝试将 Touch 事件传递给 webview(尽管如果有人有 PhoneGap 应用程序的工作代码,如果他们能分享它,我将不胜感激,因为我不是 iOS 编码方面的专业人士)

有任何想法吗?


编辑:这个问题中提到的限制仅适用于内置浏览器......如果您的目标是 Opera,您将通过使用以下代码获得成功:

var e = jQuery.Event("keydown", { keyCode: 37 });
$('#element').focus().trigger(e);

EDIT2:这是可以在插件中使用的最终工作PhoneGap代码:

键盘助手.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

键盘助手.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);
    }
};
4

7 回答 7

12

config.xml这些天您可以通过条目解决问题,添加:

<preference name="keyboardDisplayRequiresUserAction" value="false" />
于 2014-03-26T20:10:12.197 回答
7

您可以在 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];
于 2012-09-05T10:12:08.020 回答
4

在 iOS 6 之前,Apple 只允许在用户交互后调出键盘。在 iOS 6 中,他们为 UIWebView 引入了以下属性,您只需将其设置为 NO。

    "yourWebView".keyboardDisplayRequiresUserAction = NO;

Apple 默认将此设置为“是”。现在你可以调用focus()你的 JS,然后键盘就会出现。

于 2012-10-22T16:44:59.727 回答
3

您是否尝试过使用 Native Controls 并从 Javascript 调用它们?

这里有一些代码显示了在 Phonegap Cordova 应用程序(Phonegap 1.5)上使用本机控件

https://gist.github.com/1384250

希望它有助于解决问题:)

于 2012-08-29T12:31:25.453 回答
3

我承认这是私人的,但它可能会帮助你:

@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();
于 2012-08-29T12:38:38.477 回答
3

我实际上只是找到了解决方案。就像 horak 说的和本文中描述的那样,无论有没有软键盘,现在都可以使用 iOS 6.0 来实现这一点:KeyboardDisplayRequiresUserAction = NO;

从 Cordova 2.2 开始,可以简单地将上面提到的 iOS 属性添加到Cordova.plist文件中:

KeyboardDisplayRequiresUserAction, boolean, NO

这为使用 Cordova 2.2 的每个人解决了所有问题。现在只需像之前讨论的那样调用input.focus(),键盘就会自动出现。对于我们这些尚未将我们的 Cordova 更新到当前最新版本 (2.2) 的人来说,幸运的是仍然可以

使用 cordova v. < 2.2 以编程方式在 iPhone 上显示键盘

第 1 步向 Cordova.plist 添加属性

转到您的项目 > 资源 > Cordova.plist。添加:KeyboardDisplayRequiresUserAction,布尔值,否

第 2 步将以下代码片段添加到 CDVViewController.m

搜索“@interface CDVViewController”(或类似于找到上述文件)。对于 Cordova 2.1,转到第 240 行(其他所有人都转到“ IsAtLeastiOSVersion ” if 语句之后的一行,抱歉不能比这更精确。)将此代码段添加到上述行的 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 文件附带的任何其他早期版本)

于 2012-12-10T21:26:32.363 回答
0

您可以在输入字段上使用 FocusOut 事件,这将在按下 Done 键时触发。我可以在 IOS 6 及更高版本上使用它。我相信它也适用于以前的版本。

于 2013-02-16T02:33:49.847 回答