views:

5478

answers:

15

I have a UITableView with an Index on the side; I want to add a UISearchBar to it, but the index overlaps with the "x" to clear the search. I've noticed in the Contacts application, the textfield within the UISearchBar is resized to accommodate this, but I can't work out how to do this in my own app.

I have tried the following in my viewDidLoad, but it does not seem to work.

UITextField * textField = (UITextField *)[[self.search subviews] objectAtIndex:0];
CGRect r = textField.frame;

[textField setFrame:CGRectMake(r.origin.x, r.origin.y, r.size.height, r.size.width-30)];

Any ideas?

A: 

The text field used in UISearchBar is a subclass of UITextField called UISearchBarTextField.

AFAIK, there's no way to resize a UISearchBarTextField using the public API, and the private API doesn't reveal much either.

Maybe you can take a look at UISearchBarTextField's subviews, if it has any.

UPDATE: It doesn't.

UPDATE 2: I think you should take a look at UITextField's rightView property. The below code, although it doesn't work, seems like a good starting point:

UIView *emptyView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 25, 25)];
[textField setRightView:emptyView];
[textField setRightViewMode:UITextFieldViewModeAlways];
[emptyView release];
Can Berk Güder
Looks like you could bluff it that way by sticking an image on top of it. Add the line: emptyView.backgroundColor = [UIColor blackColor];into your code to see how it would work.
Padraig
A: 

It kind of looks as though Apple resize the view (note that the index is animated to the right, off screen), making it bigger than the screen.

I would imagine that you'd need to implement the searchBarTextDidBeginEditing: method of the UISearchBarDelegate to trigger this at the appropriate point. This does, however, feel a bit hacky do maybe there's a better way of doing it.

Stephen Darlington
Thanks Stephen. I'm interested in getting the initial UISearchBar textfield to be smaller from the start. There are some other threads about the index animation, but that's not what I'm trying to work out right now.
Padraig
+6  A: 

Ok, I've come up with a solution.

  1. Create a subclass of UISearchBar
  2. Include this code in the drawRect: method.

    UITextView * textField = [self.subviews objectAtIndex:0];
    textField.frame = CGRectMake(5, 6, (310 - kRightSideMargin), 31); 
    
    
    [super drawRect:rect];
    

Note: kRightSideMargin is a constant I set in my header file; I have it set to 25.

Thanks for the suggestions from everyone else.

Padraig
Im using v3.0 iphone SDK and placing this code in drawRect did not work. What actually worked for me was placing this code in layoutSubviews. Not exactly sure why - the only conclusion i can draw is that there's a change in v2 -> v3
CVertex
+8  A: 

Why not just make the actual UISearchBar smaller horizontally, and place an (empty) UINavigationBar to the right of it? They will render the exact same background.

Better than hacking the internals of Apple's objects that could change.

Also, when animating the UISearchBar's width, you'll notice that the inner text field is not animated along with it. You can fix this by calling UISearchBar's "layoutSubviews" within your animation block after changing its frame. (that's where it determines the size of the inner text field)

Nick Farina
Thank you so much man!!!! I couldn't figure out how to get the searchbar to animate. layoutSubviews was the key.
Meroon
Thank you *very* much!!!
Felixyz
I had a UISearchBar on the right-hand-side of a UINavigationBar and animate it in and out, just like the Safari app. This tip to layoutSubview of UISearchBar was the final piece of the puzzle to get it working just like Safari. No need to search subviews, or anything like that, which isn't the right or clean solution. Thanks again for the right answer.
petert
This also solved the problem for me in an easy and clean way. Thanks!
David Coufal
+1  A: 

but how to implement animation that reflect the resizing?

A: 

Another appraoch (though tedious) would be to resize the search bar and fill the 'gap' with a navigation bar. Works for me.

bare_nature
A: 

