开发者

UITextField embedded in an UIView does not respond to touch events

In my project i'm using a UITextField which is embedded into a plain white UIButton with rounded corners in order to create a "beautiful" text field. This code is used several times in different views so I decided to create a custom UIView for this purpose. The code for this custom UIView:

BSCustomTextField.h

#import <Foundation/Foundation.h>

@interface BSCustomTextField : UIView {
  UIButton* btnTextFieldContainer;
  UITextField* textField;
  NSString* text;
}

@property (retain, nonatomic) UIButton* btnTextFieldContainer;
@property (retain, nonatomic) UITextField* textField;
@property (retain, nonatomic) NSString* text;

-(id)initWithPosition:(CGPoint)position;
@end

BSCustomTextField.m

#import "BSCustomTextField.h"
#import <QuartzCore/QuartzCore.h>

@implementation BSCustomTextField
@synthesize btnTextFieldContainer, textField, text;

-(id)initWithPosition:(CGPoint)position{
   if (self == [super init]) {
      btnTextFieldContainer = [[UIButton alloc] initWithFrame:CGRectMake(position.x, position.y, 260, 50)];
      btnTextFieldContainer.backgroundColor = [UIColor whiteColor];
      [[btnTextFieldContainer layer] setCornerRadius:3.];
      [[btnTextFieldContainer layer] setMasksToBounds:YES];
      [[btnTextFieldContainer layer] setBorderWidth:0.];

      textField = [[UITextField alloc] initWithFrame:CGRectMake(10, 10, 240, 30)];

      textField.backgroundColor = [UIColor whiteColor];
      textField.clearButtonMode = UITextFieldViewModeAlways;
      textField.returnKeyType   = UIReturnKeySend;
      textField.keyboardType    = UIKeyboardTypeEmailAddress;
      textField.font               = [UIFont fontWithName:@"Helvetica-Bold" size:20.];

      [btnTextFieldContainer addSubview:textField];
      [self addSubview:btnTextFieldContainer];
   }
   return self;
}

-(void)dealloc{
   [btnTextFieldContainer release];
   [textField release];
   [super dealloc];
}
@end

So, when using this view in the viewDidLoad of the container view (see code below) the view is properly rendered on the desired position and looks exactly as specified but it does not react on touch events and thus does not become first responder when touched.

Code:

searchTextField = [[BSCustomTextField alloc] initWithPosition:CGPointMake(30, 150)];
searchTextField.textField.placeholder       = NSLocalizedString(@"lsUserName", @"");
[[(BSPlainHeaderWithBackButtonView*)self.view contentView] addSubview:searchTextField];

Calling [searchTextField.textField becomeFirstResponder] programmatically works properly and makes the keyboard to appear.

But, the interesting part is, if I embed the code of BSCustomTextField inline in my container just like this:

UIButton* btnTextFieldContainer = [[UIButton alloc] initWithFrame:CGRectMake(30, 150, 260, 50)];
btnTextFieldContainer.backgroundColor = [UIColor whiteColor];
[[btnTextFieldContainer layer] setCornerRadius:3.];
[[btnTextFieldContainer layer] setMasksToBounds:YES];
[[btnTextFieldContainer layer] setBorderWidth:0.];

searchTextField = [[UITextField alloc] initWithFrame:CGRectMake(10, 10, 240, 30)];

searchTextField.backgroundColor = [UIColor whiteColor];
searchTextField.clearButtonMode = UITextFieldViewModeAlways;
searchTextField.returnKeyType   = UIReturnKeySend;
searchTextField.keyboardType    = UIKeyboardTypeEmailAddress;
searchTextField.font            = [UIFont fontWithName:@"Helvetica-Bold" size:20.];
searchTextField.placeholder     = NSLocalizedString(@"lsUserName", @"");

[btnTextFieldContainer addSubview:searchTextField];
[[(BSPlainHeaderWithBackButtonView*)self.view contentView] addSubview:btnTextFieldContainer];
[btnTextFieldContainer release];

everything works as expected and the textfield reacts on touches. The type of the searchTextField is properly set in the header file for each case. The only difference is that in the first case I have an additional wrapping UIView on the UIButton and the UITextFiled. I have no idea what to do to make the text field to become first responder on touch.

Thanks a lot in ad开发者_如何学Govance, Roman


Ok, I've got the solution. raaz's point to the UIResponder class tipped me off to the idea that there must be something wrong in the responder chain, thus I did a little research and found this topic: Allowing interaction with a UIView under another UIView in which exact the same problem is discussed.
Here is the new working code for BSCustomTextField.m

#import "BSCustomTextField.h"
#import <QuartzCore/QuartzCore.h>


@implementation BSCustomTextField
@synthesize btnTextFieldContainer, textField, text;

-(id)initWithPosition:(CGPoint)position{
  if (self == [super init]) {
    btnTextFieldContainer = [[UIButton alloc] initWithFrame:CGRectMake(position.x, position.y, 260, 50)];
    btnTextFieldContainer.backgroundColor = [UIColor whiteColor];
    [[btnTextFieldContainer layer] setCornerRadius:3.];
    [[btnTextFieldContainer layer] setMasksToBounds:YES];
    [[btnTextFieldContainer layer] setBorderWidth:0.];

    textField = [[UITextField alloc] initWithFrame:CGRectMake(10, 10, 240, 30)];

    textField.backgroundColor = [UIColor whiteColor];
    textField.clearButtonMode = UITextFieldViewModeAlways;
    textField.returnKeyType   = UIReturnKeySend;
    textField.keyboardType    = UIKeyboardTypeEmailAddress;
    textField.font             = [UIFont fontWithName:@"Helvetica-Bold" size:20.];

    [btnTextFieldContainer addSubview:textField];
    [self addSubview:btnTextFieldContainer];
  }
  return self;
}

- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event {
    // UIView will be "transparent" for touch events if we return NO
    return YES;
}

-(void)dealloc{
  [btnTextFieldContainer release];
  [textField release];
  [super dealloc];
}
@end 

Since the clickable area fills out the entire BSCustomTextField view we can simply return YES in pointInside:withEvent:

Thank you all for pointing me into the right direction.


Refer UIResponder class

This class has instance method becomeFirstResponder: & isFirstResponder:

Also do not forget to set textfield editing property to YES


Oh, you're completely wrong with doing this way. You should add stretchable image into UIImageView and put it below UITextField.

UIImage *backgroundImage = [[UIImage imageNamed:@"fieldBackground.png"] stretchableImageWithLeftCapWidth:12.0 topCapHeight:0.0];

Or you can try to disable userInteraction in UIButton.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