【问题标题】:keyboard in UIActionSheet does not type anythingUIActionSheet 中的键盘不输入任何内容
【发布时间】:2011-08-01 03:52:46
【问题描述】:

我想知道为什么由 UITextField 打开的 iPhone 键盘除了删除键和文本字段本身内的清除按钮之外没有输入任何内容。文本字段嵌入在带有此代码示例的 UIActionSheet 中:

// setup UITextField for the UIActionSheet
UITextField*    textField = [[UITextField alloc] initWithFrame:CGRectMake(8.0, 34.0, 304.0, 30.0)];
NSString*       startText = [[self.pathName lastPathComponent] stringByDeletingPathExtension];

textField.borderStyle     = UITextBorderStyleRoundedRect;
textField.backgroundColor = [UIColor whiteColor];
textField.clearButtonMode = UITextFieldViewModeAlways;
textField.text            = startText;
textField.delegate        = self;

[textField setKeyboardType:UIKeyboardTypeAlphabet];
[textField setKeyboardAppearance:UIKeyboardAppearanceAlert];

// setup UIActionSheet
UIActionSheet*  asheet = [[UIActionSheet alloc] initWithTitle: @"Please enter file name\n\n\n"
                                                     delegate: self
                                            cancelButtonTitle: @"Cancel"
                                       destructiveButtonTitle: nil
                                            otherButtonTitles: @"OK", nil];

if ([currentView isKindOfClass:[UIToolbar class]])
    [asheet showFromToolbar:(UIToolbar*)currentView];
else if ([currentView isKindOfClass:[UITabBar class]])
    [asheet showFromTabBar:(UITabBar*)currentView];
else
    [asheet showInView:currentView];

[asheet setFrame:CGRectMake(0.0, 60.0, 320.0, 380.0)];
[asheet insertSubview:textField atIndex:0];
[textField becomeFirstResponder];

// memory management
[textField release];
[asheet release];

我可以按 shift 键,但键不会变成小写,它们总是大写。好吧,我从来没有使用带有操作表的文本字段......我在这里做错了什么?操作表和文本字段的委托方法似乎根据需要存在。

编辑: 我也更改了操作表的视图关联和操作表的大小:

UIWindow*   appWindow = [UIApplication sharedApplication].keyWindow;

[asheet showInView:appWindow];
[asheet setFrame:CGRectMake(0.0, 60.0, 320.0, 204.0)];

while (CGRectEqualToRect(asheet.bounds, CGRectZero))
    ;

// Add the text field to action sheet
[asheet addSubview:textField];
[textField release];

现在键盘没有被操作表重叠(或“underlapped”),操作表正确显示在状态栏和导航栏下方,键盘跟随在操作表下方并自下而上。

但只有 textFieldShouldBeginEditingtextFieldDidBeginEditing 会调用文本字段的委托方法,仅此而已。当我点击它时,Shift键会改变,擦除键起作用,所有其他键都会在点击时显示出来 - 但不要插入到文本字段中。那么,这到底是怎么回事?

解决方案: 感谢 SVD 向我指出似乎不可能将 UITextField 嵌入 UIActionSheet 的事实。因为我希望有一个方法可以返回带有操作表的文件名字符串(只是因为我更喜欢外观而不是添加了文本字段的 UIAlertView),所以我花了更多的工作,终于找到了一个可行的解决方案。我在这里分享它是因为我意识到你们中的很多人都在寻找类似的东西。

要使其发挥作用,需要考虑两个主要方面:

  • 文本字段不能是操作表的子视图,至少在 处于可编辑状态的时刻

  • 操作表不应与键盘重叠

好的,代码来了。模态解决方案与第二个运行循环一起使用,因此可以在不返回调用者的情况下处理文本字段和操作表的委托方法 - 我相信这可以分解为处理所有委托内容的传统方法你自己的班级。

ModalAction.h:

#import <UIKit/UIKit.h>

@interface ModalAction : NSObject

+ (NSString*)ask: (NSString*)question
  withTextPrompt: (NSString*)prompt
      textPreset: (NSString*)preset
      dockToView: (UIView*)toView;

@end

ModalAction.m:

#import "ModalAction.h"

#define TEXT_FIELD_TAG      9999
#define ACTION_SHEET_TAG    8888