What I've come up with isn't too much better. Basically, I make an empty view with the frame that I want to use for the search bar. Then I create a UIToolbar to go behind the search bar. Be sure to set its frame to the same frame as the UIView, except that the Y value has to be -1; otherwise, you'll get two borders drawn at the top. Next create your UISearchBar, but set the frame's width to 30 (or whatever makes sense for your app) less than the UIView. Add them as subviews and set your UIView as the tableHeaderView.

Jeff Kelley
+1  A: 

Sorry for Necroposting, but I found another way to make a little space on the right of the textfield. I was having the problem, that I had an indexed tableview with a searchbar as the first row. Now the index and the searchbar (made in IB, btw.) were overlapping. It tried almost everything with no success. It seems that the width and height properties of the textifield don't respond... So I came up with this:

searchBar.showsCancelButton = YES;

UIView *cButton = [searchBar.subviews objectAtIndex:2];

cButton.hidden = YES;

I still can't adjust the size of the space, but this does it for now... although... pretty weird solution...

swissdude
Thanks, this was nice and easy.
CJCraft.com
A: 

thanks

for the moment, its good for me :)

HFX
+1  A: 
+5  A: 

Hi all... it's much easier than all these suggestions. In interface builder, instead of putting the Search Bar as the header of your Table View, you can put a View instead. Then, put a Navigation Bar inside this View. Grab the left resizing handle of the Navigation Bar and pull it to the right until the N B is only 25 pixels wide. Clear out the Title in the N B (double click to select it, then delete). Then, add a Search Bar into the same View. Move its right resizing handle to the left, adjust so that it abuts the N B. That's it.

You can enable a cancel button if you want too and it also won't overlap the index (remains within the search bar).

Apparently a Table View can only have 1 subview in its header, that's why you need to put the View first, then the N B and Search Bar inside it.

UPDATE: see Beginning iPhone Development from Apress, p. 241 of SDK 3 edition. You just disable the index while searching.

- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView {
    if (isSearching) {
        return nil;
    }
    return keys;
}

Also they talk about adding a magnifying glass to the top of the index.

Great book all around.

Mike
Worked great - one addition - our table view has some custom style applied to it and to get the Navigation Bar and the Search Bar to look the same I had to make the parent View transparent (i.e. no background) - so if things don't quite match try this.
Joe
A: 

I followed Mike's advice by making a UIView, then putting a Navigation Bar and UISearch Bar inside it. Only problem is first time the search bar is shown its background is the same as a Navigation Bar normally?

Interestingly, if I activate the search, then click cancel the background of this 'fixed'!?

I'm using SDK 3.0, so I removed the UISearchBar item made when I dragged a UISearchDisplayController in to my NIB, then made the view as described above and wired it up to the file owner and the searchBar outlet in the search display controller.

petert
+1  A: 

Everyone has provided ways to modify the UI. I have discovered how to obtain identical results. You must provide the following two implementations:

  1. Use UISearchDisplayController More importantly, make sure you initialize it with:

- (id)initWithSearchBar:(UISearchBar *)searchBar contentsController:(UIViewController *)viewController

Failure to set a valid UISearchBar (or passing nil) will prevent the adjustment of the UITextField for the index.

  1. You must return a valid array of titles by implementing:

- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView;

If you return nil, the index will not be displayed, and the UITextField will not be properly adjusted.

I've submitted a bug report to Apple, suggesting that it seems logical that only #2 should be required, not #1. I have found nothing in the Human Interface Guideline (iPhone HIG) requiring use of the UISearchDisplayController.

Mark
I used the IB search display controller — which I think implements `-initWithSearchBar:contentsController:` — and this worked to resize the search bar field.
Alex Reynolds
+1  A: 

It work fine!!!

[searchBar setContentInset:UIEdgeInsetsMake(5, 0, 5, 35)];

Oscar
A: 

The key is to use the "Search Bar and Search Display Controller" and not the "Search Bar" when using Interface Builder.

Graeme Wicksted