Recreating the Quora app iOS 7 UISearchBar - ios

Quora's iOS 7 app seemingly displays a UISearchBar in the main UINavigationController's UINavigationBar. Search is triggered by tapping on the right bar button item in that bar and animates in from the right. Everything appears to happen in a single view controller.
Apple introduced the "displaysSearchBarInNavigationBar" property to UISearchDisplayController in iOS 7, but I don't believe that Quora have used this. It's not possible to have a titleView in the navigation bar when set and the Quora app certainly appears to have this.
Apple's Calendar app uses a separate view controller for search, but keeping search in the same view controller as the content, as Quora do, is a nicer experience for the user.
The only way I've thought to do this might be to use custom UIViewController transitions, but that feels like an overkill. Is there a simpler way to create this?

Here's a quick sample view controller I wrote to mimic the Quora "expanding search field" effect. I'll leave it up to you to incorporate a "search results" tableview.
I used a UITextField (subclassed so I could change the color of the placeholder text...), but you MIGHT be able to use a UISearchBar. Or you might want to make a custom view that contains the UITextField and any "close" button. In my example I used the UITextField rightView to hold a close button; in the Quora case they have the close button outside the text field, like a real UISearchBar. But I don't think you can can change the text/image of the close button on a UISearchBar (at least not easily).
It's possible that you could come up with a solution that cleanly integrated the built-in searchViewController, but it might be too much trouble for its worth.
#interface TSTextField : UITextField
#end
#implementation TSTextField
- (void) drawPlaceholderInRect: (CGRect) rect
{
CGFloat fontHeight = self.font.lineHeight;
CGFloat yOffset = (rect.size.height - fontHeight) / 2.0;
rect = CGRectMake( 0, yOffset, rect.size.width, fontHeight );
[[self placeholder] drawInRect: rect
withAttributes: #{ NSFontAttributeName : self.font,
NSForegroundColorAttributeName : self.isEditing ? self.textColor : [UIColor whiteColor] }];
}
#end
#interface TSViewController () <UITextFieldDelegate>
#end
#implementation TSViewController
- (void) viewDidLoad
{
[super viewDidLoad];
self.navigationController.navigationBar.barTintColor = [UIColor redColor];
UITextField* searchField = [[TSTextField alloc] initWithFrame: CGRectMake(0, 0, 85, 30)];
searchField.backgroundColor = [UIColor clearColor];
searchField.borderStyle = UITextBorderStyleNone;
searchField.textColor = [UIColor whiteColor];
searchField.textAlignment = NSTextAlignmentRight;
searchField.placeholder = #"Search";
searchField.delegate = self;
UIButton* magnifyButton = [UIButton buttonWithType: UIButtonTypeSystem];
[magnifyButton setTitle: #"🔍" forState: UIControlStateNormal];
[magnifyButton sizeToFit];
[magnifyButton addTarget: self action: #selector( close: ) forControlEvents: UIControlEventTouchUpInside];
searchField.leftView = magnifyButton;
searchField.leftViewMode = UITextFieldViewModeAlways;
UIButton* closeButton = [UIButton buttonWithType: UIButtonTypeSystem];
[closeButton setTitle: #"ⓧ" forState: UIControlStateNormal];
[closeButton sizeToFit];
[closeButton addTarget: self action: #selector( close: ) forControlEvents: UIControlEventTouchUpInside];
searchField.rightView = closeButton;
searchField.rightViewMode = UITextFieldViewModeWhileEditing;
UIBarButtonItem* bbi = [[UIBarButtonItem alloc] initWithCustomView: searchField];
self.navigationItem.rightBarButtonItem = bbi;
}
- (BOOL) textFieldShouldBeginEditing:(UITextField *)textField
{
UITextField* searchField = (UITextField*)self.navigationItem.rightBarButtonItem.customView;
searchField.borderStyle = UITextBorderStyleRoundedRect;
searchField.backgroundColor = [UIColor whiteColor];
searchField.textColor = [UIColor blackColor];
searchField.text = #"";
searchField.textAlignment = NSTextAlignmentLeft;
[UIView transitionWithView: searchField
duration: 0.25
options: UIViewAnimationOptionAllowAnimatedContent | UIViewAnimationOptionTransitionCrossDissolve
animations:^{
searchField.frame = CGRectMake( 0, 0, 290, searchField.frame.size.height);
}
completion: nil];
return YES;
}
- (void) close: (id) sender
{
UITextField* searchField = (UITextField*)self.navigationItem.rightBarButtonItem.customView;
searchField.rightViewMode = UITextFieldViewModeNever;
[UIView transitionWithView: searchField
duration: 0.25
options: UIViewAnimationOptionAllowAnimatedContent | UIViewAnimationOptionTransitionCrossDissolve
animations:^{
searchField.frame = CGRectMake( 0, 0, 85, searchField.frame.size.height);
searchField.backgroundColor = [UIColor clearColor];
searchField.text = #"";
searchField.borderStyle = UITextBorderStyleNone;
searchField.textColor = [UIColor whiteColor];
searchField.textAlignment = NSTextAlignmentRight;
[searchField resignFirstResponder];
}
completion:^(BOOL finished) {
searchField.rightViewMode = UITextFieldViewModeWhileEditing;
}];
}
#end

Related

Custom Keyboard InputAccessoryView not visible in iOS 11

I have implemented Custom input accessory view it was working fine till iOS 10.3.1. But it's not visible in iOS 11 beta.
Have anyone experience this issue?
The question you ask does not have much detail. But I had the same problem when using an inputAccessoryView and a custom inputView for the textfield.
And resolved this on iOS11 by setting the custom inputView's autoresizingMask to .flexibleHeight.
yourCustomInputView.autoresizingMask = .flexibleHeight
Hope this resolves the issue. If not maybe provide some more information?
Here is how I add the input accessory, incase this is of more help (as extension of textfield):
public extension UITextField {
public func addToolbarInputAccessoryView(barButtonItems: [UIBarButtonItem],
textColour: UIColor,
toolbarHeight: CGFloat = 44,
backgroundColour: UIColor = .white) {
let toolbar = UIToolbar()
toolbar.frame = CGRect(x: 0, y: 0, width: bounds.width, height: toolbarHeight)
toolbar.items = barButtonItems
toolbar.isTranslucent = false
toolbar.barTintColor = backgroundColour
toolbar.tintColor = textColour
inputAccessoryView = toolbar
}
}
And then on the inputView (not the inputAccessoryView), I was using a date picker for example - just make sure that the date picker's autoresizing mask is set to flexible height.
PSA: If you use a UIToolbar as your custom view, it's currently broken in iOS 11 GM.
Instead of loosing your hair on how to fix it, just change it to UIView.
You'll loose the blur effect but it will work.
Beta 3 has just come out and some people said it solved the problem, but for me it didn't.
However I tried setting the accessory view to something stupid (100pxls high) and spotted that the Undo/Redo/Paste bar on the iPads was incorrectly sitting over the top of my accessory bar.
So I added the following code to get rid of Apples bar (it was pointless for my custom picker anyway) and the problem went away
Hope this helps somebody
- (void)textFieldDidBeginEditing:(UITextField*)textField
{
UITextInputAssistantItem* item = [textField inputAssistantItem];
item.leadingBarButtonGroups = #[];
item.trailingBarButtonGroups = #[];
}
To avoid the inputAccessoryView issue in iOS 11 for UITextField and UITextView, just use the following code:
UIView *inputView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 150)];
self.monthPickerView = [[UIPickerView alloc]initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 150)];
self.monthPickerView.backgroundColor = [UIColor whiteColor];
self.monthPickerView.delegate = self;
self.monthPickerView.dataSource = self;
[inputView addSubview:self.monthPickerView];
cell.monthTextField.inputView = inputView ;
self.monthTextField.inputAccessoryView = [self doneButtonAccessoryView];
// doneButtonAccessoryView Method
-(UIToolbar*)doneButtonAccessoryView
{
UIToolbar *kbToolbar = [[UIToolbar alloc] init];
[kbToolbar sizeToFit];
[kbToolbar setBarTintColor:[UIColor whiteColor]];
UIBarButtonItem *doneButton = [[UIBarButtonItem alloc] initWithTitle:#"Done"
style:UIBarButtonItemStyleDone target:self
action:#selector(doneClicked)];
UIBarButtonItem *cancelButton = [[UIBarButtonItem alloc] initWithTitle:#"Cancel"
style:UIBarButtonItemStyleDone target:self
action:#selector(cancelClicked)];
NSDictionary *attrDict;
attrDict = [NSDictionary dictionaryWithObjectsAndKeys:
[UIFont fontWithName:#"Helvetica-Bold" size:16.0], NSFontAttributeName, nil];
[doneButton setTitleTextAttributes:attrDict forState:UIControlStateNormal];
UIBarButtonItem *flexWidth = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace
target:self action:nil];
[kbToolbar setItems:[NSArray arrayWithObjects:cancelButton,flexWidth, doneButton, nil]];
return kbToolbar;
}
UIToolBar is broken in iOS 11. But you can get the same thing done using UIView as inputAccessoryView. Sample code snippet here:
CGFloat width = [[UIScreen mainScreen] bounds].size.width;
UIView* toolBar = [[UIView alloc] initWithFrame:CGRectMake(0.0f,0.0f, width, 44.0f)];
toolBar.backgroundColor = [UIColor colorWithRed:0.97f green:0.97f blue:0.97f alpha:1.0f];
UILabel *titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(20.0 , 0.0f, width, 44.0f)];
[titleLabel setFont:[UIFont fontWithName:#"Helvetica" size:13]];
[titleLabel setBackgroundColor:[UIColor clearColor]];
[titleLabel setTextColor:[UIColor redColor]];
[titleLabel setText:#"Title"];
[titleLabel setTextAlignment:NSTextAlignmentLeft];
[toolBar addSubview:titleLabel];
UIButton *doneBtn = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[doneBtn setTitle:#"Done" forState:UIControlStateNormal];
doneBtn.tintColor = [UIColor colorWithRed:(float)179/255 green:(float)27/255 blue:(float)163/255 alpha:1];
[doneBtn.titleLabel setFont:[UIFont fontWithName:#"Helvetica" size:16]];
[doneBtn addTarget:self action:#selector(btnTxtDoneAction) forControlEvents:UIControlEventTouchUpInside];
[doneBtn setFrame:CGRectMake(width-70, 6, 50, 32)];
[toolBar addSubview:doneBtn];
[toolBar sizeToFit];
txtMessageView.inputAccessoryView = toolBar;
Hope this help..:)
I've had the same issue and I've found out that removing all of the bottom, top, leading, training, left, right constraints for the
view that is assigned accessoryView solved it.
Swift 4 solution
let toolBarRect = CGRect(x: 0, y: 0, width: self.view.frame.width, height: 44)
let toolBar = UIView(frame: toolBarRect)
toolBar.backgroundColor = .lightGray
let nextButton = UIButton()
nextButton.setTitleColor(.black, for: .normal)
nextButton.setTitle("Next", for: .normal)
nextButton.addTarget(self, action: #selector(self.onNextButtonTouch), for: .touchUpInside)
nextButton.translatesAutoresizingMaskIntoConstraints = false
toolBar.addSubview(nextButton)
NSLayoutConstraint.activate(
[
nextButton.heightAnchor.constraint(equalToConstant: Constants.keyboardToolBarHeight),
nextButton.trailingAnchor.constraint(equalTo: toolBar.trailingAnchor, constant: -16),
nextButton.centerYAnchor.constraint(equalTo: toolBar.centerYAnchor, constant: 0)
]
)
self.yourTextField.inputAccessoryView = toolBar
Just in case someone might still need the solution, here's what I did (IOS 12.1);
private func initSearchBox() {
// Add Done button on keyboard
txtSearch.delegate = self
let tbrDone = UIToolbar()
let btnDone = UIBarButtonItem(title: "Done", style: .plain, target: self, action: #selector(btnDone_tapped))
tbrDone.items = [btnDone]
tbrDone.sizeToFit()
self.txtSearch.inputAccessoryView = tbrDone
}
#objc func btnDone_tapped() {
view.endEditing(true)
}

Cannot get UIButton to programmatically call action in iOS

I cannot get my button to fire the associated method. I am not using IB or anything like that (all programmatic). The _mainViewController is passed in during custom init, just to clarify (although this should have nothing to do with the button). Please see my code snips:
viewcontroller.h
#import <UIKit/UIKit.h>
#interface CSNWZSSViewController : UIViewController
- (void)doneButtonPressed;
#property UIViewController *mainViewController;
#property UIButton *doneButton;
#end
viewcontroller.m
- (void)viewDidLoad
{
[super viewDidLoad];
UIView *headerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, _mainViewController.view.frame.size.width, 45)];
headerView.backgroundColor = [UIColor darkGrayColor];
_doneButton = [[UIButton alloc] initWithFrame:CGRectMake(_mainViewController.view.frame.size.width - 100, 0, 100, headerView.frame.size.height)];
[_doneButton addTarget:self
action:#selector(doneButtonPressed)
forControlEvents:UIControlEventTouchUpInside];
[_doneButton setTitle:#"Done" forState:UIControlStateNormal];
_doneButton.tintColor = [UIColor whiteColor];
_doneButton.backgroundColor = [UIColor colorWithRed:0 green:.77 blue:0 alpha:1];
[headerView addSubview:_doneButton];
CGRect headerLabelFrame = CGRectMake(5, 5, headerView.frame.size.width - 105, headerView.frame.size.height - 5);
UILabel *headerLabel = [[UILabel alloc] initWithFrame:headerLabelFrame];
headerLabel.text = #"test header";
headerLabel.textColor = [UIColor whiteColor];
headerLabel.backgroundColor = [UIColor clearColor];
headerLabel.font = [UIFont systemFontOfSize:20.0f];
headerLabel.lineBreakMode = NSLineBreakByTruncatingTail;
[headerView addSubview:headerLabel];
[self.view addSubview:headerView];
}
- (void)doneButtonPressed
{
NSLog(#"button pressed");
}
Update 10/9/16 using buttonWithType init and explicit userInteractionEnabled
_doneButton = [UIButton buttonWithType:UIButtonTypeCustom];
[_doneButton addTarget:self
action:#selector(doneButtonPressed)
forControlEvents:UIControlEventTouchUpInside];
[_doneButton setTitle:#"Done" forState:UIControlStateNormal];
_doneButton.tintColor = [UIColor whiteColor];
_doneButton.backgroundColor = [UIColor blackColor]; //[UIColor colorWithRed:0 green:.77 blue:0 alpha:1];
_doneButton.frame = CGRectMake(_mainViewController.view.frame.size.width - 100, 0, 100, headerView.frame.size.height);
_doneButton.userInteractionEnabled = YES;
[headerView addSubview:_doneButton];
Note 12/9/16 the _mainViewController object is passed in here:
CSNWZSSViewController *CSNWZSSVC = [[CSNWZSSViewController alloc] initWithRichTextString:source withTitleString:title forViewController:self.viewController];
[self.viewController.view addSubview:CSNWZSSVC.view];
Solution with matt's help (see below) The context was getting messed up due to the lack of adding the new view controller.
CSNWZSSViewController *CSNWZSSVC = [[CSNWZSSViewController alloc] initWithRichTextString:source withTitleString:title forViewController:self.viewController];
[self.viewController addChildViewController:CSNWZSSVC];
[self.viewController.view addSubview:CSNWZSSVC.view];
The _mainViewController is passed in during custom init
I'm going to guess that this is the problem — that you are mismanaging this view controller and that it is not being correctly made part of the view controller hierarchy, and in fact may even be going out of existence so that there is no one to send the button action message to.
edit Yes, now that you've posted more code, I'm clearly right:
CSNWZSSViewController *CSNWZSSVC = [[CSNWZSSViewController alloc] initWithRichTextString:source withTitleString:title forViewController:self.viewController];
[self.viewController.view addSubview:CSNWZSSVC.view];
That is totally wrong behavior. You cannot arbitrarily add another view controller's view to yours. There is a strict dance for managing a child view controller, and you are not doing the dance.
Try:
UIButton *theButton = [UIButton buttonWithType:UIButtonTypeCustom];
And then set your frame.

Dismiss custom alert view iOS

I'm setting up a subclass of UIView to roll my own UIAlertView style view. I've got everything set up properly with displaying the view, but I'm at a bit of a loss as to how to dismiss the view properly. Specifically, when a user taps on the button in the view, it needs to animate out of the main view. This is the code for the view itself:
+ (void)showCustomAlertWithTitle:(NSString *)titleString andMessage:(NSString *)messageString inView:(UIView *)view andButton1Title: (NSString *)button1Title andButton2Title: (NSString *)button2Title
{
UIWindow *window = [[[UIApplication sharedApplication] windows] lastObject];
CGRect windowFrame = window.frame;
[view setAlpha:0.5f];
UIColor *buttonColor = [UIColor colorWithRed:0/255.0f green:130/255.0f blue:216/255.0f alpha:1];
UIColor *titleColor = [UIColor colorWithRed:0/255.0f green:153/255.0f blue:102/255.0f alpha:1];
// Shade
UILabel *shadeWindow = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, windowFrame.size.width, windowFrame.size.height)];
shadeWindow.backgroundColor = [UIColor blackColor];
shadeWindow.alpha = 0.50f;
// Define size and origin of alert box
float alertBoxHeight = 225;
float alertBoxWidth = 200;
float alertBoxXorigin = windowFrame.size.width / 2 - (alertBoxWidth / 2);
float alertBoxYorigin = windowFrame.size.height / 2 - (alertBoxHeight / 2);
// Initialize background
UIView *alertBackground = [[UIView alloc] initWithFrame:CGRectMake(alertBoxXorigin, alertBoxYorigin, alertBoxWidth, alertBoxHeight)];
alertBackground.layer.cornerRadius = 5.0f;
[alertBackground.layer setMasksToBounds:YES];
alertBackground.layer.backgroundColor = [UIColor whiteColor].CGColor;
// Title Label
UILabel *titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, alertBoxWidth, 40)];
titleLabel.text = titleString;
titleLabel.textAlignment = NSTextAlignmentCenter;
titleLabel.textColor = titleColor;
titleLabel.layer.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.05f].CGColor;
[titleLabel setFont:[UIFont fontWithName:#"AvenirNext-Bold" size:20.0]];
// Title Divider
UILabel *titleDivider = [[UILabel alloc] initWithFrame:CGRectMake(0, 40, alertBoxWidth, 1.0)];
titleDivider.backgroundColor = [UIColor grayColor];
titleDivider.alpha = 0.5f;
// Alert Message Text
UITextView *alertMessage = [[UITextView alloc] initWithFrame:CGRectMake(0, 40, alertBoxWidth, alertBoxHeight - 90)];
alertMessage.text = messageString;
alertMessage.layer.backgroundColor = [UIColor whiteColor].CGColor;
[alertMessage setFont:[UIFont fontWithName:#"Avenir" size:15.0]];
alertMessage.textAlignment = NSTextAlignmentCenter;
alertMessage.textColor = [UIColor grayColor];
[alertMessage setEditable:NO];
// Button 1
UIButton *button1 = [[UIButton alloc] init];
UIButton *button2 = [[UIButton alloc] init];
[button1 addTarget:self action:#selector(buttonPressed:) forControlEvents:UIControlEventTouchUpInside];
if (button2Title == nil)
{
button1.frame = CGRectMake(10, alertBoxHeight - 50, alertBoxWidth - 20, 40);
}
else
{
button1.frame = CGRectMake(10, alertBoxHeight - 50, (alertBoxWidth / 2) - 20, 40);
button2.frame = CGRectMake(alertBoxWidth / 2 + 10, alertBoxHeight - 50, (alertBoxWidth / 2) - 20, 40);
}
button1.layer.backgroundColor = buttonColor.CGColor;
[button1 setTitle:button1Title forState:UIControlStateNormal];
[button1.titleLabel setFont:[UIFont fontWithName:#"AvenirNext-Bold" size:15.0f]];
button1.layer.cornerRadius = 2.5f;
[button1.layer setMasksToBounds:YES];
// Button 2
button2.layer.backgroundColor = buttonColor.CGColor;
[button2 setTitle:button2Title forState:UIControlStateNormal];
[button2.titleLabel setFont:[UIFont fontWithName:#"AvenirNext-Bold" size:15.0f]];
button2.layer.cornerRadius = 2.5f;
[button2.layer setMasksToBounds:YES];
// Bounce Implementation
alertBackground.transform = CGAffineTransformMakeScale(0.01, 0.01);
[UIView animateWithDuration:0.25 delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^
{
alertBackground.transform = CGAffineTransformIdentity;
}
completion:^(BOOL finished)
{
// do something once the animation finishes, put it here
}];
[window addSubview:view];
[window addSubview:alertBackground];
[view addSubview:shadeWindow];
[view bringSubviewToFront:alertBackground];
[alertBackground addSubview:button1];
[alertBackground addSubview:titleLabel];
[alertBackground addSubview:titleDivider];
[alertBackground addSubview:alertMessage];
[alertBackground addSubview:button2];
[alertBackground bringSubviewToFront:titleDivider];
/* [[[customAlerts sharedInstance] subViewArray] addObject:alertBackground];
[[[customAlerts sharedInstance] subViewArray] addObject:view];
[[[customAlerts sharedInstance] subViewArray] addObject:window];*/
}
When button1 is tapped, for instance, I need to have it animate the view out of the superView and remove it from the stack. I'm not sure how to handle this. Does anyone have any ideas?
To permanently remove a view, I generally use the UIView instance method removeFromSuperview. followed by a line setting the relevant variable to nil:
[myAlertView removeFromSuperview];
myAlertView = nil;
In your case then, I think you need to move the view off the screen by animating the its bounds property, then use the above couple of lines to remove any references to it.
Just found the answer here:
Dismiss view controller from #selector without creating seperate method
Had to download some custom classes but it worked:
[button1 addEventHandler:^(id sender, UIEvent *event)
{
[UIView animateWithDuration:0.25f animations:^{
[alertBackground setAlpha:0.0f];
[shadeWindow setAlpha:0.0f];
[window setAlpha:0.0f];
}];
} forControlEvent:UIControlEventTouchUpInside];
Custom classes can be found here:
https://github.com/ZeR0-Wu/JTTargetActionBlock

textFieldShouldReturn does not get called (textField loaded programmatically)

I'm currently loading a -UITextField programmatically and trying to make the keyboard go down once I click on 'Search'.
I declare the -UITextFeild inside the .m file as
UITextField *searchTextField;
Inside the .h file I do indeed declare the -UITextField's delegate
#interface firstChannel : UIViewController<LBYouTubePlayerControllerDelegate, UITableViewDelegate,UITableViewDataSource, NSXMLParserDelegate, UITextFieldDelegate, AVPlayerItemOutputPullDelegate>{
This is how I add the UITextField programmatically.
searchTextField = [[UITextField alloc] initWithFrame:CGRectMake(10, -26, 300, 30)];
searchTextField.borderStyle = UITextBorderStyleRoundedRect;
searchTextField.font = [UIFont fontWithName:#"Heiti TC" size:13];
searchTextField.autocorrectionType = UITextAutocorrectionTypeNo;
searchTextField.clearButtonMode = UITextFieldViewModeWhileEditing;
searchTextField.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
searchTextField.placeholder = #"Search on the Channel";
searchTextField.borderStyle = UITextBorderStyleNone;;
searchTextField.textAlignment = UITextAlignmentCenter;
searchTextField.center = CGPointMake(160, 43);
searchTextField.textColor = [UIColor colorWithRed:(232.0/255.0) green:(232.0/255.0) blue:(232.0/255.0) alpha:(100.0/100.0)];
searchTextField.clearButtonMode = UITextFieldViewModeNever;
searchTextField.returnKeyType = UIReturnKeySearch;
[searchTextField setKeyboardAppearance:UIKeyboardAppearanceAlert];
[self.view.window addSubview:searchTextField];
[searchTextField becomeFirstResponder];
I added the delegate inside -viewDidLoad
searchTextField.delegate = self;
However when I click on "Search" on the keyboard nothing happens. I'm unsure why that's happening I've even debugged it by logging something once you hit returns but nothing happens.
Call the searchTExtField.delegate after you create and setup the text field.
Try moving all the code in viewDidLoad
- (void)viewDidLoad
{
[super viewDidLoad]; searchTextField = [[UITextField alloc] initWithFrame:CGRectMake(10, -26, 300, 30)];
searchTextField.borderStyle = UITextBorderStyleRoundedRect;
searchTextField.font = [UIFont fontWithName:#"Heiti TC" size:13];
searchTextField.autocorrectionType = UITextAutocorrectionTypeNo;
searchTextField.clearButtonMode = UITextFieldViewModeWhileEditing;
searchTextField.delegate = self;
searchTextField.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
searchTextField.placeholder = #"Search on the Channel";
searchTextField.borderStyle = UITextBorderStyleNone;;
searchTextField.textAlignment = UITextAlignmentCenter;
searchTextField.center = CGPointMake(160, 43);
searchTextField.textColor = [UIColor colorWithRed:(232.0/255.0) green:(232.0/255.0) blue:(232.0/255.0) alpha:(100.0/100.0)];
searchTextField.clearButtonMode = UITextFieldViewModeNever;
searchTextField.returnKeyType = UIReturnKeySearch;
[searchTextField setKeyboardAppearance:UIKeyboardAppearanceAlert];
[self.view.window addSubview:searchTextField];
[searchTextField becomeFirstResponder];
}
Also, if you are using search bar then you need to use search bar delegate. If you are just using UITextfield, then you should be okay.
Have you implemented the delegate method (this method gets called when the user taps the return key):
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
[textField resignFirstResponder];
//Perform search with text:
[self performSearch:[textField text]];
return NO;
}
This will resign the responder. Here you can also call your search method.

Customize navigation bar with title view

I am trying to add a custom view in the center of a navigation bar and I am using the following code to test it:
UIView * testView = [[UIView alloc] init];
[testView setBackgroundColor:[UIColor blackColor]];
testView.frame = CGRectMake(0, 0, 100, 35);
[self.navigationController.navigationItem.titleView addSubview:testView];
I am setting this up in the viewDidLoad method of my view controller but when i run my program
nothing seems to change in my navigation bar.
Could you help me with this?
This works. Give frame at the time of initialisation
UIView *iv = [[UIView alloc] initWithFrame:CGRectMake(0,0,32,32)];
[iv setBackgroundColor:[UIColor whiteColor]];
self.navigationItem.titleView = iv;
If you want to just customize the title for one view controller you can use
UILabel *lblTitle = [[UILabel alloc] init];
lblTitle.text = #"Diga-nos o motivo";
lblTitle.backgroundColor = [UIColor clearColor];
lblTitle.textColor = [UIColor colorWithRed:77.0/255.0 green:77.0/255.0 blue:77.0/255.0 alpha:1.0];
lblTitle.shadowColor = [UIColor whiteColor];
lblTitle.shadowOffset = CGSizeMake(0, 1);
lblTitle.font = [UIFont fontWithName:#"HelveticaNeue-Bold" size:18.0];
[lblTitle sizeToFit];
self.navigationItem.titleView = lblTitle;
or if you want to customize for all view controllers use
[[UINavigationBar appearance] setTitleTextAttributes:
[NSDictionary dictionaryWithObjectsAndKeys:
[UIColor colorWithRed:255.0/255.0 green:255.0/255.0 blue:255.0/255.0 alpha:1.0],
UITextAttributeTextColor,
[UIColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:0.8],
UITextAttributeTextShadowColor,
[NSValue valueWithUIOffset:UIOffsetMake(0, -1)],
UITextAttributeTextShadowOffset,
[UIFont fontWithName:#"Arial-Bold" size:10.0],
UITextAttributeFont,
nil]];
Replace
[self.navigationController.navigationItem.titleView addSubview:testView];
to
self.navigationItem.titleView = testView;
Edit:
Note: You cannot add subviews to titleView cause it's default value is nil, you need to set a new view as the titleView.
Swift 3/4
You may set i.e. UILabel as a titleView. Call it in viewDidLoad():
private func setNavigationTitle(_ title: String) {
navigationItem.title = nil // clear the default title
let titleLabel = UILabel() // you don't need to specify a frame, it will be centred in the navbar
titleLabel.font = ...
titleLabel.textColor = ...
titleLabel.text = title
titleLabel.backgroundColor = .clear
navigationItem.titleView = titleLabel
navigationTitleView = titleLabel // you may create a property if you want to manipulate the title view later
}
Note navigationItem.title = nil, otherwise title may override titleView.
CustomLabel *titleLabel = [CustomLabel initWithLabelFrame:labelFrame textFont:[UIFont fontWithName:#"Helvetica" size:[UIFont systemFontSize]] textColor:[UIColor blackColor] labelText:#"Add as" textAlignment:NSTextAlignmentCenter labelOnView:reference.view labelTag:62];
[self.navigationItem setTitleView:titleLabel]; // titleLabel set in navigationItem
#import <UIKit/UIKit.h>
#interface MasterViewController : UITableViewController
#end
#import "MasterViewController.h"
#interface MasterViewController ()
#end
#implementation MasterViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.navigationItem.titleView = [self titleView];
}
- (UIView *)titleView {
CGFloat navBarHeight = self.navigationController.navigationBar.frame.size.height;
CGFloat width = 0.95 * self.view.frame.size.width;
UIView *containerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, width, navBarHeight)];
UIImage *logo = [UIImage imageNamed:#"logo.png"];
UIButton *logoButton = [UIButton buttonWithType:UIButtonTypeCustom];
CGFloat logoY = floorf((navBarHeight - logo.size.height) / 2.0f);
[logoButton setFrame:CGRectMake(0, logoY, logo.size.width, logo.size.height)];
[logoButton setImage:logo forState:UIControlStateNormal];
UIImage *bubble = [UIImage imageNamed:#"notification-bubble-empty.png"];
UIImageView *bubbleView = [[UIImageView alloc] initWithImage:bubble];
const CGFloat Padding = 5.0f;
CGFloat bubbleX =
logoButton.frame.size.width +
logoButton.frame.origin.x +
Padding;
CGFloat bubbleY = floorf((navBarHeight - bubble.size.height) / 2.0f);
CGRect bubbleRect = bubbleView.frame;
bubbleRect.origin.x = bubbleX;
bubbleRect.origin.y = bubbleY;
bubbleView.frame = bubbleRect;
[containerView addSubview:logoButton];
[containerView addSubview:bubbleView];
return containerView;
}
#end
You'll want to use storyboard to do this to support iPhone 6 and newer (larger) devices.
Create a container view for your custom navigation item title/subtitle etc, and drag it into the visual editor (not into the view hierarchy).
Swift 3
let myImageView = UIImageView(image: <...set your image...>)
override fun viewDidLoad(){
super.viewDidLoad()
self.navigationItem.titleView = myImageView //
}
One more alternate solution is
override fun viewWillAppear(_ animated: Bool) {
super. viewWillAppear(animated)
self.navigationItem.titleView = myImageView
}
I recommend to use, viewDidLoad to setup your titleView

Resources