@interface ModalActionDelegate : NSObject <UIActionSheetDelegate, UITextFieldDelegate> 
{
    CFRunLoopRef    currentLoop;
    NSString*       text;
    NSUInteger      index;
}
@property (assign) NSUInteger index;
@property (retain) NSString* text;
@end


@implementation ModalActionDelegate
@synthesize index;
@synthesize text;

-(id)initWithRunLoop: (CFRunLoopRef)runLoop 
{
    if (self = [super init])
        currentLoop = runLoop;

    return self;
}

// Activate keyboard
- (void)acceptInput: (UIActionSheet*)actionSheet
{
    UITextField*    textField = (UITextField*)[actionSheet viewWithTag:TEXT_FIELD_TAG];
    UIWindow*       appWindow = [UIApplication sharedApplication].keyWindow;
    CGRect          frame     = textField.frame;

    [appWindow insertSubview:textField aboveSubview:actionSheet];
    frame.origin.y += 60.0; // move text field to same position as on action sheet
    textField.frame = frame;
    [textField becomeFirstResponder];
}

- (void)dealloc
{
    self.text = nil;
    [super dealloc];
}

#pragma mark -
#pragma mark === UIActionSheetDelegate ===
#pragma mark -

// User pressed button. Retrieve results
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
{
    NSLog(@"actionSheet clickedButtonAtIndex:%d", buttonIndex);
    UIWindow*       appWindow = [UIApplication sharedApplication].keyWindow;
    UITextField*    textField = (UITextField*)[appWindow viewWithTag:TEXT_FIELD_TAG];

    if (textField != nil)
        self.text = textField.text;

    self.index = buttonIndex;
    CFRunLoopStop(currentLoop);
}

#pragma mark -
#pragma mark === UITextFieldDelegate ===
#pragma mark -

- (BOOL)textFieldShouldBeginEditing:(UITextField*)textField
{
    NSLog(@"textFieldShouldBeginEditing");
    return YES;
}

- (void)textFieldDidBeginEditing:(UITextField*)textField
{
    NSLog(@"textFieldDidBeginEditing");
    [textField becomeFirstResponder];
}

- (BOOL)textFieldShouldEndEditing:(UITextField*)textField
{
    NSLog(@"textFieldShouldEndEditing");
    return YES;
}

- (void)textFieldDidEndEditing:(UITextField*)textField
{
    NSLog(@"textFieldDidEndEditing");
    [textField resignFirstResponder];
}

- (BOOL)textField:(UITextField*)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString*)string
{
    return YES;
}

- (BOOL)textFieldShouldClear:(UITextField*)textField
{
    NSLog(@"textFieldShouldClearEditing");
    return YES;
}

- (BOOL)textFieldShouldReturn:(UITextField*)textField
{
    NSLog(@"textFieldShouldReturn (%@)", textField.text);
    BOOL    hasSomeText = ![textField.text isEqualToString:@""];

    if (hasSomeText)
    {
        // send an OK to the action sheet
        UIWindow*       appWindow   = [UIApplication sharedApplication].keyWindow;
        UIActionSheet*  actionSheet = (UIActionSheet*)[appWindow viewWithTag:ACTION_SHEET_TAG];

        if (actionSheet != nil)
        {
            [actionSheet dismissWithClickedButtonIndex:0 animated:YES];
            self.text  = textField.text;
            self.index = 0;
            CFRunLoopStop(currentLoop);
            [textField resignFirstResponder];
        }
    }

    return hasSomeText;
}

@end


@implementation ModalAction

