I am trying to set up a UITableView, with x amount of sections and X number of rows per section.
However I would like to add a single row to the top of my UITableView Is there is a way to hardcode this into the view?
I currently return the number of sections and rows per section based off a NSdictionary like so.
- (NSInteger)numberOfSectionsInTableView: (UITableView *)tableView
{
// Return the number of sections.
return [letterDictionary count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// returns the number of rows per section based off each entry in letterDictionary
currentLetter = [sectionLetterArray objectAtIndex:section];
return [[letterDictionary objectForKey:currentLetter] count];
}
You can add a "header" to the tableview.
In your tableview class:
self.tableView.tableHeaderView = yourView;
You cannot just add a row above your UItable within the table. If you just need a row of text why not use UITextField, UILabel or UITextView depending on your needs and just position it above your UItable whereever you like.
If I missunderstood you and you just like to add one row as the very first one in your first section, all you need to do sth like this:
if (section == 0) {
return [[letterDictionary objectForKey:currentLetter] count]+1;
} else
{
return [[letterDictionary objectForKey:currentLetter] count];
}
and ensure that when returning row for indexpath you have also a similar if-statement and return whatever you need for section == 0 and row == 0.
But this first row will certainly scroll away if you scroll down your table view - as said I am not sure exactly what you need.
You could try to customize your tableview section's header...
For example you can use something like this:
YourController.h
-(UIView *)headerView;
YourController.m
-(UIView *)headerView
{
UIView *header = [[UIView alloc] initWithFrame:CGRectZero];
// Place everything you want in your header
// using [header addSubview:yourSubview];
// Finally set header's frame and return it
header.frame = CGRectMake(0.0, 0.0, 320.0, 44.0);
return header;
}
// Use this to return header's height
-(CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
if (section == yourSection)
{
return [self headerView].frame.size.height;
}
else
{
return [self sectionHeaderHeight];
}
}
// Use this to return your view
-(UIView *)tableView:(UITableVIew *)tableVIew viewForHeaderInSection:(NSInteger)section
{
if (section == yourSection) // To show the header only on a specified section
{
return [self headerView];
}
else
{
return nil;
}
}
If you change your mind and want to customize below the tableView, your can use the same method changing Header with Footer.
Finally take a look at docs about these methods:
- tableView:viewForHeaderInSection:
- tableView:heightForHeaderInSection:
- tableView:viewForFooterInSection:
- tableView:heightForFooterInSection:
Hope this fits your needs!
Related
I have two type of cells that I'll be using my UITableView, so I created two prototype cell with different identifier. I manuelly changed the size but when I compile and run, the two cells have same size.
Is there any way to do it through storyboard and without checking every single time
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
I will have around a good 100 cells at least.
UPDATE: in my case I have a tableview with 3 sections, the first one is small, the second and the third one are bigger.
I think your best option is to use that -tableView:heightForRowAtIndexPath: delegate method you listed and return the height you would like.
You could assign tags to each prototype and use an if/else if conditional.
Or if you have a subclassed UITableViewCell for each prototype you could do something like
...
id cell = [tableView cellForRowAtIndexPath:indexPath];
if ([cell isKindOfClass:[CustomCell1 class]]) {
// return aNumber;
} else if ([cell isKindOfClass:[CustomCell2 class]]) {
// return aNumber;
} else {
return aNumber;
}
...
If you know that the sections if what determines the height of the cell, then you can implement it like this:
- (CGFloat) tableView:(UITableView *)tableView heightForRowAtIndexPath: (NSIndexPath*)indexPath {
CGFloat result;
if (indexPath.section == 0) {
result = 160;
} else {
result = 80;
}
return result;
}
Depending on the heights that you need of course.
I had two UITableView in my project and I am giving custom header to one table using the method:
- (UIView *) tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
if(tableView.tag == 3)
{
SectionInfo *array = [self.sectionInfoArray objectAtIndex:section];
if (!array.sectionView)
{
NSString *title = array.groupdeck.groupTitle;
array.sectionView = [[SectionView alloc] initWithFrame:CGRectMake(0, 0, tblData.bounds.size.width, 45) WithTitle:title Section:section delegate:self];
}
return array.sectionView;
}
else{
return 0;
}
return 0;
}
It is giving the header to the table with the tag 3 like:
But it is giving the default header to other table also even return 0 else condition like:
What am I missing?
Try :
otherTable.sectionHeaderHeight = 0.0;
You don't have to do anything else.
Or:
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
if(tableView.tag == 3)
{
//Required height.
}
else
{
return 0.0;
}
}
It might be defaulting to the default header because you returned a 0. Try returning nil instead.
From: tableView:viewForHeaderInSection: default value?
With Reference to written in Apple Documentation
// custom view for header. will be adjusted to default or specified header height
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section;
It is displaying the default header which has height of 22 for grouped table and 10 for nongrouped table.
Also if the height of your view which you want to display in UITableView is more than above values then you also have to use the UITableView Delegate method
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section;
I don't want to show the "no results" text while my server is processing a search query.
I figured out the exact coordinates of the table cell that contains the label and attempted to cover it.
self.noResultsCoverView = [[[UIView alloc] initWithFrame:CGRectMake(
0.0,
44.0,
320.0,
43.0
)] autorelease];
self.noResultsCoverView.backgroundColor = [UIColor whiteColor];
[self.searchDisplayController.searchResultsTableView addSubview:self.noResultsCoverView];
To my chagrin, my cover was above the table view, but below the label. I need the cover to be above the label. searchResultsTableView::bringSubviewToFront didn't work, which makes me believe that the label isn't a child of the searchResultsTableView at all.
BTW, this Stack Overflow answer doesn't quite work for me. It works on the very first search, but flashes a weird black cover on subsequent searches.
this should do the work properly. The code to return at least one cell:
BOOL ivarNoResults; // put this somewhere in #interface or at top of #implementation
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (tableView == self.searchDisplayController.searchResultsTableView) {
if (filteredList.count == 0) {
ivarNoResults = YES;
return 1;
} else {
ivarNoResults = NO;
return [filteredList count];
}
}
// {…}
// return the unfiltered array count
}
and for "showing" the clean cell:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (tableView == self.searchDisplayController.searchResultsTableView && ivarNoResults) {
static NSString *cleanCellIdent = #"cleanCell";
UITableViewCell *ccell = [tableView dequeueReusableCellWithIdentifier:cleanCellIdent];
if (ccell == nil) {
ccell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cleanCellIdent] autorelease];
ccell.userInteractionEnabled = NO;
}
return ccell;
}
// {…}
}
The easiest way to work around this is to return 1 in numberOfRowsInSection while the query is in progress and leave the dummy cell empty or set its hidden property to YES so it is not visible.
Try this it worked for me
In the UISearchDisplayController delegate do this:=
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString
{
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, 0.001);
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
for (UIView* v in self.searchDisplayController.searchResultsTableView.subviews) {
if ([v isKindOfClass: [UILabel class]] &&
[[(UILabel*)v text] isEqualToString:#"No Results"]) {
[(UILabel*)v setText:#""];
break;
}
}
});
return YES;
}
You need to realize that when you have a UISearchDisplayController, and the search bar is active, the UITableView argument passed into your UITableView data source and delegate methods is in fact NOT your tableView object, but a tableView managed by the UISearchDisplayController, intended to display "live" search results (perhaps results filtered from your main data source, for example).
You can easily detect this in code, and then return the appropriate result from the delegate/data source method, depending on which tableView object is asking.
For example:
- (NSInteger)tableView:(UITableView *)tv numberOfRowsInSection:(NSInteger)section
{
if (tv == self.searchDisplayController.searchResultsTableView) {
// return the number of rows in section for the visible search results.
// return a non-zero value to suppress "No results"
} else {
// return the number of rows in section for your main data source
}
}
The point is that your data source and delegate methods are serving two tables, and you can (and should) check for which table is asking for data or delegation.
By the way, the "No results" is (I believe) provided by a background image which the UISearchDisplayController displays when the delegate says there are no rows... You are not seeing a 2-row table, the first blank and the second with text "No results". At least, that's what I think is happening there.
I have a static table view in my application. This table view is used for preferences.
A section in the table view only has one cell which holds a UISwitch. When this switch is activated, I want to show the section beneath and when it is not, I want to hide the section beneath. All the sections (also the one which should be hidden / shown) is set up using Interface Builder.
Is there any way to hide or show this section when the table view is static as a static table view doesn't have a data source? Should it be easier, I could also agree to use the same section but add / hide rows from this section when the switch is on or off.
EDIT
I have come closer how to do this.
Setting the height of the cells in the section and the height of the footer and header of the section to 0, I can nearly hide the section. I still have some spacing between the section above and the section below that I cannot figure out how to get rid of.
Does anyone have an idea where this extra spacing comes from? See the photo below.
This is the code I use to nearly hide the section.
/* Will display cell */
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.section == 2)
cell.hidden = YES;
else
cell.hidden = NO;
}
/* Height of cell */
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.section == 2)
return 0;
return [super tableView:tableView heightForRowAtIndexPath:indexPath];
}
/* Height of section header */
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
if (section == 2)
return 0;
return [super tableView:tableView heightForHeaderInSection:section];
}
/* Height of section footer */
- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section
{
if (section == 2)
return 0;
return [super tableView:tableView heightForFooterInSection:section];
}
This is how the table view looks now. There is still some space I need to hide. The extra space is between the sections labeled "Arbejde" and "Anden".
I got it working using the code in the question. Just set the height to 1.0f instead of 0. It seems that the height only has an effect when it's value is greater than zero.
Reducing the space between sections of the UITableView.
For static cells, I just use this:
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
let cell = self.tableView(self.tableView, cellForRowAt: indexPath)
if cell.isHidden {
return 0
} else {
return cell.bounds.size.height
}
}
see this tutorial this may helps you www.cocoanetics.com/2011/03/expandingcollapsing-tableview-sections/
For static cells I found no decent answers either. If you wish to drop sections or expand a cell then this is the code I used.
Create a BOOL Value in your .m
#interface yourClassName (){
BOOL ddMenuButtonPressed;
}
#end
ddMenu means drop down menu.
Next I set the bool value to false in the viewDidLoad method.
ddMenuButtonPressed = false;
I then initialise the ddButton (in storyboard control+drag from your button or switch to your .h file and create action and set name to ddMenuButton) and use this method in my .m file.
- (IBAction)ddMenuShow:(UIButton *)sender
{
if (sender.tag == 0) {
sender.tag = 1;
ddMenuButtonPressed = true;
} else {
sender.tag = 0;
ddMenuButtonPressed = false;
}
//very important that you include these
//they update the view like a viewDidLoad statement without leaving the screen
//if you have any data entry points in your cell like a textfield it **will not** erase that data fortunately
[self.tableView beginUpdates];
[self.tableView endUpdates];
}
Finally we add the following method:
// Handle expanding and minimising cell or section
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
//if the section is 0 (and there is only one cell) and ddMenuButtonPressed hasn't been pressed
if (indexPath.section == 0 && ddMenuButtonPressed == false){
//return the height you have it set as in story board (or a number)
return [super tableView:tableView heightForRowAtIndexPath:indexPath];
}
//if the section is 0 and the ddMenuButton has been pressed
if (indexPath.section == 0 && ddMenuButtonPressed == true){
//change the cell height to 380 or whatever size you want
return 380;
}
//otherwise leave cells as they are
else {
return [super tableView:tableView heightForRowAtIndexPath:indexPath];
}
}
And that's it. No fancy coding, nice and clean (minus the commenting) and simple and you can use this over and over for as many sections as you like.
Can I have the number of rows dynamically?
I'm trying to remove a tableView section header and I don'k know how... and I've taught that a solution would be to change the number of sections.
Right now my numberOfSectionsInTableView looks like:
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 2;
}
and
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
beTribesAppDelegate *appDelegate = [UIApplication sharedApplication].delegate;
switch (section) {
case 0:
return [appDelegate.firstArray count];
case 1:
return [appDelegate.secondArray count];
default:
return 0;
}
}
setting the title section like this:
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
sectionTitles = [[NSMutableArray alloc] init];
[sectionTitles addObject:#"firstSection"];
[sectionTitles addObject:#"secondSection"];
NSString *sectionText = [sectionTitles objectAtIndex:section];
return sectionText;
}
I am not sure to understand the question as the answer seems trivial: just change the implementation to return some dynamic value and you are done, right?
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return self.nbSections;
}
Where nbSections is a property to which you will assign the value you want so you can change it at any time you want. So what's the matter then?
PS: Of course, call [tableView reloadData] to recompute the content of your tableView and make the new value being taken into account obviously... maybe that's what you were missing?
To remove the section header you must set the header height to 0 like so
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section{
switch (section) {
case 0:
return 0;
default:
return 44;
}
}
this example will remove the first section header and all the others will be set to 44.
First thing to do would be to move the sectionTitles array into a property on your view controller, and initialise it in your init method.
Then when you want to change the title of a section change the value in the array and call [tableView reloadData]
Do you want to remove the whole section from the tableView or just the header? if you want to just remove the header set the item in the array to #""
If you want to remove the section altogether remove the item from sectionTitles and change your numberOfSectionsInTableView method to read:
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return [sectionTitles count];
}