Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 9 years ago.
Improve this question
Before
After
basically my point is I have customTableViewCell which has button on the right most (same as image1 "show version history"). When I clicked that I want to add a dynamic number of subviewCell which is under customTableViewCells.
my question is, how is this being implemented? is there any library that you can refer on this?
I hope that You haven't search for it :
Let's take a look on these links :
UITableViewCell expand on click
gitHub
Expand / Collapse UITableViewCell with different cell and data source
Expand collapse UITableViewCell
GitHub
Accordion table cell - How to dynamically expand/contract uitableviewcell?
Have a look on these table view implementations
https://www.cocoacontrols.com/controls/jkexpandtableview
https://www.cocoacontrols.com/controls/sdnestedtable
https://www.cocoacontrols.com/controls/uiexpandabletableview
https://www.cocoacontrols.com/controls/ocborghettiview
That's very easy.
You want to track if the section is expanded. Use a instance variable (or property) for this
if it is not expanded you return 1 in tableView:numberOfRowsInSection: for the expandable section
if it is expanded you return 1 + the number of expanded cells in t:numberOfRowsInSection:
in tableView:didSelectRowAtIndexPath: you toggle the expansion state when the first cell is tapped and insert or delete the expanded rows.
e.g.:
#interface MBMasterViewController () {
BOOL firstSectionExpanded;
}
#end
#implementation MBMasterViewController
#pragma mark - Table View
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 3;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
NSInteger count = 1;
if (section == 0 && firstSectionExpanded) { count = 3; }
return count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
if (indexPath.row == 0) {
cell.textLabel.text = [NSString stringWithFormat:#"Section %ld", (long)indexPath.section];
}
else {
cell.textLabel.text = [NSString stringWithFormat:#"Sub Cell %ld", (long)indexPath.row];
}
return cell;
}
- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.row != 0) {
// don't select sub cells
return nil;
}
return indexPath;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSArray *cells = #[ [NSIndexPath indexPathForRow:1 inSection:indexPath.section],
[NSIndexPath indexPathForRow:2 inSection:indexPath.section]];
NSArray *cellsToDelete;
NSArray *cellsToInsert;
if (indexPath.section == 0) {
if (firstSectionExpanded) {
cellsToDelete = cells;
}
else {
cellsToInsert = cells;
}
firstSectionExpanded = !firstSectionExpanded;
}
if (cellsToDelete) {
[tableView deleteRowsAtIndexPaths:cellsToDelete withRowAnimation:UITableViewRowAnimationAutomatic];
}
if (cellsToInsert) {
[tableView insertRowsAtIndexPaths:cellsToInsert withRowAnimation:UITableViewRowAnimationAutomatic];
}
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
I have a UITableView that contain 2 different custom cell. One is ExerciseTime and one is RestTime. I want my RestTime cell to be inserted between every 2 ExerciseTime cell :
Here is my code:
-Height for row
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
// RestTime
if (indexPath.row % 2 == 1) {
return 40.0f;
}
// ExerciseTime
else {
return 65.0f;
}
}
-Number of row in section (i couldnt find a way to set number of row for both RestTime and ExerciseTime)
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return (self.preset.blocks.count * 2) - 1;
}
-Cell for row
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if(indexPath.row % 2 == 1) {
RestTimeTableViewCell *restTimeCell = (RestTimeTableViewCell *)[tableView dequeueReusableCellWithIdentifier:RestTimeTableViewCellIdentifier forIndexPath:indexPath];
RestTime *restTime = (RestTime *)[self.restTimeArray objectAtIndex:indexPath.row];
//CustomCell
return restTimeCell;
}else{
ExerciseTimeTableViewCell *exerciseTimecell = (ExerciseTimeTableViewCell *)[tableView dequeueReusableCellWithIdentifier:ExerciseTimeTableViewCellIdentifier forIndexPath:indexPath];
ExerciseTime *exerciseTime = [self.exerciseTimeArray objectAtIndex:indexPath.row];
//CustomCell
return exerciseTimecell;
}
return nil;
}
How can I create a tableView with 2 custom cell like this?
First return count as total of two array in numberOfRowsInSection and then in cellForRowAtIndexPath try some thing like this.
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
// RestTime
if (indexPath.row % 3 == 0) {
return 40.0f;
}
// ExerciseTime
else {
return 65.0f;
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell"];
if (indexPath.row % 3 == 0) {
RestTimeTableViewCell *restTimeCell = (RestTimeTableViewCell *)[tableView dequeueReusableCellWithIdentifier:RestTimeTableViewCellIdentifier forIndexPath:indexPath];
//Access you object from array like this
NSInteger index = (NSInteger) (indexPath.row / 3);
RestTime *restTime = (RestTime *)[self.restTimeArray objectAtIndex:index];
}
else {
ExerciseTimeTableViewCell *exerciseTimecell = (ExerciseTimeTableViewCell *)[tableView dequeueReusableCellWithIdentifier:ExerciseTimeTableViewCellIdentifier forIndexPath:indexPath];
//Access you object from array like this
NSInteger index = (indexPath.row - (NSInteger) (indexPath.row / 3));
ExerciseTime *exerciseTime = [self.exerciseTimeArray objectAtIndex:(index - 1)];
}
return cell;
}
Output: I have try this by setting background color as Red color for RestTimeTableViewCell and Green color for ExerciseTimeTableViewCell.
if you have n exerciseTime, you will be able to insert n-1 restTimes. So
Try this...
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.exerciseTime.count + (self.restTime.count >= self.exerciseTime.count) ? self.exerciseTime.count-1 : self.restTime.count;
}
Now, add exerciseTime in even position, and add restTime in odd position until current index exists in both of those lists. if current index exceeds restTime, then continue adding exerciseTime. Let me know if that works.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
I'd like to be able to select one row or more, and with an IBAction do something.
Let's say I have four rows, A, B, C and D. If I select A and B, and press the button connected to that IBAction, something happens.
How do I go about this?
Code:
#implementation ViewController {
NSArray *names;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [names count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *tableIdentifier = #"tableCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:tableIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:tableIdentifier];
}
cell.textLabel.text = [names objectAtIndex:indexPath.row];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if ((indexPath.row == 0) && (indexPath.row == 2)) {
NSLog(#"John and James selected.");
}
}
- (void)viewDidLoad {
[super viewDidLoad];
// Initialize table data
names = [NSArray arrayWithObjects:#"John", #"Michael", #"Hannah", #"James", nil];
}
Thanks!
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *selectedCell = [tableView cellForRowAtIndexPath:indexPath];
if ([selectedCell accessoryType] == UITableViewCellAccessoryNone) {
[selectedCell setAccessoryType:UITableViewCellAccessoryCheckmark];
[selectedIndexes addObject:[NSNumber numberWithInt:indexPath.row]];
} else {
[selectedCell setAccessoryType:UITableViewCellAccessoryNone];
[selectedIndexes removeObject:[NSNumber numberWithInt:indexPath.row]];
}
[tableView deselectRowAtIndexPath:indexPath animated:NO];
}
This code will show tick mark on your selected row.
You also have to use an array that maps the checked cells and in cellForRowAtIndexPath you have to verify if the accessoryType should be checked or not.
Then on your button action you can do your code with selected rows.
Hope this helps!
I want UITableView always has the text "No more items" in the last cell, I want this row appears regardless of number of items, include 0 items. How could I do?
You can get the total row of a section by using numberOfRowsInSection: method.
NSInteger total = [self.tableView numberOfRowsInSection:indexPath.section];
// Check if last cell or no cell.
if(indexPath.row == totalRow -1 || indexPath.row == 0)
{
// Do your operation here
}
You can perform this in your cellForRowAtIndexPath or willDisplayCell methods. Hope it helps.
Just add the row regardless of your other items:
- (void)buildMenu {
[_menuItems removeAllObjects];
// ... add your items or not if you have 0
YourCellItem *lastItem = [[YourCellItem alloc] initWithTitle:#"No more items"];
[_menuItems addObject:lastItem];
[self.tableView reloadData];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return _menuItems.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"yourCellIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
YourTableViewCell *basicCell = (YourTableViewCell *)cell;
YourCellItem *item = [_menuItems objectAtIndex:indexPath.row];
basicCell.itemTitle.text = item.title;
return cell;
}
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
i want to load datas from NSMutableArray to my TableView Sections
in my app i download datas from JSON database and sections Count and cells count are in that jSON file so the variables are not stable!
i want to load a NSMutableArray ObjectAtIndex in to cell (in the section) (i should to check if the Object should be in section 1 or in section 2 !)
Here is part of my code :
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"ProjectCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
for (int i = 0; i<[ProjectsToLoad count]; i++) {
Project *loader = [ProjectsToLoad objectAtIndex:i];
if ([loader group_id] == ([indexPath section]+1))
{
[cell.textLabel setText:[loader title]];
NSLog(#"LOADED CELL IS : %# , %i" , [loader title] , [indexPath section]);
}
}
return cell;
}
UPDATE : how can i return an array of cells Instead of returning a cell?
I am not sure what do you want to achieve. You cannot fill "datas" in UITableView. UITableViewController to fill UITableView uses special functions defined as UITableViewDataSource. If you want to have all data from your ProjectToLoad in one section you should:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [ProjectsToLoad count];
}
And then your cellAtRow will looks like:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"ProjectCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
Project *loader = [ProjectsToLoad objectAtIndex:indexPath.row];
[cell.textLabel setText:[loader title]];;
return cell;
}
If source is changing, you should refresh data using one of these function:
[self.tableView reloadData];
[self.tableView reloadRowsAtIndexPaths: withRowAnimation:];
[self.tableView reloadSections:withRowAnimation:];
I have a UITableView with one section. All of the cells in that one section have cells that are derived from a subclass of UITableViewCell called PLContactCell.
What I'd like to do is, for the very last row of the table only, not use a PLContactCell. I just want to use a normal UITableViewCell that I can format however I would like. I'd also like to be able to have this cell NOT respond to being tapped.
My initial cellForRowAtIndexPath method is:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
PLContactCell *cell = [tableView dequeueReusableCellWithIdentifier:[PLContactCell reuseIdentifier]];
if (!cell) {
cell = [PLContactCell reusableCell];
cell.delegate = self;
}
id modelObject = [[sections objectAtIndex:indexPath.section] objectAtIndex:indexPath.row];
if ([modelObject isKindOfClass:[NSString class]]) {
[cell configureWithString:modelObject];
} else {
[cell configureWithUser:modelObject];
}
return cell;
}
EDIT
So I tried created a UITableView cell in the XIB file and added the reuse identifier of "newCell" to it. Then I added this code:
if (indexPath.row == [[sections objectAtIndex:indexPath.section] count] - 1) {
NSString *CellIdentifier = #"newCell";
noFormatCell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
}
This doesn't do anything. My question is, how do I access the last row of the section and how do I make it so that that cell it is not a PLContactCell but a UITableView Cell.
If it's always at the end, you might consider using the footer view of the UITableView. You can then keep some extra logic out of your UITableViewDataSource.
If it HAS to be as a cell, you'd have to add an extra row count on your last section, then do an if statement check to watch out for it in your -tableView:cellForRowAtIndexPath: implementation. I would strongly urge you try the footer approach, as it's cleaner and way easier to figure out what you were doing a few months/years from now.
Here's some code. Note you'd need to make another section if you are using grouped style in the UITableView.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (section == sections.count - 1) //Looking for last section
{
return [sections objectAtIndex:section].count + 1; //Add one to the last section
}
return [sections objectAtIndex:section].count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSInteger row = indexPath.row;
if ((sections.count == indexPath.section) && [sections objectAtIndex:indexPath.section].count == indexPath.row)
{
//Here you would create and return your UITableViewCell
}
PLContactCell *cell = [tableView dequeueReusableCellWithIdentifier:[PLContactCell reuseIdentifier]];
if (!cell) {
cell = [PLContactCell reusableCell];
cell.delegate = self;
}
id modelObject = [[sections objectAtIndex:indexPath.section] objectAtIndex:indexPath.row];
if ([modelObject isKindOfClass:[NSString class]]) {
[cell configureWithString:modelObject];
} else {
[cell configureWithUser:modelObject];
}
return cell;
}