Customizing a UITableView with Searchbar - objective-c

I have a TableView with a search bar. But I want to add another view (lets say a label) in to the TableView (so it scrolls with the tableview) . For an example, if you open iPhones Phone Contacts application, under All Numbers, you can see a lable called "My Number:". Which must be at the same hierarchical level as the searchbar. I tried to add a new label just above the search bar, but storyboards don't allow me to do that.
In here if I drag and drop a UILabel to this hierarchy it either replaces the searchbar at the top , or the label drops inside of the prototype cell. There is no other way of showing searchbar and Label both at once.
Is there any way of doing this?

Create a separate view outside the view controller's view (or inside, it doesn't matter. you can even create this programmatically) and link it to an IBOutlet myCustomView.
Create an IBOutlet searchBar and link your UISearchBar
in viewDidLoad; you can use
[searchBar addSubView:myCustomView];
and add your custom view above the search bar.
you can show/hide (myCustomView.hidden = YES / NO) the custom view or add and remove it from superview whenever you need.
ex.
- (IBAction)didTapShowCustomHeaderButton {
myCustomView.hidden = NO;
}
- (IBAction)didTapHideCustomHeaderButton {
myCustomView.hidden = YES;
}

add the below two delegates in the code
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
UILabel *label = [[[UILabel alloc] initWithFrame:CGRectMake(10, 10, 100, 30)] autorelease];
label.text = #"My Label";
label.backgroundColor = [UIColor clearColor];
return label;
}
-(CGFloat)tableView:(UITableView*)tableView heightForHeaderInSection:(NSInteger)section{
return 30 // this height should be equivalent to the myLabel height u declared in headerView above
}

Related

Is it possible to Have a Searchbar in a UIViewController iOS 8?

