I created one tableview with 2 section and i displayed the array of the data in the tableview .. now i want to expand and collapse the section…
i am just a beginner please give any sample code for expand and collapse the tableview section…
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 2;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [arraytable count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *cellitem = #"simpletableitem";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellitem];
if (!cell) {
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellitem];
}
cell.textLabel.text = [arraytable objectAtIndex:[indexPath row]];
return cell;
}
This is my cellForRowAtIndexPath and arraytable is my array i give it in view did load
arraytable = #[#"hari12",#"narayanan",#"Praba",#"Deepak",#"Sailesh",#"Ram charan"];
Here's a sample code I've made to achieve what you want.
You can use this as a general guideline, since there are plenty of ways to achieve this, other than what I've done.
I've noticed from your example above that you have a table view with 2 sections, so this is what I'll use for the sample code.
There are maybe better ways to implement the below, but that was at the top of my head, and I think it's pretty simple and straightforward.
I've also included explanations as comments in the code below.
Note that you'll probably need to change some variables' names to fit your code (such as self.tableView, if you use something else) and section1DataArray, section2DataArray
// I've declared 2 BOOL properties to hold whether each section is visible or not
#interface ViewController ()
#property (nonatomic) BOOL section1visible, section2visible;
#end
-(void)viewDidLoad {
// After creating the table view, I've set the footer view frame to CGRectZero,
// so when a table view is collapsed you won't have the table columns 'bounds'
self.tableView.tableFooterView = [[UIView alloc] initWithFrame: CGRectZero];
}
// Then I've created a custom header for each table since I've wanted to make the header
// name a button which collapse/expand the table view.
-(CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
// Here I've set the height arbitrarily to be 50 points
return 50;
}
-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
// Change the below frame to fit your needs. In my example, I've used a table view
// to be at the width of the screen, and the height of 50 points (as we've set above)
UIView *header = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 50)];
// Then create a button
// I've arbitrarily chosen a size of 100x20 and created a frame to be placed in the
// middle of the above header
UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(header.frame.size.width/2 - 50, header.frame.size.height/2 - 10, 100, 20)];
// Now I'm setting the tag (for later use) and title of each button
if(section == 0) { // First section
[button setTitle:#"Section 1" forState:UIControlStateNormal];
button.tag = 0;
} else { // Else, second section, since we only have two
[button setTitle:#"Section 2" forState:UIControlStateNormal];
button.tag = 1;
}
// I've arbitrarily chose to set the button colour to gray colour
button.titleLabel.textColor = [UIColor grayColor];
// Then we need to actually add an action to the button
[button addTarget:self action:#selector(updateTableView:) forControlEvents:UIControlEventTouchUpInside];
// Then we need to add the button to the header view itself
[header addSubview:button];
return header;
}
// Then we need to update our tableView:numberOfRowsInSection: to check for our BOOL value
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
if(section == 0 && self.section1visible) {
return [self.section1DataArray count];
} else if (section == 1 && self.section2visible) {
return [self.section2DataArray count];
} else {
return 0;
}
}
// Then we need to create the actual method the button calls
-(void)updateTableView:(UIButton *)sender {
// Check the button tag, to identify which header button was pressed
NSInteger section = sender.tag;
if(section == 0) {
self.section1visible = !self.section1visible;
} else { // section == 1
self.section2visible = !self.section2visible;
}
// Use an animation to update the UI to create a 'smooth' expand/collapse
[self.tableView reloadSections:[NSIndexSet indexSetWithIndex:section] withRowAnimation:UITableViewRowAnimationFade];
}
Good luck mate.
Related
I need some UI advice.
I have a view that needs to load data formatted like this:
{
"heading": "This is a header",
"content": "This is some detailed content about the header"
},
{
"heading": "This is another headline.",
"content": " These are more details about the headline. "
}
Here are the parameters: On load, it should just display the headings in a table view. Tapping a heading will expand that cell and load the the content or details about it. Here is a rough sketch:
On Load:
Heading 1
Heading 2
Heading 3
Heading 4
On Tap of Heading 2:
Heading 1
Heading 2
Content for Heading 2 get displayed here
Heading 3
Heading 4
There also needs to be a bar button item that will either expand or collapse all cells. Which would like this:
Collapse All:
Heading 1
Heading 2
Heading 3
Heading 4
Expand All:
Heading 1
Content for Heading 1 get displayed here
Heading 2
Content for Heading 2 get displayed here
Heading 3
Content for Heading 3 get displayed here
Heading 4
Content for Heading 4 get displayed here
I used some weird parent/child logic to get the individual cells to expand, but I think I went down a dark path because now I am trying to implement the expand/collapse all and I am stuck.
Does anyone know of any open source code that does this type of accordion table view and/or any suggestion on how to setup a view controller to do this? I have seen a few libraries expand and collapse individual cells, but being able to do all of them is getting tricky.
this is how I do it, perhaps a slightly simpler, although definitely similar approach :)
#import "ViewController.h"
//dont worry, the header is empty except for import <UIKit/UIKit.h>, this is a subclass on UIViewController
#interface ViewController ()<UITableViewDataSource, UITableViewDelegate>
#property (weak, nonatomic) UITableView *tableView;
#end
#implementation ViewController
{
//ivars
BOOL sectionIsOpen[4]; //we will use this BOOL array to keep track of the open/closed state for each section. Obviously I have the number of sections fixed at 4 here, but you could make a more dynamic array with malloc() if neccesary..
}
- (void)viewDidLoad {
[super viewDidLoad];
UITableView *tv = [[UITableView alloc]initWithFrame:self.view.bounds style:UITableViewStyleGrouped];
tv.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
tv.dataSource = self;
tv.delegate = self;
[self.view addSubview:tv];
self.tableView = tv;
// Do any additional setup after loading the view, typically from a nib.
}
#pragma mark - UITableViewDataSource
-(NSInteger )numberOfSectionsInTableView:(UITableView *)tableView{
return 4;
}
-(NSInteger )tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return ((sectionIsOpen[section]) ? [self numberOfRowsInSection:section] : 0);
}
-(NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section{
//put your switch() here...
return [NSString stringWithFormat:#"I am section %i", (int)section ];
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *cellId = #"cellID";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellId];
if (!cell) {
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellId];
}
//etc etc decorate your cell...
cell.textLabel.text = [NSString stringWithFormat:#"cell %i / %i", (int)indexPath.section, (int)indexPath.row ];
return cell;
}
#pragma mark - UITableViewDelegate
-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section{
const CGRect fr = CGRectMake(0, 0, 320.0, 40.0 );
UIButton *btn = [[UIButton alloc]initWithFrame:fr];
[btn setTitle:[self tableView:tableView titleForHeaderInSection:section] forState:UIControlStateNormal ];
[btn setTag:section];
[btn addTarget:self action:#selector(sectionOpenToggle:) forControlEvents:UIControlEventTouchUpInside];
// add an image, colour etc if you like
return btn;
}
#pragma mark - tableViewHelpers
//the number of rows in sectionX when it is open...
-(NSInteger )numberOfRowsInSection:(NSInteger )section{
return section + 1;
}
//opening/closing a section
-(void )setSection:(NSInteger )section toOpen:(BOOL )open{
if (open != sectionIsOpen[section]) {
//build an array of indexPath objects
NSMutableArray *indxPths = [NSMutableArray array];
for (NSInteger i = 0; i < [self numberOfRowsInSection:section]; i ++) {
[indxPths addObject: [NSIndexPath indexPathForRow:i inSection:section ]
];
}
[self.tableView beginUpdates];
if (open) {
[self.tableView insertRowsAtIndexPaths:indxPths withRowAnimation:UITableViewRowAnimationFade];
//nb there is a large ENUM of tableViewRowAnimation types to experiment with..
}else{
[self.tableView deleteRowsAtIndexPaths:indxPths withRowAnimation:UITableViewRowAnimationFade];
}
sectionIsOpen[section] = open;
[self.tableView endUpdates];
}
}
-(void )sectionOpenToggle:(id )sender{
[self setSection:[sender tag] toOpen: !sectionIsOpen[[sender tag]] ];
}
// open/close all sections.
-(void )setAllSectionsOpen:(BOOL )open{
for (NSInteger i = 0; i < [self numberOfSectionsInTableView:self.tableView]; i ++) {
[self setSection:i toOpen:open];
}
}
//these two for your convenience, hook up to navbar items etc..
-(IBAction)openAllSections:(id)sender{
[self setAllSectionsOpen:YES];
}
-(IBAction)closeAllSections:(id)sender{
[self setAllSectionsOpen:NO];
}
#end
I'm not a native english speaker, so if some of my explanations aren't clear enough, tell me, and I'll try to rephrase them.
Anyway, could be better ways to do it, but that was just at the top of my head,
The below code might look scary and complicated, but I personally think it is really
straight-forward,
I've just added a lot of comments, explaining each step, so the code actually not as
long/complicated/messy as it might appear at first glance.
From your example above, it seems to me that your data source is an NSArray which contains NSDictionary objects,
And that each NSDictionary contains one header (section), and only one content (row) for that section,
So the below example is set to handle just that- a table view, with multiple sections, and one row on each section,
Which its data source is NSArray which contains NSDictionary objects.
Since I don't know if your current data source is mutable or not, in my example I will first create an mutable copy of it, and will use it throughout the code.
Throughout the code I will assume self.tableView is your table view, and self.dataArray is the array of dictionaries you've posted above,
I also assume that you've already set the table view's delegate and dataSource to be self, either in code or in storyboard.
// Here we define the height of each header,
// I've arbitrarily chosen 50 points. You can change it as you like.
// The reason I've declare it like this, is that I'm using its
// height to also create a UIView for the header, so this way
// if you want to change the height, you need to only change it once.
#define kHeaderHeight 50
-(void)viewDidLoad {
...
...
// The method below will be called to create an mutable copies of the
// dictionaries in your data source, plus add them another object
// which will indicate in our code if the correspond header
// should be expanded or collapsed
[self createDataSource];
// The below line is not mandatory, but I personally like to add it
// So collapsed sections won't have the row's 'bounds' under them.
self.tableView.tableFooterView = [[UIView alloc] initWithFrame: CGRectZero];
...
...
}
-(void)createDataSource {
// Here we are basically going to create a temporary mutable array,
// then we are going to iterate through self.dataArray array,
// Make a mutable copy of every dictionary in it, Add a BOOL value
// it that indicates if the row is expanded or not, add the new mutable
// dictionary to the temporary array, and then make self.dataArray
// point to an immutable copy of the new array we've created
NSMutableArray *array = [[NSMutableArray alloc] init];
for(int i = 0; i < [self.dataArray count]; i++) {
NSMutableDictionary *dict = [self.dataArray[i] mutableCopy];
[dict setObject:#(NO) forKey:#"expanded"];
[array addObject:dict];
}
self.dataArray = [array copy];
}
// Now we will set the height of each header.
-(CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
return kHeaderHeight;
}
// Here we create a custom view for the header, so we can make its title clickable,
// That will expand/collapse each section
-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
// Here we are creating a view for the header, and use our defined header
// height to set its height appropriately.
UIView *header = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, kHeaderHeight)];
// Then create a button
// I've arbitrarily chosen a size of 100x20 and created a frame to be placed in the
// middle of the above header
UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(header.frame.size.width/2 - 50, header.frame.size.height/2 - 10, 100, 20)];
NSString *headerTitle = [self.dataArray[section] objectForKey:#"heading"];
[button setTitle:headerTitle forState:UIControlStateNormal];
// We set the button tag to correspond to its section for future use
button.tag = section;
// I've arbitrarily chose to set the button colour to gray colour
button.titleLabel.textColor = [UIColor grayColor];
// Then we need to actually add an action to the button
[button addTarget:self action:#selector(updateTableView:) forControlEvents:UIControlEventTouchUpInside];
// Then we need to add the button to the header view itself
[header addSubview:button];
return header;
}
// Here we are just setting the number of sections to correspond to the
// number of items we have in our data array
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return [self.dataArray count];
}
// Here we are finally using the BOOl value we've added to our dictionary at the
// beginning of our code. If the "expanded" BOOL value is YES, return 1 row,
// else, the section is collapsed, so return 0 rows
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
if([[self.dataArray[section] objectForKey:#"expanded"] boolValue]) {
return 1;
} else {
return 0;
}
}
// Here is just a simple method to create the cells that will use our dataArray
// as their source for their title
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *identifier = #"cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
if(!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier];
}
cell.textLabel.text = [self.dataArray[indexPath.row] objectForKey:#"content"];
return cell;
}
// This method being called when clicking on the table view's headers
// it uses the button tag we've set earlier, to determine which section we're trying
// to collape/expand, it retrieves the current "expanded" bool value, and then store
// the opposite value back in our dictionary (so if table was collapsed, meaning
// its "expanded" value is NO, after this will run, it will be "YES", which
// will be evaluated after our next line, which tells the table view to reload
// this specific section).
// NOTE that while our dataArray is immutable array, meaning we can't modify it,
// it points to an mutable dictionaries, so we have no problem modifying them.
-(void)updateTableView:(UIButton *)sender {
BOOL expanded = [[self.dataArray[sender.tag] objectForKey:#"expanded"] boolValue];
[self.dataArray[sender.tag] setObject:#(!expanded) forKey:#"expanded"];
[self.tableView reloadSections:[NSIndexSet indexSetWithIndex:sender.tag] withRowAnimation:UITableViewRowAnimationFade];
}
// Connect the below methods to your collapse/expand all buttons.
// What the below method actually does, is iterating thru all of the dictionaries
// in dataArray, changes their value to be corresponding to what we are trying to
// do (expand or collapse all) and then calling reloadSections:withRowAnimation:
// on our table view.
// You might wonder why I just don't call reloadData.
// Although it will do the job, I like the following more, because I personally
// feel it gives more 'smooth' update of the UI
-(void)expandAll:(UIButton *)sender {
for(int i = 0; i < [self.dataArray count]; i++) {
[self.dataArray[i] setObject:#(YES) forKey:#"expanded"];
}
[self.tableView reloadSections:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, self.dataArray.count)] withRowAnimation:UITableViewRowAnimationFade];
}
-(void)collapseAll:(UIButton *)sender {
for(int i = 0; i < [self.dataArray count]; i++) {
[self.dataArray[i] setObject:#(NO) forKey:#"expanded"];
}
[self.tableView reloadSections:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, self.dataArray.count)] withRowAnimation:UITableViewRowAnimationFade];
}
Good luck mate.
I have a tableViewCell in a TableView that gets big if you click on it and if you click it again it goes back to its original size.
What I'd like it to do is, display a datePicker when its big but every time I try to simply add a datePicker in my code it is at the bottom of the tableView and not inside the big cell.
This is my code for adding the datePicker when the cell gets big.
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
if (indexPath.row == 0) {
return 150.0;
}
else if ([self cellIsSelected:indexPath] && indexPath.row == 1 ){
[_dateLabel removeFromSuperview]; //just the label of the cell
// Add the picker
UIDatePicker *pickerView = [[UIDatePicker alloc] initWithFrame:CGRectMake(0, 0, 350, 200)];
pickerView.datePickerMode = UIDatePickerModeDate;
[_cell addSubview:pickerView];
return kCellHeight * 4.0;
}
else if (![self cellIsSelected:indexPath]) {
[_myPicker removeFromSuperview];
}
return kCellHeight;
}
How do I add a UIDatePicker to a TableViewCell?
Please take a look at this answer on SO, as it may help you further.
Just remember to set the delegates:
#interface YourTableViewViewController : UITableViewController <UIPickerViewDataSource, UIPickerViewDelegate>
And make sure you return values from these methods:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return <NUM_OF_SECTIONS>;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return <NUM_OF_ROWS_IN_SECTION>;
}
For the rest, it is self-explanatory there.
I added Tableview on xib file(you can see on image).tableview is loading well . But last cell is out of screen so when I Swipe Up last index is showing. When I get off my hand, last cell is not appear. I don't change any height of tableview . Why not fixed to my screen ?
I am using reveal menu like facebook in this project : https://github.com/mikefrederick/MFSideMenu
Also You can see problem on movie.
https://www.dropbox.com/s/usfwdhl5w9znkl6/IMG_0006.MOV
viewcontroller.h
#property(nonatomic,retain)IBOutlet UITableView * tableview;
viewcontroller.m
-(void)viewDidAppear:(BOOL)animated
{
self.tableview.backgroundColor=[UIColor colorWithRed:(28/255.0) green:(28/255.0) blue:(28/255.0) alpha:1];
[self.tableview setSeparatorColor:[UIColor blackColor]];
}
- (void)viewDidLoad
{
[super viewDidLoad];
if ([self respondsToSelector:#selector(edgesForExtendedLayout)])
self.edgesForExtendedLayout = UIRectEdgeNone;
}
#pragma mark -
#pragma mark - UITableViewDataSource
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 2;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (section==0)
{
return 5;
}
if (section==1)
{
return 3;
}
return 0;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
cell.textLabel.text =#"exampleCell";
NSLog(#"cell.contentView.bounds.size.width %1.0f",cell.contentView.bounds.size.width);
return cell;
}
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
if(section == 1)
return 40;
return 0;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
self.tableview.layer.cornerRadius = 10.0f;
tableView.layer.borderWidth = 2.0;
tableView.layer.borderColor = [UIColor redColor].CGColor;
return 60;
}
#pragma mark UITableViewDelegate
- (void)tableView: (UITableView*)tableView
willDisplayCell: (UITableViewCell*)cell
forRowAtIndexPath: (NSIndexPath*)indexPath
{
cell.backgroundColor =[UIColor colorWithRed:(41/255.0) green:(41/255.0) blue:(41/255.0) alpha:1];
cell.textLabel.backgroundColor = [UIColor clearColor];
cell.detailTextLabel.backgroundColor = [UIColor clearColor];
if([indexPath row] == ((NSIndexPath*)[[tableView indexPathsForVisibleRows] lastObject]).row){
//end of loading
//for example [activityIndicator stopAnimating];
}
}
- (UIView *) tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
UIView *headerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, tableView.bounds.size.width, 30)];
[headerView setBackgroundColor:[UIColor colorWithRed:(112/255.0) green:(112/255.0) blue:(112/255.0) alpha:1]];
UILabel *titleLabel = [ [UILabel alloc] initWithFrame:CGRectMake(20, 0, 300, 44)];
titleLabel.text = #"MÜŞTERİ ALANI";
titleLabel.textColor = [UIColor whiteColor];
titleLabel.backgroundColor = [UIColor clearColor];
[headerView addSubview:titleLabel];
return headerView;
}
In your video, this menu appears to be a slide out menu, presumably using some third party slide out menu controller library. So this view controller is contained within some container view from that. It is possible that the slide out menu controller isn't properly sizing your view controller to fit its container view.
One solution would be to check any example apps that come with the slide out controller you're using to see if they suffer from the bug and report this to the developer if it is the case. This would be good because other developers would benefit from the improvements. In fact it's possible the slide out controller you're using has fixed this bug with a newer version already that you don't have yet.
Another solution, assuming there's an example app that doesn't suffer from this, is to see how it is adding its slide out menu and see if you're failing to do something that they're doing.
Lastly, if there's no example app or you can't figure out why theirs is working differently, try adding the following to your view controller's viewDidAppear: method:
self.view.frame = self.view.superview.bounds;
This assumes that the container view they create is properly sized.
Your problem seems to be in your xib.
You have to set the size of your View to "Freeform" then add autosizing constraints on your view like you did on your tableView.
first you should select the CELL, not the TABLE VIEW. Next, go to the attribute inspector and click the separator, and you should select the custom inserts. Lastly you can adjust the separator line according to your wish. Hope this will help you and others. Thanks for the question too.
I have a table view of custom cells and some buttons in each cell.Clicking on any of the button inside the cell will reveal another custom view below that cell.Next click on the same button will collapse the view and need this same for all cells.I tried with insertrow method on the button click but in vain.How can i do this with using only the table view delegates.
This is what i tried:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *simpleTableIdentifier = #"CustomCell_For_Dashboard";
CustomCellFor_Dashboard *customCell = (CustomCellFor_Dashboard *)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (customCell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"CustomCellFor_Dashboard" owner:self options:nil];
customCell = [nib objectAtIndex:0];
}
[customCell.howyoulfeelBtn addTarget:self action:#selector(buttonclicked:) forControlEvents:UIControlEventTouchUpInside];
customCell.nameLabel.text = #"test";
customCell.imgView.image = [UIImage imageNamed:#"Default.png"];
// customCell.prepTimeLabel.text = [prepTime objectAtIndex:indexPath.row];
return customCell;
}
-(void)buttonclicked:(id)sender{
NSIndexPath *indexPath = [myTable indexPathForCell:sender];
[myTable beginUpdates];
NSIndexPath *insertPath = [NSIndexPath indexPathForRow:indexPath.row inSection:indexPath.section];
[myTable insertRowsAtIndexPaths:[NSArray arrayWithObject:insertPath] withRowAnimation:UITableViewRowAnimationTop];
}
can anyone help me?
I got the same task on one project with just one thing different: There were no buttons, just tapping on cell will expand or collapse it.
There are several things you should edit in your code. First, the button method code will look something like this:
- (void) collapseExpandButtonTap:(id) sender
{
UIButton* aButton = (UIButton*)sender; //It's actually a button
NSIndexPath* aPath = [self getIndexPathForCellWithButtonByMagic:aButton];
//expandedCells is a mutable set declared in your interface section or private class extensiont
if ([expandedCells containsObject:aPath])
{
[expandedCells removeObject:aPath];
}
else
{
[expandedCells addObject:aPath];
}
[myTableView beginEditing];
[myTableView endEditing]; //Yeah, that old trick to animate cell expand/collapse
}
Now the second thing is UITableViewDelegate method:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if ([expandedCells containsObject:indexPath])
{
return kExpandedCellHeight; //It's not necessary a constant, though
}
else
{
return kNormalCellHeigh; //Again not necessary a constant
}
}
Key thing here is to determine if your cell should be expanded/collapsed and return right height in delegate method.
Going off of what #eagle.dan.1349 said, this is how to do it on the clicking of the cell. In storyboard, you also need to set the table cell to clip subviews, otherwise the content that would be hidden will show.
.h
#property (strong, nonatomic) NSMutableArray *expandedCells;
.m
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if ([self.expandedCells containsObject:indexPath])
{
[self.expandedCells removeObject:indexPath];
}
else
{
[self.expandedCells addObject:indexPath];
}
[tableView beginUpdates];
[tableView endUpdates];
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
CGFloat kExpandedCellHeight = 150;
CGFloat kNormalCellHeigh = 50;
if ([self.expandedCells containsObject:indexPath])
{
return kExpandedCellHeight; //It's not necessary a constant, though
}
else
{
return kNormalCellHeigh; //Again not necessary a constant
}
}
Saw this post and just wanted to give my 2 cents as my solution to this is very similar to the chosen answer (the tapping of a whole area).
Many people architect this by using just cells alone, but I believe there is a way to build this that might align better with what people are trying to achieve:
There are headers and there are cells. Headers should be tappable, and then cells underneath the headers would show or hide. This can be achieved by adding a gesture recognizer to the header, and when tapped, you just remove all of the cells underneath that header (the section), and viceversa (add cells). Of course, you have to maintain state of which headers are "open" and which headers are "closed."
This is nice for a couple of reasons:
The job of headers and cells are separated which makes code cleaner.
This method flows nicely with how table views are built (headers and cells) and, therefore, there isn't much magic - the code is simply removing or adding cells, and should be compatible with later versions of iOS.
I made a very simple library to achieve this. As long as your table view is set up with UITableView section headers and cells, all you have to do is subclass the tableview and the header.
Link: https://github.com/fuzz-productions/FZAccordionTableView
I also had a same situation and my solution was to put a button on top of the Section Title with viewForHeaderInSection method.
noOfRows defines how many rows are there in each section and button.tag keeps which button of section is pressed.
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
UIButton *btnSection = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, tableView.frame.size.width, tableView.frame.size.height)];
btnSection.tag = section;
[btnSection setTitle:[sectionArray objectAtIndex:section] forState:UIControlStateNormal];
[btnSection addTarget:self action:#selector(sectionButtonTapped:) forControlEvents:UIControlEventTouchUpInside];
return btnSection;
}
- (void)sectionButtonTapped:(UIButton *)button {
sectionIndex = button.tag;
if (button.tag == 0) {
noOfRows = 3;
} else if (button.tag == 1) {
noOfRows = 1;
} else if (button.tag == 2) {
noOfRows = 2;
}
[self.tableView reloadData];
}
Hope this will help you..
I want to accomplish something like this :
see there's only one data but, background color continue until end.
I understand I can do inside tableview delegate of tableView:willDisplayCell:forRowAtIndexPath:. but then it doesn't go to empty cell, hence my empty cell always be white.
I used the following code to display cell alternative color even if cell is not initialized.I have done this work on scrollViewDidScroll as showing below:--
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
UIView *view=[[UIView alloc] initWithFrame:tblView.frame];
view.backgroundColor=[UIColor greenColor];
UIView *cellView;
int y=0;
int i=0;
for (UIView *view in tblView.subviews) {
if ([NSStringFromClass([view class]) isEqualToString:#"_UITableViewSeparatorView"]) {
cellView=[[UIView alloc] initWithFrame:CGRectMake(0, y, 320, 44)];
if (i%2==0) {
cellView.backgroundColor=[UIColor redColor];
}else{
cellView.backgroundColor=[UIColor greenColor];
}
[view addSubview:cellView];
i++;
}
}
tblView.backgroundView=view;
}
And got the correct result on scrolling table view. But the problem is it works when user scrolls the tableView atleast once a time.
If you will get success to fire event on tableView completes its reloading.Then it will be fine.
Here is output I got on scrolling tableView.
I also write this method to call didScrollMethod manually but doesn't seems to work perfectly.
[tblView.delegate scrollViewDidScroll:(UIScrollView*)tblView.superclass];
But calling method like code below absolutely works fine.
- (void)viewDidLoad
{
tblView=[[MyFirstView alloc] init];
tblView.delegate=self;
[tblView setFrame:self.view.frame];
[self.view addSubview:tblView];
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
-(void)viewDidAppear:(BOOL)animated{
[tblView.delegate scrollViewDidScroll:(UIScrollView*)tblView.superclass];
}
Means after loading tableView in viewDidLoad call didScroll in viewDidAppear works fine.
Insert below code if fluctuates first row while scrolling.
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
UIView *view=[[UIView alloc] init];
return view;
}
You have to set the backgroundColor to the contentView of a UITableViewCell.
Sample as below:
-(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"identifier"];
if (cell==nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"identifier"]autorelease];
cell.contentView.backgroundColor= [UIColor greenColor];
}
return cell;
}
To have alternate colors in your cells of tableView, you can do the following;
-(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"identifier"];
if (cell==nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"identifier"]autorelease];
}
if(indexPath.row % 2)
{
cell.contentView.backgroundColor= [UIColor greenColor];
}
else
{
cell.contentView.backgroundColor= [UIColor yellowColor];
}
return cell;
}
A table with plain style doesn't show rows below the last row so there is no way to produce the desired effect using table view cells. About your only option would be to create a view with the alternating pattern and make the view the table view's footer view.
This view would need to deal with being updated as the number of actual rows in the table changes to/from odd and even. And you need to make it tall enough so if the user scrolls the table up a bunch, the footer still reaches the bottom of the screen.
You can setup some placeholder cells in addition to your cell with 'Monthly meeting', something like:
return amount of rows as 1 + (rows to fill screen) in the tableView:numberOfRowsInSection:
In the tableView:cellForRowAtIndexPath: - check for index path of the cell, if its row = 0, then this is your action cell, otherwise, update cells background, do the same in the tableView:willDisplayCell:forRowAtIndexPath:. Make sure to remove selectionStyle for your placeholder cells.
Or, you can use 2 cells - first one - again, your 'Monthly meeting' cell, and second one - a cell with height enough to cover screen from first cell to the bottom with image of striped cells.
This is simple to do. Just have as many items in your data source array as you want to see rows, and have all but the first one be empty strings. In willDisplayCell:forRowAtIndexPath: apply a background color to all the odd numbered cells.
- (void)viewDidLoad {
[super viewDidLoad];
self.theData = #[#"Monthly Meeting",#"",#"",#"",#"",#"",#"",#"",#"",#""];
[self.tableView reloadData];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return self.theData.count;
}
-(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.row % 2 == 1) {
cell.backgroundColor = [UIColor colorWithRed:232/255.0 green:238/255.0 blue:222/255.0 alpha:1];
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
cell.textLabel.text = self.theData[indexPath.row];
return cell;
}
Set backgroundColor to the contentView of a UITableViewCell with the help of simple mathematics, Example:
-(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"identifier"];
if (cell==nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"identifier"]autorelease];
if (i%2==0) {
cell.contentView.backgroundColor= [UIColor greenColor];
}else{
cell.contentView.backgroundColor= [UIColor redColor];
}
}
return cell;
}