+ (NSString*)textQueryWith: (NSString*)question
                    prompt: (NSString*)prompt
                textPreset: (NSString*)preset
                   button1: (NSString*)button1
                   button2: (NSString*)button2
                   forView: (UIView*)toView
{
    // Create action sheet
    CFRunLoopRef            currentLoop = CFRunLoopGetCurrent();
    ModalActionDelegate*    madelegate  = [[ModalActionDelegate alloc] initWithRunLoop:currentLoop];
    NSString*               sheetTitle  = [question stringByAppendingString:@"\n\n\n"];
    UIActionSheet*          actionSheet = [[UIActionSheet alloc] initWithTitle: sheetTitle
                                                                      delegate: madelegate
                                                             cancelButtonTitle: button1
                                                        destructiveButtonTitle: nil
                                                             otherButtonTitles: button2, nil];
                            actionSheet.tag = ACTION_SHEET_TAG;

    // Build text field
    UITextField*    textField = [[UITextField alloc] initWithFrame:CGRectMake(8.0, 34.0, 304.0, 30.0)];

    textField.borderStyle = UITextBorderStyleRoundedRect;
    textField.tag         = TEXT_FIELD_TAG;
    textField.placeholder = prompt;
    textField.text        = preset;
    textField.delegate    = madelegate;
    textField.clearButtonMode          = UITextFieldViewModeWhileEditing;
    textField.keyboardType             = UIKeyboardTypeAlphabet;
    textField.keyboardAppearance       = UIKeyboardAppearanceAlert;
    textField.autocapitalizationType   = UITextAutocapitalizationTypeWords;
    textField.autocorrectionType       = UITextAutocorrectionTypeNo;
    textField.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
    textField.returnKeyType            = UIReturnKeyDone;

    // Show action sheet and wait for it to finish displaying
    UIWindow*   appWindow = [UIApplication sharedApplication].keyWindow;

    [actionSheet showInView:appWindow];
    [actionSheet setFrame:CGRectMake(0.0, 60.0, 320.0, 204.0)];

    while (CGRectEqualToRect(actionSheet.bounds, CGRectZero))
        ;

    // Add the text field to action sheet
    [actionSheet addSubview:textField];
    [textField release];

    // Set the field to first responder and move it into place
    [madelegate performSelector: @selector(acceptInput:) withObject: actionSheet];

    // Start the run loop
    CFRunLoopRun();

    // Retrieve the user choices
    NSUInteger  index  = madelegate.index;
    NSString*   answer = [[madelegate.text copy] autorelease];

    if (index == 1)
        answer = nil;   // assumes cancel in position 1

    [textField resignFirstResponder];
    [actionSheet release];
    textField.delegate = nil;
    [textField removeFromSuperview];
    [madelegate release];

    return answer;
}

+ (NSString*)ask: (NSString*)question
  withTextPrompt: (NSString*)prompt
      textPreset: (NSString*)preset
      dockToView: (UIView*)toView
{
    return [ModalAction textQueryWith: question
                               prompt: prompt
                           textPreset: preset
                              button1: NSLocalizedString(@"AlertBtnCancel", @"")
                              button2: @"OK"
                              forView: toView];
}

@end

它在模拟器 iOS 4.2 和真实设备的 iOS 4.0.2 上运行 - 我希望它对其他人也有帮助。

【问题讨论】:

    标签: iphone keyboard uitextfield uiactionsheet


    【解决方案1】:

    关于操作表的一个奇怪的事情是,例如,如果有一个标签栏,标签栏可能会“窃取”一些操作表的点击,即使在视觉上操作表在顶部。

    您的操作表是 380 像素高 - 因此当键盘滑出时,它会与操作表重叠。也许在这种情况下,是动作表窃取了键盘的点击?尝试使操作表更小更靠近顶部 - 例如为了测试这个想法,我只是让它起源于 0,0 和 240 像素高。

    编辑:

    显然这是一个问题 - 在没有标签栏或工具栏的简单测试应用程序中,它对我不起作用。我找到了这些链接:

    使用警报视图执行此操作,它似乎有效(尽管它似乎只适用于警报视图): https://discussions.apple.com/thread/1674641

    这里有人制作了自己的“行动表”: how to enable text input in UITextField which is in UIActionSheet?

    【讨论】:

    • 谢谢,这听起来很有道理——不幸的是它没有成功。没有任何改变(除了操作表现在真的在键盘上方)。是否有必要在 UI 显示操作表之后长时间延迟后使文本字段成为第一响应者?用 UIAlertView 代替可能会更好吗? (我选择了一个操作表,因为它与“嵌入式”键盘的外观一致)
    • 也许了解这一点很重要:此操作表方法的调用方视图控制器位于导航控制器堆栈上,并且它具有关联的工具栏。所以我为 currentView 提供工具栏。
    • 感谢 SVD。我将您的答案标记为正确,因为对我来说最重要的是它不起作用 - 采用标准方法。我之前也找到了您的第二个链接,但这并不是我想要的。在上面我自己的解决方案中,我必须将文本字段的子视图所有权重新排序到主窗口,以便它可以触摸键盘。
    猜你喜欢
    • 1970-01-01
    • 2023-03-14
    • 1970-01-01
    • 1970-01-01
    • 2020-09-09
    • 1970-01-01
    • 2010-09-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多