UITextField embedded in a UIView not responding to touch events - ios

Why does a UITextField not respond to touch events when embedded in a UIView (which itself is embedded in the original view controller's main UIView)?
Here's the code:
- (void)loadView
{
self.view = [UIView new];
UIView *positionalView = [[UIView alloc] initWithFrame:CGRectMake(20, 100, 280, 100)];
UITextField *usernameField = [[UITextField alloc] initWithFrame:CGRectMake(0, 0, 280, 50)];
usernameField.placeholder = #"Full Name";
usernameField.delegate = self;
[usernameField addTarget:self action:#selector(textFieldChanged:) forControlEvents:UIControlEventEditingChanged];
[positionalView addSubview:usernameField];
UITextField *passwordField = [[UITextField alloc] initWithFrame:CGRectMake(0, 0, 280, 50)];
passwordField.placeholder = #"Password";
passwordField.delegate = self;
[passwordField addTarget:self action:#selector(textFieldChanged:) forControlEvents:UIControlEventEditingChanged];
[positionalView addSubview:passwordField];
[self.view addSubview:positionalView];
}
Finding it difficult to understand this behavior as the above code works fine, if I simply remove the positionalView and add the text fields directly to the main self.view.
Can anyone explain this?

You create a local variable named positionalView, but add the text fields to a property named positionalView. These are not the same variables.

The parent UIView's size is zero, pin the top, bottom, left and right constraints of the UITextField to the parent view so the parent view's size is the size of the UITextField, or set the frame of the parent UIView so that it has a size that is not zero.
Check the Debug View Hierarchy debug tool to check!

You need bringSubviewToFront::
[positionalView addSubview:usernameField];
[positionalView bringSubviewToFront:usernameField];
Same for passwordField and positionalView

Related

How to add UIButton as bottomView to UIView?

I have a UIView class, and in xib also I have a MainView which is a UIView. I want to add UIButton as bottomView to the View.I need to give bottom space 16 between MainView and bottomView. How do I do it?
self.bottomView = [[UIView alloc] initWithFrame:CGRectMake(0, self.MainView.bounds.size.height +30, self.MainView.bounds.size.width, 40.0)];
[self.bottomView setBackgroundColor:[UIColor greenColor]];
self.selectBtn= [UIButton buttonWithType: UIButtonTypeRoundedRect];
[self.selectBtn setFrame:CGRectMake(0,20,100,40)];
[self.selectBtn setTitle:#"Select" forState:UIControlStateNormal];
[self.selectBtn addTarget:self action:#selector(selectButtonTapped:) forControlEvents:UIControlEventTouchUpInside];
[self.bottomView addSubview:self.selectBtn];
[self addSubview:self.bottomView];
Expected result
Output from above code
Please find you have added button on this frame
self.bottomView = [[UIView alloc] initWithFrame:CGRectMake(0, self.MainView.bounds.size.height +30, self.MainView.bounds.size.width, 40.0)];
Here you have made the y as height + 30 so it is not visible to the view.
You should use this.
self.bottomView = [[UIView alloc] initWithFrame:CGRectMake(0, self.MainView.bounds.size.height - 40, self.MainView.bounds.size.width, 40.0)];
Also if you want 16 pixel gap you should the view above it with the same approach.
Please let me know if you need any more help

UITextFields aren't allowing me to edit text

I've programmatically created two UITextFields in my iOS app, and set their text to the _minPrice and _minPrice variables, respectively.
The _minPrice and _maxPrice values appear correctly in the two fields, but tapping on them doesn't allow the user to edit them, they just remain those static values, backspacing doesn't work. Is there anything about my code thats preventing the text fields from being edited?
// Min Price
UITextField *tf = [[UITextField alloc] initWithFrame:CGRectMake(-25, -76, 70, 30)];
tf.textColor = [UIColor blackColor];
tf.font = [UIFont fontWithName:#"Helvetica-Neue" size:14];
tf.backgroundColor=[UIColor whiteColor];
tf.text= _minPrice;
tf.textAlignment = NSTextAlignmentCenter;
tf.layer.cornerRadius=8.0f;
tf.layer.masksToBounds=YES;
tf.layer.borderColor=[[UIColor lightGrayColor]CGColor];
tf.layer.borderWidth= 1.0f;
// Max Price
UITextField *tf1 = [[UITextField alloc] initWithFrame:CGRectMake(100, -76, 70, 30)];
tf1.textColor = [UIColor blackColor];
tf1.font = [UIFont fontWithName:#"Helvetica-Neue" size:14];
tf1.backgroundColor=[UIColor whiteColor];
tf1.text= _maxPrice;
tf1.textAlignment = NSTextAlignmentCenter;
tf1.layer.cornerRadius=8.0f;
tf1.layer.masksToBounds=YES;
tf1.layer.borderColor=[[UIColor lightGrayColor]CGColor];
tf1.layer.borderWidth= 1.0f;
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(100, 200, 400, 400)];
[view addSubview:tf];
[view addSubview:tf1];
[self.view addSubview:view];
Your issue is clearly the frames you're setting...
Setting the color of the view you add the labels to to blue reveals your problem:
If you ensure that the labels are actually within the view you add them to (i.e. not negative), editing will be fine. All I did was change the negative x and y values in tf to positive, and they were editable:
UITextField *tf = [[UITextField alloc] initWithFrame:CGRectMake(25, 76, 70, 30)];
Try this! Maybe there is another view at the top of the textField
your_textfield.userInteractionEnabled = YES;
If this doesn't work
add another line
[self.view bringSubviewToFront: your_textfield];
Try to add delegate methods on your textfields. Like
- (void) textFieldDidEndEditing:(UITextField *)textField
{
// ADD BREAKPOINT HERE.
}
Check if it goes to that line of code. If not maybe there's a view on top of it. Or you can try to bring textfield to front like .
[self.view bringSubviewToFront:yourTextfield];
But this isn't a good example of how you fix the problem. Just to test if there is a view on top of it.

Why does UISearchBar's UITextField not respond like a normal UITextField to a rightview?

I'm having trouble implementing a UISearchBar whose UITextField has a rightview. I tried on a normal UITextField the following:
self.textField = [[UITextField alloc] initWithFrame: CGRectMake(10, 30, 300, 30)];
self.textField.borderStyle = UITextBorderStyleRoundedRect;
self.textField.clearButtonMode = UITextFieldViewModeNever;
self.textField.delegate = self;
UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(0, 100, 150, 44)];
[button setBackgroundColor: [UIColor redColor]];
[self.textField setRightViewMode:UITextFieldViewModeAlways];
[self.textField setRightView:button];
[self.view addSubview:self.textField];
And as expected, it generates the following:
I need the UISearchBar's UITextField to be have the same -- so I decided to subclass UISearchBar.
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// This is simply here to make sure that we are able to get the textfield
[self setSearchTextPositionAdjustment:UIOffsetMake(0, 0)];
// Function that helps us get the textfield
UITextField *textField = [self textFieldGetter];
// This will be true if we call setSearchTextFieldPositionAdjust
if (textField) {
// Verify that the textfield exists...
NSLog(#"The textField does exist");
UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(0, 100, 150, 44)];
[button setBackgroundColor: [UIColor redColor]];
// Set the clear button to be off
textField.clearButtonMode = UITextFieldViewModeNever;
// Make the button the rightview of the textfield
[textField setRightView:button];
[textField setRightViewMode:UITextFieldViewModeAlways];
}
}
return self;
}
But it does not work and the UISearchBar simply looks like:
The UITextFieldGetter is in essence something very similar to this answer.
Why isn't the UITextField the same in the UISearchBar as it is normally? Is there a way that I can get the same effect programmatically? Or if it can't be done, is there a way that I can change the UITextField's width once I know the button is there?

My UIView has a UIButton as one of it's subviews but not responding to events in objective-c

Here is my code. It has started to look crowded after an hour or 2 of trying to solve this issue. I've tried setting user interaction enabled to yes, I've tried just using a button alone and not making it the subview of another view.
Right now I have filterBar > filterBarContainer > filterButton.
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
self.navigationController.navigationBar.userInteractionEnabled = YES;
self.view.userInteractionEnabled = YES;
// Create filter bar with specified dimensions
UIView *filterBar = [[UIView alloc] initWithFrame:CGRectMake(0, 42, self.view.frame.size.width, self.navigationController.navigationBar.frame.size.height)];
[filterBar setUserInteractionEnabled:YES];
// Make it a subview of navigation controller
[[[self navigationController] navigationBar] addSubview:filterBar];
[filterBar setBackgroundColor:[[UIColor whiteColor] colorWithAlphaComponent:0.9f]];
[filterBar setTag:1];
// Reusable vars
// CGFloat filterBarX = filterBar.frame.origin.x;
//CGFloat filterBarY = filterBar.frame.origin.y;
CGFloat filterBarHeight = filterBar.frame.size.height;
CGFloat filterBarWidth = filterBar.frame.size.width;
// Create centre filter button with specified dimensions
UIView *filterButtonContainer = [[UIView alloc] initWithFrame:CGRectMake(0, 2, filterBarWidth / 2 - 30 , filterBarHeight - 10)];
[filterButtonContainer setUserInteractionEnabled:YES];
// Make it a subview of filter bar
[filterBar addSubview:filterButtonContainer];
[filterButtonContainer setBackgroundColor:[UIColor redColor]];
// Centre the button
[filterButtonContainer setCenter:[filterBar convertPoint:filterBar.center fromView:filterBar.superview]];
// Add button to filter button
UIButton *filterButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[filterButton setUserInteractionEnabled: YES];
[filterButton setFrame:CGRectMake(0, 0,40 , 20)];
[filterButton setTitle:#"test" forState:UIControlStateNormal];
[filterButtonContainer addSubview:filterButton];
[filterButton setBackgroundColor:[UIColor yellowColor]];
// self.filterButton = filterButton;
[filterButton addTarget:self action:#selector(filterButtonTapped:) forControlEvents:UIControlEventTouchUpInside];
NSLog(#"dd");
filterButtonContainer.layer.borderColor = [UIColor blackColor].CGColor;
filterButtonContainer.layer.borderWidth = 1;
This is the method I'm trying to trigger.
- (void)filterButtonTapped:(UIButton *)sender
{
NSLog(#"filter button tapped");
UIActionSheet *filterOptions = [[UIActionSheet alloc] initWithTitle:#"Filter Garments"
delegate:self
cancelButtonTitle:#"Cancel"
destructiveButtonTitle:nil
otherButtonTitles:#"Recommended", #"What's New", #"Price - High to Low", #"Price - Low to High", nil];
[filterOptions showInView:self.collectionView];
}
Most likely one of your parent views (superviews of your button) have a width or height that places the filter button outside of their area. The button is still displayed (if you don't define that the view should cut off subviews), but elements outside the view's area will not get any touch events. Check your superview's width and height.
You're adding filterBar as a subview of your navigationBar, but you're setting it's y-origin within navigationBar to 42. And then you're setting your filterButtonContainer's y-origin within the filterBar to 2. Assuming navigationBar's height is 44, most of the filterBar and the entirety of your filterButtonContainer and filterButton won't be within their navigationBar superview so the button wouldn't be selectable.
Edit: To make it selectable while keeping the positioning intact, I suggest adding the filter bar to self.view. For example, change:
[[[self navigationController] navigationBar] addSubview:filterBar];
to
[self.view addSubview:filterBar];

Subview of custom UIButton class doesn't trigger click

I'm writing a custom UIButton subclass, to create my own fully customized button
to have total controll. Still, I'm having problems when I try to add a subview
to that UIButton's view. The subview blocks the "touch" events so it won't bubble to
the UIButton itself..
This is a demonstration:
I first create my CustomNavigationButton, with a frame.. It's magenta.
I can see the magenta on the screen so it's there. Secondly, I add a subview
to that CustomNavigationButton (which is green), I can see the green so it's
there, but if I click the green rectangle (subview), the "UIControlEventTouchUpInside"
doesn't get called on my CustomNavigationButton..
In my AppDelete:
CustomNavigationButton* mapBtn = [[CustomNavigationButton alloc] initWithFrame:CGRectMake(0, 0, 100, 25)];
mapBtn.backgroundColor = [UIColor magentaColor];
[mapBtn addTarget:self action:#selector(goMapHandler:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:mapBtn];
And here's my CustomNavigationButton class (which is a subclass of UIButton)
#implementation CustomNavigationButton
#synthesize bg;
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// STORE INITIAL FRAME
self.initialFrame = frame;
bg = [[UIView alloc] initWithFrame:CGRectMake(0, 20, 40, 40)];
bg.backgroundColor = [UIColor greenColor];
[bg setUserInteractionEnabled:YES];
[self addSubview:bg];
}
return self;
}
#end
I figured out how to do it!
If "bg" is the subview I'm adding to the UIButton, then you should do:
bg.userInteractionEnabled = NO;
bg.exclusiveTouch = NO;
But keep in mind that, if your subview extends the frame of the UIButton,
a touch will not occur! You can check if your subview exceeds the UIButton
by giving the UIButton a background-color.

Resources