How to fix offset keyboard when UISearchbar is touched - ios

The problem I'm having is that when a user touches into the search bar the keyboard appears fine. Then when the presentQR method (see below) is called and then dismissed and then the searchbar is touched the keyboard appears as shown in the screenshot where it is offset. This is iOS7; not sure if that matters though.
I'm adding a UISearchbar using the following code:
// search bar
UIView *searchBarView = [[UIView alloc] initWithFrame:CGRectMake(90.0, 0.0, 200.0, 44.0)];
searchBarView.autoresizingMask = 0;
searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0, 0, 190, 40)];
searchBar.backgroundImage = [[UIImage alloc] init];
searchBar.autoresizingMask = UIViewAutoresizingFlexibleWidth;
self.navigationItem.titleView = searchBar;
searchBar.delegate = self;
[[UIBarButtonItem appearanceWhenContainedIn:[UISearchBar class], nil] setTitleTextAttributes:[NSDictionary dictionaryWithObjectsAndKeys:[UIColor whiteColor],UITextAttributeTextColor,[UIColor whiteColor],UITextAttributeTextShadowColor,[NSValue valueWithUIOffset:UIOffsetMake(0, -1)],UITextAttributeTextShadowOffset, nil] forState:UIControlStateNormal];
UITextField *textfield = [[UITextField alloc] init];
searchBar.placeholder = #"City Search";
// hide magnifying glass
textfield = nil;
for (UIView* subView in searchBar.subviews) {
if ([subView isKindOfClass:[UITextField class]]) {
textfield = (UITextField*)subView;
[(UITextField*)subView setTextColor:[UIColor whiteColor]];
[(UITextField*)subView setFont:[UIFont fontWithName:#"DIN-Regular" size:18]];
textfield.leftViewMode = UITextFieldViewModeNever;
textfield.rightViewMode = UITextFieldViewModeAlways;
break;
}
}
UIButton *cancelButton;
for (id button in searchBar.subviews)
{
if ([button isKindOfClass:[UIButton class]])
{
cancelButton=(UIButton*)button;
break;
}
}
[searchBar addSubview:textfield];
[searchBarView addSubview:searchBar];
self.navigationItem.titleView = searchBarView;
-(void)presentQR {
QRReaderViewController *qr = [[QRReaderViewController alloc]initWithNibName:#"QRReaderViewController" bundle:nil];
UIButton *removeQRBtn=[UIButton buttonWithType:UIButtonTypeCustom];
removeQRBtn.frame=CGRectMake(260, 10, 60, 40);
[removeQRBtn addTarget:self action:#selector(removeQR) forControlEvents:UIControlEventTouchDown];
[removeQRBtn setImage:[UIImage imageNamed:#"qrcode.png"] forState:0];
[qr.view addSubview:removeQRBtn];
qr.view.backgroundColor = customColorGrey;
qr.modalPresentationStyle = UIModalTransitionStyleCrossDissolve;
// [self presentModalViewController:qr animated:YES];
[self presentViewController:qr animated:YES completion:nil];
}
-(void)removeQR {
// [self dismissModalViewControllerAnimated:YES];
[self dismissViewControllerAnimated:YES completion:nil];
}

1st Make sure that in QRReaderViewController there is nothing like reframing window or such. There might be an element conflicting with UIWindow preventing keyboard to be shown correctly. (e.g unbalanced orientation changes.)
2nd If you didn't find anything there you could try accessing the keyboard view using the following code and attempt to reset the frame. You could put this code in keyboardWillShow method (need to register for the notification)
https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIWindow_Class/UIWindowClassReference/UIWindowClassReference.html#//apple_ref/c/data/UIKeyboardWillShowNotification
PS. I would suggest to just log the keyboard frame so you know when it's changed.
Reframing Keyboard: Found here: https://stackoverflow.com/a/10957843/1017340
//The UIWindow that contains the keyboard view - It some situations it will be better to actually
//You need to iterate through each window to figure out where the keyboard is, but In my applications case
//I know that the second window has the keyboard so I just reference it directly
UIWindow* tempWindow = [[[UIApplication sharedApplication] windows] objectAtIndex:1];
//Because we cant get access to the UIPeripheral throughout the SDK we will just use UIView.
//UIPeripheral is a subclass of UIView anyways
UIView* keyboard;
//Iterate though each view inside of the selected Window
for(int i = 0; i < [tempWindow.subviews count]; i++)
{
//Get a reference of the current view
keyboard = [tempWindow.subviews objectAtIndex:i];
//Assuming this is for 4.0+, In 3.0 you would use "<UIKeyboard"
if([[keyboard description] hasPrefix:#"<UIPeripheral"] == YES)
{
NSLog(#"Keyboard Frame: %#",NSStringFromCGRect(keyboard.frame));
//HERE : try reframing the keyboard
//[keyboard setFrame:CGRectMake(...)]; /*NOT TESTED NOT RECOMMENDED*/
}
}

Related

Custom View above a keyboard not working in ios9

Have added a custom view consisting of buttons on top of the keyboard. The buttons are being displayed correctly but on tapping on the buttons, the underlying keys of the keyboard are pressed instead of the button actions.
UIWindow* tempWindow = [UIApplication sharedApplication].windows.lastObject;
for (UIView *keyboard in [tempWindow subviews]) {
if ([[keyboard description] hasPrefix : #"<UIInputSetContainerView"]) {
for(int i = 0 ; i < [keyboard.subviews count] ; i++)
{
UIView* hostkeyboard = [keyboard.subviews objectAtIndex:i];
if([[hostkeyboard description] hasPrefix:#"<UIInputSetHost"] == YES){
[hostkeyboard addSubview:extraRow];
[hostkeyboard bringSubviewToFront:extraRow];
}
}
}
}
extraRow is the UIView consisting of buttons.
Is there anything missing ?
You could do just add a custom view to the keyboard as an inputAccessoryView. Then it just assign the button the correct target you want it to fire when clicked on
- (void)textFieldDidBeginEditing:(UITextField *)textField {
UIView * theView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 200)];
[theView setBackgroundColor: [UIColor greyColor]];
UITextField * txtTest = [[UITextField alloc] initWithFrame:CGRectMake(0, 5, theView.frame.size.width, 60)];
UIButton * btn = [[UIButton alloc] initWithFrame:CGRectMake(20, 65, 100, 30)];
[btn setTitle:#"Click my Button" forState:UIControlStateNormal];
[btn addTarget:self action:#selector(alert:) forControlEvents:UIControlEventTouchUpInside];
// Just put this to see the items or customize the color
[txtTest setBackgroundColor:[UIColor whiteColor]];
[btn setBackgroundColor:[UIColor blueColor]];
// Need this to add it to the view
[theView addSubview:txtTest];
[theView addSubview:btn];
textField.inputAccessoryView = theView;
}
One thing you might want to consider is setting the extraRow's exclusiveTouch property to YES. As a disclaimer I haven't tried this example myself but I think the problem you are having is due to the view passing along the touch event.

Custom UIAlertView not resizing for keyboard after its 1st appearance

I have a custom UIAlertVIew with 2 textFields that I am using to input values into. The first time that the customUIAlertVIew is displayed, the view is moved up to make room for the keyboard.
This is unfortunately, not the case for each subsequent display. Each subsequent time, the alertView isn't moved up for the keyboard.
I am looking for what is causing this problem, and how can I get around it in the future.
EDIT: Here is the code for how the custom UIAlertVIew is created.
CustomUIAlertView.m
-(id)initWithTitle:(NSString *)title {
if (self = [super init]){
self.title = title;
self.message = #"\n\n\n\n\n\n";
[self addButtonWithTitle:#"Cancel"];
[self addButtonWithTitle:#"Done"];
[self setDelegate:self];
}
return self;
}
-(void)didPresentAlertView:(UIAlertView *)alertView{
NSArray *subViews = [UIApplication sharedApplication].keyWindow.rootViewController.
presentedViewController.view.subviews;
if (subViews.count >1){
UIView *presentedView = [subViews objectAtIndex:1];
UILabel *player1Label = [[UILabel alloc]initWithFrame:CGRectMake(20, 55, 130, 21)];
player1Label.text = [NSString stringWithFormat:#"Player 1 Score"];
// player1Label.textInputMode = UIKeyboardTypeNumberPad;
player1Label.tag = 42;
[presentedView addSubview:player1Label];
UILabel *player2Label = [[UILabel alloc]initWithFrame:CGRectMake(20, 75, 130, 21)];
player2Label.text = [NSString stringWithFormat:#"player 2 Score"];
player2Label.tag = 43;
[presentedView addSubview:player2Label];
self.p1ScoreField = [[UITextField alloc]initWithFrame:CGRectMake(150, 55, 80, 21)];
self.p1ScoreField.placeholder= #"score";
self.p1ScoreField.tag = 44;
self.p1ScoreField.keyboardType = UIKeyboardTypeNumberPad;
self.p1ScoreField.borderStyle = UITextBorderStyleRoundedRect;
self.p1ScoreField.delegate = self;
[self.p1ScoreField addTarget:self action:#selector(UITextFieldDidChange:) forControlEvents:UIControlEventEditingChanged];
[presentedView addSubview:self.p1ScoreField];
self.p2ScoreField = [[UITextField alloc]initWithFrame:CGRectMake(150, 75, 80, 21)];
self.p2ScoreField.tag = 45;
self.p2ScoreField.placeholder = #"score";
self.p2ScoreField.keyboardType = UIKeyboardTypeNumberPad;
self.p2ScoreField.borderStyle = UITextBorderStyleRoundedRect;
self.p2ScoreField.delegate = self;
[self.p2ScoreField addTarget:self action:#selector(UITextFieldDidChange:) forControlEvents:UIControlEventEditingChanged];
[presentedView addSubview:self.p2ScoreField];
}
}
View presented in a separate view Controller. Alloc/Init is called on alertView at the viewDidAppear method.
- (IBAction)addNewRoundButtonPressed:(id)sender {
[alertView show];
}
Adding subviews to UIAlertView is not supported by Apple and is strongly discouraged.
You're better off using a regular view controller with custom modal presentation (look up UIViewControllerAnimatedTransitioning) or Googling a 3rd-party replacement.

UISearchBar's text field. right view not showing

What i'm trying to implement is to move UISearchBar's magnifier icon from the left edge of the text field to the right edge. This is how i do that:
searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, FRSearchMaxHeight)];
searchBar.delegate = self;
searchBar.placeholder = NSLocalizedString(#"Search friends", "");
searchBar.showsCancelButton = NO;
UIView *view = [searchBar subviewConformingToProtocol:#protocol(UITextInput)];
UIView<UITextInput> *textInputView = (UIView<UITextInput> *)view;
[textInputView setReturnKeyType:UIReturnKeyDone];
[textInputView setKeyboardAppearance:UIKeyboardAppearanceAlert];
tableView.tableHeaderView = searchBar;
UIImage *image = [UIImage imageWithColor:[UIColor colorWithRed:0.9f green:0.9f blue:0.9f alpha:0.9f] size:searchBar.frame.size];
[searchBar setBackgroundImage:image];
textInputView.layer.cornerRadius = 0.f;
textInputView.layer.borderWidth = 1.f;
textInputView.layer.borderColor = [UIColor lightGrayColor].CGColor;
UIView *magnifier = [(UITextField *)textInputView leftView];
[(UITextField *)textInputView setRightView:magnifier];
[(UITextField *)textInputView setLeftViewMode:UITextFieldViewModeNever];
[(UITextField *)textInputView setRightViewMode:UITextFieldViewModeAlways];
however the magnifier is never shown. It vanishes. I checked frame like this:
NSLog(#"FRAME %#", NSStringFromCGRect(((UITextField *)textInputView).rightView.frame));
and it says: FRAME {{0, 0}, {12.5, 12.5}}. What am i missing?

Remove a subview from UIViewController

I'm adding a subview to the main view but then I cant remove it from this view.
NextViewController *nextView = [[NextViewController alloc] init];
nextView.transitioningDelegate = self;
nextView.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
[self.presentedViewController.view addSubview:nextView.view];
nextView.view.frame = CGRectMake(724, 80, 300, 150);
UIButton *stayButton = [[UIButton alloc] initWithFrame:CGRectMake(101, 94, 90, 49)];
[stayButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
[stayButton setTitle:#"Detener" forState:UIControlStateNormal];
[stayButton addTarget:self
action:#selector(waitForNextView)
forControlEvents:UIControlEventTouchUpInside];
[nextView.view addSubview:stayButton];
stayButton.titleLabel.font = [UIFont systemFontOfSize:25];
[stayButton setTitleColor:[UIColor colorWithRed:(255/255.0) green:(255/255.0) blue:(255/255.0) alpha:1] forState:UIControlStateNormal];
here I'm adding a button to the view and then when the button is pushed it goes`-
(void)waitForNextView{
transition = NO;
NextViewController *nextView = [[NextViewController alloc] init];
SectionViewController *sectionView = [[SectionViewController alloc]init];
[self.locationManager stopRangingBeaconsInRegion:self.beaconRegion];
actualSection = 0;
[NSTimer scheduledTimerWithTimeInterval:10.0 target:self selector:#selector(dismissView2) userInfo:nil repeats:NO];
}
I've tried with:
[nextView.view removeFromSuperView];
[nextView.presentedViewController removeFromParentViewController];
But I don't know what else can I do :S
If you want more information, nextView is a UIViewController of 300x100 size. I want to present it and then remove it when I hit the button, that's all.
I would be great if someone can help me.
Thanks
You are creating different reference and then you're trying to remove it from its superview while not being added at all. I will try to explain:
1. When you're adding nextView.view to self.view you have created a instance like this
NextViewController *nextView = [[NextViewController alloc] init];
2. When you're trying to remove it, instead of referring to the instance above you're creating a brand new one again in your waitForNextView method like so again
NextViewController *nextView = [[NextViewController alloc] init];
and then you're trying to remove it. Please note that the last instance of nextView has not being added anywhere yet, and this is the reason your code doesn't work.
In order to work you should refer to the first reference you've added to self.view. Please adjust your code as shown below
In your ViewController.m
#interface ViewController()
{
NextViewController *nextView;
}
When adding your viewController
nextView = [[NextViewController alloc] init];
nextView.transitioningDelegate = self;
nextView.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
[self.presentedViewController.view addSubview:nextView.view];
nextView.view.frame = CGRectMake(724, 80, 300, 150);
UIButton *stayButton = [[UIButton alloc] initWithFrame:CGRectMake(101, 94, 90, 49)];
[stayButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
[stayButton setTitle:#"Detener" forState:UIControlStateNormal];
[stayButton addTarget:self
action:#selector(waitForNextView)
forControlEvents:UIControlEventTouchUpInside];
[nextView.view addSubview:stayButton];
stayButton.titleLabel.font = [UIFont systemFontOfSize:25];
[stayButton setTitleColor:[UIColor colorWithRed:(255/255.0) green:(255/255.0) blue:(255/255.0) alpha:1] forState:UIControlStateNormal];
And finally in your IBAction method
-(void)waitForNextView{
transition = NO;
[self.locationManager stopRangingBeaconsInRegion:self.beaconRegion];
actualSection = 0;
[nextView removeFromSuperview];
}
The problem here is that you are adding the button as a subview to the view of nextView, so removing the view of nextView won't work.
If you add a tag to your button, then you can retrieve the subview by using the tag. Eg. When you define your button:
[stayButton setTag:1];
Then in the waitForNextView method, you can get the control like this:
UIButton *stayButton = (UIButton*)[nextView.view viewWithTag:1];
[stayButton removeFromSuperView];
use this code in the methode dismissView2
for (UIView *subview in view.subviews ){
[subview removeFromSuperview];
}

removeObjectFromSuperView not working with if statement

I have a button that when pressed is supposed to hide the status bar and place text in its spot. Then, when the button is pressed the label is supposed o be removed from the view and the status bar will re-appear. The first part works -- the status bar is hidden and the label is placed on the view, the problem is when I press the button a second time (to remove the text and put back the status bar). The status bar re-appears but the label is not being removed from the view. To achieve this I am using an if statement. I am also using removeObjectFromSuperView which is the thing that is not working.
Here is the code:
- (IBAction)buttonPressed:(id)sender {
UILabel *label = [[UILabel alloc]initWithFrame:CGRectMake(0, 0, 320, 21)];
label.text = #"This is a test";
[label setFont:[UIFont systemFontOfSize:13]];
label.textAlignment = NSTextAlignmentCenter;
if (hidden == NO) {
[UIApplication sharedApplication].statusBarHidden = YES;
[self.view addSubview:label];
hidden = YES;
}else if (hidden == YES) {
[UIApplication sharedApplication].statusBarHidden = NO;
[label removeFromSuperview];
hidden = NO;
}
}
Thanks
Edit: Here is what the problem looks like:
You need to track your label outside of the buttonPressed: method. Right now you are creating a new label every time the button is pressed then removing that same label.
So for example:
#interface MyViewController () {
UILabel *label;
}
- (IBAction)buttonPressed:(id)sender {
if (hidden == NO) {
[UIApplication sharedApplication].statusBarHidden = YES;
label = [[UILabel alloc]initWithFrame:CGRectMake(0, 0, 320, 21)];
label.text = #"This is a test";
[label setFont:[UIFont systemFontOfSize:13]];
label.textAlignment = NSTextAlignmentCenter;
[self.view addSubview:label];
hidden = YES;
} else if (hidden == YES) {
[UIApplication sharedApplication].statusBarHidden = NO;
[label removeFromSuperview];
label = nil;
hidden = NO;
}
}
You can also set label = nil; once you remove it from the super view.

Resources