In the UISearchBar control, is the a way to change the Search key title for the keyboard to Done?
For a searchbar named tablesearchbar:
// Set the return key and keyboard appearance of the search bar
for (UIView *searchBarSubview in [tableSearchBar subviews]) {
if ([searchBarSubview conformsToProtocol:#protocol(UITextInputTraits)]) {
#try {
[(UITextField *)searchBarSubview setReturnKeyType:UIReturnKeyDone];
[(UITextField *)searchBarSubview setKeyboardAppearance:UIKeyboardAppearanceAlert];
}
#catch (NSException * e) {
// ignore exception
}
}
}
At least for iOS 8, simply:
[self.searchBar setReturnKeyType:UIReturnKeyDone];
As of iOS 7 beta 5, Run Loop's answer didn't work for me, but this did:
for(UIView *subView in [searchBar subviews]) {
if([subView conformsToProtocol:#protocol(UITextInputTraits)]) {
[(UITextField *)subView setReturnKeyType: UIReturnKeyDone];
} else {
for(UIView *subSubView in [subView subviews]) {
if([subSubView conformsToProtocol:#protocol(UITextInputTraits)]) {
[(UITextField *)subSubView setReturnKeyType: UIReturnKeyDone];
}
}
}
}
One more useful hint, to the Run Loop code (in "#try") section.
This enabled "Done" button when text field is empty:
UITextField *tf = (UITextField *)searchBarSubview;
tf.enablesReturnKeyAutomatically = NO;
For Swift to change return key of UISearchBar
searchBar.returnKeyType = UIReturnKeyType.done
enum available are as below
public enum UIReturnKeyType : Int {
case default
case go
case google
case join
case next
case route
case search
case send
case yahoo
case done
case emergencyCall
#available(iOS 9.0, *)
case continue
}
Just a reminder! If you searchBar stays as first responder, after you change your returnKeyType, you need to dismiss your keyboard and pop it up again to see the changes.
search.resignFirstResponder()
searchBar.returnKeyType = UIReturnKeyType.Done
search.becomeFirstResponder()
As it is a protocol with optional methods, you should test each method separately instead of try-catching.
for (UIView *searchBarSubview in searchBar.subviews)
{
if ([searchBarSubview conformsToProtocol:#protocol(UITextInputTraits)])
{
// keyboard appearance
if ([searchBarSubview respondsToSelector:#selector(setKeyboardAppearance:)])
[(id<UITextInputTraits>)searchBarSubview setKeyboardAppearance:UIKeyboardAppearanceAlert];
// return key
if ([searchBarSubview respondsToSelector:#selector(setReturnKeyType:)])
[(id<UITextInputTraits>)searchBarSubview setReturnKeyType:UIReturnKeyDone];
// return key disabled when empty text
if ([searchBarSubview respondsToSelector:#selector(setEnablesReturnKeyAutomatically:)])
[(id<UITextInputTraits>)searchBarSubview setEnablesReturnKeyAutomatically:NO];
// breaking the loop when we are done
break;
}
}
This will work for iOS <= 6. For iOS >= 7, you need to loop in searchBar.subviews[0].subviews.
Since the Alert-style keyboards are semi-transparent, I can see my view behind it. It doesn't look very good since I have multiple elements behind the keyboard that makes it hard for the keys to stand out. I wanted an all-black keyboard.
So I animated a black UIImageView into position behind the keyboard when text is edited. This gives the appearance of an all-black keyboard.
- (void)textFieldDidBeginEditing:(UITextField *)textField {
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.25];
blackBoxForKeyboard.frame = CGRectMake(0, 377, 320, 216);
[UIView commitAnimations];
}
I tried all the solutions shown here, and none of them worked for my UISearchBar (xcode5 compiling for iOS7). I ended up with this recursive function which worked for me:
- (void)fixSearchBarKeyboard:(UIView*)searchBarOrSubView {
if([searchBarOrSubView conformsToProtocol:#protocol(UITextInputTraits)]) {
if ([searchBarOrSubView respondsToSelector:#selector(setKeyboardAppearance:)])
[(id<UITextInputTraits>)searchBarOrSubView setKeyboardAppearance:UIKeyboardAppearanceAlert];
if ([searchBarOrSubView respondsToSelector:#selector(setReturnKeyType:)])
[(id<UITextInputTraits>)searchBarOrSubView setReturnKeyType:UIReturnKeyDone];
if ([searchBarOrSubView respondsToSelector:#selector(setEnablesReturnKeyAutomatically:)])
[(id<UITextInputTraits>)searchBarOrSubView setEnablesReturnKeyAutomatically:NO];
}
for(UIView *subView in [searchBarOrSubView subviews]) {
[self fixSearchBarKeyboard:subView];
}
}
I then called it like so:
_searchBar = [[UISearchBar alloc] init];
[self fixSearchBarKeyboard:_searchBar];
Just for covering all the iOS versions:
NSArray *subviews = [[[UIDevice currentDevice] systemVersion] floatValue] < 7 ? _searchBar.subviews : _searchBar.subviews[0].subviews;
for (UIView *subview in subviews)
{
if ([subview conformsToProtocol:#protocol(UITextInputTraits)])
{
UITextField *textField = (UITextField *)subview;
[textField setKeyboardAppearance: UIKeyboardAppearanceAlert];
textField.returnKeyType = UIReturnKeyDone;
break;
}
}
Related
I would like to customize the delete button which is shown when performing the 'swipe to left'-action on a tableview cell. I currently set up a subclass of a UITableViewCell but also want to customize the delete-button which is being shown.
My goal is to place three buttons when swiping.
I choose for another implementation where I was using a UIScrollview in each cell.
http://www.teehanlax.com/blog/reproducing-the-ios-7-mail-apps-interface/
Accepted answer will not work on iOS 7, as there is now UITableViewCellContentView in between. So subviews loop now should look like this(if you want to support older iOS versions too, use currently accepted answer for iOS 6.1-)
for (UIView *subview in self.subviews) {
for (UIView *subview2 in subview.subviews) {
if ([NSStringFromClass([subview2 class]) rangeOfString:#"Delete"].location != NSNotFound) {
// Do whatever you want here
}
}
}
This might help you.
- (void)willTransitionToState:(UITableViewCellStateMask)state
{
[super willTransitionToState:state];
if ((state & UITableViewCellStateShowingDeleteConfirmationMask) == UITableViewCellStateShowingDeleteConfirmationMask)
{
for (UIView *subview in self.subviews)
{
if ([NSStringFromClass([subview class]) isEqualToString:#"UITableViewCellDeleteConfirmationControl"])
{
UIImageView *deleteBtn = [[UIImageView alloc]initWithFrame:CGRectMake(0, 0, 64, 33)];
[deleteBtn setImage:[UIImage imageNamed:#"arrow_left_s11.png"]];
[[subview.subviews objectAtIndex:0] addSubview:deleteBtn];
}
}
}
}
Referenced from:
Customize the delete button in UITableView
create custom delete button for uitableview
Custom Delete button On Editing in UITableView Cell
-(void)willTransitionToState:(UITableViewCellStateMask)state{
NSLog(#"EventTableCell willTransitionToState");
[super willTransitionToState:state];
if((state & UITableViewCellStateShowingDeleteConfirmationMask) == UITableViewCellStateShowingDeleteConfirmationMask)
{
UIImageView *deleteBtn = [[UIImageView alloc]initWithFrame:CGRectMake( 320,0, 228, 66)];
[deleteBtn setImage:[UIImage imageNamed:#"BtnDeleteRow.png"]];
[[self.subviews objectAtIndex:0] addSubview:deleteBtn];
[self recurseAndReplaceSubViewIfDeleteConfirmationControl:self.subviews];
[self performSelector:#selector(recurseAndReplaceSubViewIfDeleteConfirmationControl:) withObject:self.subviews afterDelay:0];
}
}
The solutions above didn't work for me for iOS 7, at - (void)willTransitionToState:, the delete button wasn't in the view heirarchy so I wasn't able to manipulate anything. I ended up doing everything on - (void)didTransitionToState:. The example below was specifically for when my cells had some spacing at the top so I'm altering the frame of the delete button. If you want to customize the delete button, you can just add a view on top of the delete button or replace it with your own UIButton
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
//your own stuff
//for some reason, editingAccessoryView cannot be nil and must have a non-CGRectZero frame
self.editingAccessoryView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 1, 1)];
}
return self;
}
- (void)didTransitionToState:(UITableViewCellStateMask)state
{
[super didTransitionToState:state];
if ((state & UITableViewCellStateShowingDeleteConfirmationMask) == UITableViewCellStateShowingDeleteConfirmationMask)
{
UIView *deleteButton = [self deleteButtonSubview:self];
if (deleteButton) {
CGRect frame = deleteButton.frame;
frame.origin.y += defined_padding;
frame.size.height -= defined_padding;
deleteButton.frame = frame;
}
}
}
- (UIView *)deleteButtonSubview:(UIView *)view
{
if ([NSStringFromClass([view class]) rangeOfString:#"Delete"].location != NSNotFound) {
return view;
}
for (UIView *subview in view.subviews) {
UIView *deleteButton = [self deleteButtonSubview:subview];
if (deleteButton) {
return deleteButton;
}
}
return nil;
}
How to resign a UITextField of UISearchBar? I tried with the below code
UIView * subView;
NSArray * subViews = [self.searchBar subviews];
for(subView in subViews)
{
if( [subView isKindOfClass:[UITextField class]] )
{
((UITextField*)subView).delegate=self;
((UITextField*)subView).returnKeyType=UIReturnKeyDone;
break;
}
}
for (UIView *subview in self.searchBar.subviews)
{
if ([subview conformsToProtocol:#protocol(UITextInputTraits)])
{
[(UITextField *)subview setClearButtonMode:UITextFieldViewModeWhileEditing];
}
}
And added the TextField Delegate method
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
[textField resignFirstResponder];
return YES;
}
this works but this resigns the keyboard oly if the textfield is not empty. If the textfield is empty then it is not resigning
Use this :
[searchBar resignFirstResponder];
Please do this one...
-(void)searchBar:(UISearchBar *)theSearchBar textDidChange:(NSString *)searchText
{
if (searchBar.text.length == 0)
[searchBar resignFirstResponder];
}
i hope this will work fine.
First set Delegate in .h file like bellow...
#interface yourViewController : UIViewController<UISearchBarDelegate>
and when you want to resign keyboard of UISearchBar simple use bellow line..
[searchBar resignFirstResponder];
UPDATE:
-(BOOL)searchBarShouldEndEditing:(UISearchBar *)searchBar{
[self.searchBar resignFirstResponder];
return YES;
}
In my application I have to add a search bar at the head of the tableview. I am able to add the searchbar but problem is without adding default search bar of ios can i add my customize search bar?? I am giving an image to see what types of search bar will be there...
you can subclass the UISearchBar and override the layoutSubviews method :
- (void)layoutSubviews {
UITextField *searchField;
NSUInteger numViews = [self.subviews count];
for(int i = 0; i < numViews; i++) {
if([[self.subviews objectAtIndex:i] isKindOfClass:[UITextField class]]) { //conform?
searchField = [self.subviews objectAtIndex:i];
}
}
if(!(searchField == nil)) {
searchField.textColor = [UIColor whiteColor];
[searchField setBackground: [UIImage imageNamed:#"yourImage.png"] ];
[searchField setBorderStyle:UITextBorderStyleNone];
}
[super layoutSubviews];
}
Also you can :
//to clear searchbar backgraound
- (void) clearSearchBarBg
{
for (UIView *subview in theSearchBar.subviews)
{
if ([subview isKindOfClass:NSClassFromString(#"UISearchBarBackground")])
{
[subview removeFromSuperview];
break;
}
}
}
//display showSearchButtonInitially in a keyboard
- (void)showSearchButtonInitially
{
UIView * subview;
NSArray * subviews = [theSearchBar subviews];
for(subview in subviews)
{
if( [subview isKindOfClass:[UITextField class]] )
{
NSLog(#"setEnablesReturnKeyAutomatically");
[((UITextField*)subview) setEnablesReturnKeyAutomatically:NO];
((UITextField*)subview).delegate=self;
[((UITextField*)subview) setEnabled:TRUE];
((UITextField*)subview).borderStyle = UITextBorderStyleNone;
break;
}
}
}
Look for Apple DOC for UISearchBar
You have bunch of methods there to get whatever you want
You can get UITextView Inside the search bar by
UITextField *textField = [searchBar.subviews objectAtIndex:2];
if ([textField isKindOfClass:[UITextField class]]) {
//Do your customization
}
Again look for AppleDoc for UITextField. You have bunch of methods for that also.
Yeah definitely. You can make your custom search bar (which is a sub-class of UIView) and add it as subview to the tableHeaderView.
[[searchBarDesign.subviews objectAtIndex:0] removeFromSuperview];
here searchBarDesign is my searchBar name.
I think it's better just set all properties of UISearchBar when it is loaded.
#interface MySearchBar : UISearchBar
#end
#implementation MySearchBar
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[self myInitialize];
}
return self;
}
-(void)awakeFromNib
{
[super awakeFromNib];
[self myInitialize];
}
-(void)myInitialize
{
self.backgroundImage = [UIImage imageNamed:#"image.png"];
for (UIView* subview in self.subviews) {
if ([subview isKindOfClass:[UITextField class]]) {
//customize text field
UITextField* textfield = (UITextField*) subview;
}
}
}
#end
how can i programmatically show/hide this opaque view from UISearchDisplayController?
Probably in searchDisplayControllerWillBeginSearch or searchDisplayControllerDidBeginSearch i need to set something... but what?
thanks.
Temporary solved using UIKeyboardWillAppearNotification.
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardWillShow) name:UIKeyboardWillShowNotification object:nil];
OpaqueView is an UIControl with alpha = 0.8.
- (void) keyboardWillShow {
for( UIView *subview in self.view.subviews ) {
if( [subview isKindOfClass:[UIControl class]] ) {
UIControl *v = (UIControl*)subview;
if (v.alpha < 1) {
v.hidden = YES;
}
}
}
}
I used this ORRIBLE way to temporary fix problem.... any other idea will be appreciated!
thanks.
Code given by elpsk is current but will not work in iOS7 and above
Code working in both iOS6 and iOS7 is as below
- add below notification in viewDidLoad
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardWillShow) name:UIKeyboardWillShowNotification object:nil];
Write below function
- (void) keyboardWillShow {
for( UIView *subview in self.view.subviews ) {
if([subview isMemberOfClass:[UIControl class]] ||
([[[subview class] description] isEqualToString:#"UISearchDisplayControllerContainerView"])) {
UIControl *v = (UIControl*)subview;
if (v.alpha < 1) {
v.hidden = YES;
}
}
}
}
NOTE : Code just have one extra condition as in iOS7 UIControl class become UISearchDisplayControllerContainerView,
The other answers where not working for me. This one works for me on iOS7 and iOS8.
for( UIView *subview in self.view.subviews ) {
if([subview isMemberOfClass:[UIControl class]] ||
([[[subview class] description] isEqualToString:#"UISearchDisplayControllerContainerView"])) {
for(UIView *subView2 in subview.subviews)
{
for(UIView *subView3 in subView2.subviews)
{
if (subView3.alpha < 1) {
subView3.hidden = YES;
}
}
}
}
}
If you don't need support for iOS7 please don't use the searchDisplayController anymore because its deprecated. For iOS8 use the UISearchController and the dimsBackgroundDuringPresentation
Property
Ref: https://developer.apple.com/library/prerelease/ios/documentation/UIKit/Reference/UISearchController/index.html#//apple_ref/occ/instp/UISearchController/dimsBackgroundDuringPresentation
Mmmm...quick answer. Not pretty but surely works
#pragma mark UISearchBarDelegate
// Displays a view to simulate the lose of focus
- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar {
searchBar.showsCancelButton = NO;
searchBar.autocorrectionType = UITextAutocorrectionTypeNo;
UIButton *view1 = [[UIButton alloc] init];
view1.frame = CGRectMake(0, 0, 320, MAX(480, self.tableView.contentSize.height));
view1.alpha = 0.6;
view1.tag = 2000;
view1.backgroundColor = [UIColor blackColor];
[view1 addTarget:self
action:#selector(removeView)
forControlEvents:UIControlEventTouchUpInside];
[self.tableView setScrollEnabled:NO];
[self.tableView addSubview:view1];
[view1 release];
}
/**
* Pop the view and the keyboard
*/
- (void)removeView {
UIView *v = [self.tableView viewWithTag:2000];
v.hidden = YES;
[v removeFromSuperview];
[self.tableView setScrollEnabled:YES];
[self.searchBar resignFirstResponder];
}
That view is showed when you're writing, so I guess you should use it at searchBarTextDidBeginEditing. If I'm wrong, use it when you start searching or whatever.
I have a search functionality using UISearchBar that occurs on-the-fly, so I think it would be more obvious to replace that "Search" button on the keyboard with "Done".
Is there a way to do that?
thanks
You can change the keyboardType property of your UISearchBar object. However, there is not a way to change the returnKeyType directly. You may be able to filter down and change it manually. Check the documentation for UISearchBar and see if you can find returnKeyType as that is what you are looking for.
I accomplish it this way:
// -- Basic UISearchBar setup.
self.theSearchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0,0,320,38)];
[self.theSearchBar setDelegate:self];
[self.view addSubview:self.theSearchBar];
// -- Customize the returnKeyType of the search bar's nested UITextField.
UITextField *searchBarTextField = [[self.theSearchBar subviews] objectAtIndex:1];
searchBarTextField.returnKeyType = UIReturnKeyGo;
Hope that is helpful. This approach (i.e. grabbing a subview by index) may break in the future, but it works fine for now.
for (UIView *view in _searchBar.subviews){
if ([view isKindOfClass:[UITextField class] ]) {
UITextField *searchTf = (UITextField *)view;
searchTf.returnKeyType = UIReturnKeyDone;
}
}
This is working for iOS 6
UITextField *searchBarTextField = [[searchBarObj subviews] objectAtIndex:1];
searchBarTextField.returnKeyType = UIReturnKeyDefault;
[searchBarTextField setEnablesReturnKeyAutomatically:NO];
This is working for iOS 7
for (UIView *subview in self.searchBar.subviews)
{
for (UIView *subSubview in subview.subviews)
{
if ([subSubview conformsToProtocol:#protocol(UITextInputTraits)])
{
UITextField *textField = (UITextField *)subSubview;
[textField setKeyboardAppearance: UIKeyboardAppearanceAlert];
textField.returnKeyType = UIReturnKeyDone;
break;
}
}
}
Don't rely on it being the second subview, use isKindOfClass: method to check. It will be more iOS update proof that way.
for (UIView *subview in self.theSearchBar.subviews) {
if ([subview isKindOfClass:[UITextField class]]) {
[(UITextField *)subview setReturnKeyType:UIReturnKeyGo];
break;
}
}