I need to have a Searchbar inside a ViewController as the picture bellow. I don't wanna use UItableViewcontroller. Is it possible to have this searchbar that will help me to query in a NSMutableArray thanks to NSpredicate ?
My Goal
After Searching showing the results of the array in the View "white view".
Yes, It is possible.
You can create a search bar programmatically.
First,Add UISearchBarDelegate Protocol in .h (header) file.
#interface ViewController : UIViewController<UISearchBarDelegate>
Then, Create UISearchBar and add as subview in your view.
UISearchBar searchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(30, 80, screen.size.width-60, 40)]; //give your frame x,y and width and height
searchBar.placeholder = #"Enter City Name";
searchBar.delegate = self;
//searchBar.hidden = NO;
[self.view addSubview:searchBar];
Now, Implement delegate methods
- (void)searchBarSearchButtonClicked:(UISearchBar *)aSearchBar{
//your code when search button clicked
}
-(void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText {
//your code when you are entering text in search bar
}

Adding viewcontroller elements to another scrollview

I have a ViewController called Tag that has labels and photos I need to recreate on another viewcontroller called "Task" with a scrollview. I've added these by saying:
Task.m
- (void)loadFromNib {
Tag *tag = [[Tag alloc] init];
[self.view addSubview:tag.imageView3];
[scroll addSubview:tag.imageView3];
The image only loads when it's not added to the scrollview.

Where to set popover size?

I have a UIViewController called HomeViewController and it has a model that contains an array of data. HomeViewController also has a button that when pressed will show a UITableViewController that display's the model's array of data.
My question is, what is the standard/best way to set the popover's size? I only want the popover to be tall enough to display the data, but no taller. What is common practice? I assume that I need to set contentSizeForViewInPopover at some point but I'm not sure where...In the viewDidLoad method of the popover class? In the prepareForSegue method?
Here's the code I have so far: (Note that DataPresentingViewController is my popover view controller class`)
//In HomeViewController
- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if([segue.destinationViewController isKindOfClass:[DataPresentingViewController class]])
{
DataPresentingViewController *dest = (DataPresentingViewController *) segue.destinationViewController;
dest.mySavedData = self.myModel.mySavedData;
}
}
I know that I could just set the contentSizeForViewInPopover here in the prepareForSegue method; however, this seems like something the popover class should deal with.
As of iOS7 contentSizeForViewInPopover is deprecated. You should use UIViewController's preferredContentSize property instead.
Hope this helps!
set contentSizeForViewInPopover in ViewDidLoad method in HomeViewController
contentSizeForViewInPopover is deprecated in iOS 7
The property: popoverContentSize of UIPopoverController represents the size of the content view that is managed by the view controller in the contentViewController property of UIPopoverController.
Reference
The advantage is that it is available in iOS 3.2 and later, so you don't need to check device version everytime, just replace contentSizeForViewInPopover method with your UIPopOverController object instance.
Have you tried:
setPopoverContentSize:<#(CGSize)#> animated:<#(BOOL)#>
in your segue logic block. Useful if you want the popover size to be variable based upon a data set, or view placement or whatever.
// self.contentSizeForViewInPopover = CGSizeMake(320.0, 600.0); //Deprecated in ios7
self.preferredContentSize = CGSizeMake(320.0, 600.0); //used instead
A little known trick to sizing your UIPopoverViewController to match the height of your UITableView is to use the tableView's rectForSection method to give you the height. Use the height in your viewController's contentSizeForViewInPopover like this:
- (CGSize)contentSizeForViewInPopover {
// Currently no way to obtain the width dynamically before viewWillAppear.
CGFloat width = 200.0;
CGRect rect = [self.tableView rectForSection:[self.tableView numberOfSections] - 1];
CGFloat height = CGRectGetMaxY(rect);
return (CGSize){width, height};
}
Try the following code:
- (IBAction)setData:(id)sender
{
UIViewController *popoverContent=[[UIViewController alloc] init];
UITableView *tableView=[[UITableView alloc] initWithFrame:CGRectMake(265, 680, 0, 0) style:UITableViewStylePlain];
UIView *popoverView=[[UIView alloc] initWithFrame:CGRectMake(0, 0, 200, 300)];
popoverView.backgroundColor=[UIColor whiteColor];
popoverContent.view=popoverView;
popoverContent.contentSizeForViewInPopover=CGSizeMake(200, 420);//setting the size
popoverContent.view=tableView;
tableView.delegate=self;
tableView.dataSource=self;
self.popoverController=[[UIPopoverController alloc] initWithContentViewController:popoverContent];
[self.popoverController presentPopoverFromRect:CGRectMake(400, 675, 0, 0) inView:self.view permittedArrowDirections:UIPopoverArrowDirectionDown animated:YES];
}
It looks like you want to do it programmatically, but in the storyboard, before you hook up a view controller to a segue, under the attributes inspector there is a "popover, use explicit size option." Maybe you can set the size that would work the best for your App first and not worry about the size with using code. Hope this helps, let us know how it goes.

adding subviews to UITableViewCell's content view makes cell unselectable

I want to add some static text to a UITableViewCell in a UITextView.
UITextView *addressField = [[UITextView alloc] initWithFrame:CGRectMake(0, 0, 300, 75)];
[addressField setBackgroundColor:[UIColor clearColor]];
[addressField setFont:[UIFont fontWithName:#"HelveticaNeue" size:14]];
[addressField setContentInset:UIEdgeInsetsMake(0, 20, 0, 0)];
[addressField setEditable:NO];
[addressField setScrollEnabled:NO];
// change me later
[addressField setText:#"John Doe\n555 Some Street\nSan Francisco, CA, 00000"];
[cell.contentView addSubview:addressField];
[addressField release];
This works great but I this code makes the cell unselectable probably because the UITextView is covering the entire cell.
How can I work around this so that I can have both the UITextView and selectable cells?
btw, I could make the UITextView size a bit smaller but users would still not be able to select the cell if they touch the UITextView.
I think a slightly better way to do it is to create a tap gesture recognizer on the entire table. (For example in your viewDidLoad)
// gesture recognizer to make the entire cell a touch target
UITapGestureRecognizer* tap = [[UITapGestureRecognizer alloc]
initWithTarget:self action:#selector(changeFocus:)];
[tableView addGestureRecognizer:tap];
[tap release];
Then you create a selector (changeFocus: in this case) to do the actual selecting.
- (void)changeFocus:(UITapGestureRecognizer *)tap
{
if (tap.state == UIGestureRecognizerStateEnded)
{
CGPoint tapLocation = [tap locationInView:self.tableView];
NSIndexPath* path = [self.tableView indexPathForRowAtPoint:tapLocation];
[self tableView:self.tableView didSelectRowAtIndexPath:path];
}
}
You can make your changeFocus method more elaborate to prevent selections or give focus to specific subviews of the selected indexPath.
I would adopt the following approach in order to keep interaction enabled with both the UITextView and the UITableViewCell.
Declare your controller class (a UITableViewController I guess ?) as UITexView delegate.
When you declare your UITextView, set the table view controller as it's delegate.
Implement one of the UITextViewDelegate methods (ex : - (void)textViewDidChangeSelection:(UITextView *)textView) in your table view controller .m file.
From within this method you can manipulate the targeted cell either with a custom code or by triggering the tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *) delegate method through selectRowAtIndexPath:animated:scrollPosition:.
Your code might then look like :
In the table view controller .h file :
#interface MyTableViewController : UITableViewController <UITextViewDelegate> { ...
...
}
In the table view controller .m file :
UITextView *addressField = [[UITextView alloc] initWithFrame:CGRectMake(0, 0, 300, 75)];
[addressField setDelegate:self];
...
Then implement this function for example (or any other suitable UITextViewDelegate function) :
- (void)textViewDidChangeSelection:(UITextView *)textView {
// Determine which text view triggered this method in order to target the right cell
...
// You should have obtained an indexPath here
...
// Call the following function to trigger the row selection table view delegate method
[self.tableView selectRowAtIndexPath:indexPath animated:YES scrollPosition:UITableViewScrollPositionNone]
}
Note that there are other alternatives like subclassing UITextView and deal with it's touch methods. I would recommend to use the possibilites offered by its delegate protocol though.
Note also that it might be handy to have your UITextView declared or at least referenced as an instance variable of the table view controller class. This will help you easily keep track of which addressField was hit and get the right indexPath.
[addressField setUserInteractionEnabled:NO];
I hope this helps you a bit:
[self.view insertSubview:TextView aboveSubview:TableView];
Or vice-versa based on your requirements.

Several TableView questions

I am looking to create a similar interface to the iTunes iPhone app search interface. I have a few questions I can't seem to find an answer for:
Here is an image of the iTunes iPhone app search interface in question:
How do I create the tableView section subtitle, e.g. the Tap to Preview, Double-Tap to View info under the Top Hits section title.
How is the price button created to float right? Is this done natively or using a custom UIView?
Finally how would I differentiate between a single tap and double tap on any of the table view cells?
You will need to create a Custom UITableViewCell, here's a tutorial. for the price button and other visuals of the cell.
As for the Tap to Preview subtitle, you can create a custom header view, see:
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
Most likely, you would need to create 2 UILabels for this view, and obviously you would want to match the fonts used here.
An Example
- (UIView *) tableview:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
UIView *headerView = [[[UIView alloc] initWithFrame:CGRectMake(0, 0, tableView.bounds.size.width, 30)] autorelease];
UILabel * label = [[UILabel alloc] initWithFrame:CGRectZero];
label.text = #"Top Hits";
label.backgroundColor = [UIColor clearColor];
label.font = [UIFont boldSystemFontOfSize:17];
[headerView addSubview:label];
UILabel * label2 = [[UILabel alloc] initWithFrame:CGRectZero];
label2.text = #"Tap to Preview, Blah blah blah";
label2.backgroundColor = [UIColor clearColor];
label2.font = [UIFont fontWithName:#"Apple's Default Font?" size:17];
[headerView addSubview:label2];
/* something like this */
return headerView;
}
- (CGFloat) tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
return 50.0f;
}
Most of your questions are address well in Apple's Table View Programming Guide for iOS. Here are some short answers:
You can make a header for a section be a UIView, in which case you can use multiple UILabels to create titles with subtitles and the like.
This is probably set as the accessoryView of the UITableViewCell, or it may be an entirely custom subclass of UITableViewCell.
For this, you'll need to implement the UITableViewDelegate method - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath. For more on customizing this method (e.g. to differentiate between single and mutliple taps), check out the Managing Selections section of the above tutorial.
1-For the Custom header
you can use the table view datasource method
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section;
and then you can either create the view programmtically with all the labels
or you can make an seperate view in the xib ,create its instance in your viewcontroller and return that instance in the above datasource method- this approach would be much easier and simpler.
2- You can implement the price button by using a uibutton and setting it an background image
in a custom table view cell. you can hide/unhide this button as per your functionality.
3- I would suggest you to disable the tableview selection and add tap gesture recognizers to the custom table view cell. this would give you more flexibility
Hope this could help you