I am calculating height of Cell programatically in heightForRowAtIndexPath-
My complete method is:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
id cell = [self.tableView dequeueReusableCellWithIdentifier:kCellID];
if([cell isKindOfClass:[Custom class]])
{
return 100;
}
else
{
return 20;
}
}
My app takes 3-5 sec to Show the ViewController. Although cellForRowAtIndexPath is called and I can show the logs in Console.
But My ViewController not loaded.
When just return the height using this code app works fine:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
return 100;
}
I don't know that is the issue with this line:
id cell = [self.tableView dequeueReusableCellWithIdentifier:kCellID];
What I am missing in this issue?
You have some logic in the cellForRowAtIndexPath: method that determines what type of cell that row should be. Add that logic into the heightForRowAtIndexPath: method to determine the what the height of each row should be.
Your this line is wrong
id cell = [self.tableView dequeueReusableCellWithIdentifier:kCellID];
it will force your cell to reuse.
Use
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
id cell=[tableView cellForRowAtIndexPath:indexPath];
if([cell isKindOfClass:[CustomCellClass class]])
{
return 100;
}
else
{
return 20;
}
}
Related
I'm trying to create a dynamic UITableView where a cell can expand/collapse as the user selects the cell.
- (void)setUpCell:(DynamicTableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath {
cell.label.text = [self.dataSource objectAtIndex:indexPath.row];
cell.secondLabel.text = [self.dataSource objectAtIndex:self.dataSource.count - indexPath.row - 1];
if ([self.isVisible[indexPath.row] isEqual:#NO]) {
cell.secondLabel.hidden = YES;
} else {
cell.secondLabel.hidden = NO;
}
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return self.dataSource.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
DynamicTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
[self setUpCell:cell atIndexPath:indexPath];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
DynamicTableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
if ([self.isVisible[indexPath.row] isEqual: #YES]) {
self.isVisible[indexPath.row] = #NO;
cell.secondLabel.hidden = YES;
} else {
self.isVisible[indexPath.row] = #YES;
cell.secondLabel.hidden = NO;
}
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
static DynamicTableViewCell *cell = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
cell = [self.tableView dequeueReusableCellWithIdentifier:CellIdentifier];
});
[self setUpCell:cell atIndexPath:indexPath];
return [self calculateHeightForConfiguredSizingCell:cell];
}
- (CGFloat)calculateHeightForConfiguredSizingCell:(DynamicTableViewCell *)sizingCell {
[sizingCell layoutIfNeeded];
CGSize size = [sizingCell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize];
return size.height;
}
I forked this project and have the test code here.
Once the cell has been sized it does not change when selecting the cell, only hides/shows the content of the cell. I've tried replacing the explicit size calculation with UITableViewAutomaticDimension. Also tried reloading the cell. Seems once the cell size has been calculated, it does not change.
Any suggestions as to what to try would be greatly appreciated!
In iOS development a view never collapses if you set the hidden property to true.
Instead you should use autolayout. Assuming your view has two labels vertically stacked on top of each other, pin the first label to the cells contentView's top, give it a height constraint, pin the second label's top to the first labels bottom, pin the second labels bottom to the cell's contentView bottom. Set the height of the second label, and save this constraint in a variable, lets called it secondLabelHeightConstraint, now you can collapse and expand the cell by setting the value of secondLabelHeightConstraint to 0 or what ever value you would like.
Starting my quest into ios development but I have a problem, below.
The plan:
The result:
You need to set height of your custom cell using tableview delegate method
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.row == 0) {
return 150.0;
}else if (indexPath.row == 1){
return 300.0;
}
return 0.0;
}
as well as u need to set your custom cell cliptobound property to yes in datasource method
- (CGFloat)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
customcell *cell = (customcell *)[tableView dequeResusableCellWithIdentifier:#"newcell" forIndexPath:indexPath];
cell.cliptobound = YES;
return cell;
}
Your tableview needs to know the height of your custom cell, use the following tableview delegate method:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.row == 0) {
return 100.0;
}
return 200.0;
}
Your cells are getting reused without the content being reset in cellForRowAtIndexPath. In that method you need to blank out the cell content before putting more content in it.
How do you hide a static cell?
I would like to hide and static cell if an image does not exist.
I tried:
imageCell.hidden = YES; //did not work
I have seen answers suggesting to change datasource or use:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 0;// will hide all cell
}
But I couldnt find a way to do this with a specific view cell.
what I want to achieve:
if(image==nil){
//hide imageCell
}
Now here is the catch , the image is downloaded asynchronously, so deleguate methods might be called before the attempted downlaod.
Do the following :
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.row == 2 && !myImageIsLoaded)
return 0; // Will hide just the third row of your table if myImageIsLoaded is false
return 44;
}
And you can use the following to animate all whenever you want (e.g. each time an image as loaded) :
[myTable beginUpdate];
[myTable endUpdate];
If your cells are static so it should work. Otherwise you could encounter some problems.
If you want literally hide the cell that image does not exist, you can try this:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
return [cell imageView] ? 44.0f : 0.0f;
}
A very simple question...
can we change the height of only current row(the row which is clicked) in UItableView?
Note: I dont want any affect on size of remaining rows.
Yes you can. You need a variable that keeps the last selected row. For ex.:
#property (nonatomic, assign) NSInteger selectedRow;
...
Then implement the method
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
if(indexPath.row == self.selectedRow) {
return 100.;
}
return 44.;
}
and then, update the method:
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView deselectRowAtIndexPath:indexPath animated:YES];
if(self.selectedRow == indexPath.row)
self.selectedRow = -1;
else
self.selectedRow = indexPath.row;
//The magic that will call height for row and animate the change in the height
[tableView beginUpdates];
[tableView endUpdates];
}
NOTE: Initialise your self.selectedRow with -1 value in the beginning as the default is 0.
You can use heightForRowAtIndexPath for setting height for a row
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
You can place a check for NSIndexPath and return height for that particular indexpath
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
if(indexPath.row == rowtochangeheight) {
return 60;
}
else
{
return 44;
}
}
Yes you can do, But you need to save indexpath of selected row and you must intialize selectedRow variable by negative value.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
selectedRow = indexpath.row;
[tblView reloadData];
}
- (float)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.row == selectedRow)
return 150.0f;
return 30;
}
This should be easy, but I'm having trouble.
I have a static UITableView with a cell that I would like to remove programmatically if it's not needed.
I have a IBOutlet for it
IBOutlet UITableViewCell * cell15;
And I can remove it by calling
cell15.hidden = true;
This hides it, but leaves a blank space where the cell used to be and I can't get rid of it.
Perhaps a hack would be to change the height of it to 0?
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:indexPath
{
//what would I put here?
}
Thanks so much!
You can't really deal with this in the datasource since with static tables you don't even implement the datasource methods. The height is the way to go.
Try this:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
if (cell == cell15 && cell15ShouldBeHidden) //BOOL saying cell should be hidden
return 0.0;
else
return [super tableView:tableView heightForRowAtIndexPath:indexPath];
}
Update
It appears that, under autolayout, this may not be the best solution. There is an alternative answer here which may help.
You can use tableView:willDisplayCell and tableView:heightForRowAtIndexPath with the cell identifier to show/hide static tableview cells, but yo must implement heightForRowAtIndexPath referring to super, not to self. These two methods work fine for me:
(void) tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
if ([cell.reuseIdentifier.description isEqualToString:#"cellCelda1"]) {
[cell setHidden:YES];
}
}
and
(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [super tableView:tableView cellForRowAtIndexPath:indexPath];
if ([cell.reuseIdentifier.description isEqualToString:#"cellCelda1"]) {
return 0;
}
return cell.frame.size.height;
}
Depending on how your table is supposed to work, in your data source you can implement tableView:numberOfRowsInSection: to return 0 rows for the section based on your necessary logic.
Updated for your comment:
The section parameter will be populated by iOS when your implementation is called so all you need is a switch to handle the section that has the row you ant removed/hidden. Example below:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
switch(section) {
case 0: // first section of your table, change for your situation
return 0;
default:
return 0;
}
}
It for only constant cell
-(void)tableViewSearchPeopleCellHide:(BOOL)hide{
searchCellShouldBeHidden=hide;
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:1 inSection:0]];
[self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:1 inSection:0] atScrollPosition:UITableViewScrollPositionTop animated:YES];
cell.hidden=hide;
self.searchPeople.hidden=hide;//UILabel
[self.tableView reloadData];
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
// UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
if (searchCellShouldBeHidden) //BOOL saying cell should be hidden
return 0.0;
else
return [super tableView:tableView heightForRowAtIndexPath:indexPath];
}
The first thing you can do is tag the cell from storyboard which you want to hide.
Put some standard number which you can identify.
Add this code.
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [super tableView:tableView cellForRowAtIndexPath:indexPath];
if (cell.tag==10) { //I have put 10 for some static cell.
cell.hidden=YES;
return 0;
}
cell.hidden = NO;
return [super tableView:tableView heightForRowAtIndexPath:indexPath];
}
Set the cell you want to hide to hidden somewhere in your code. Add this code: (If your cell has different row height, then you need to override more functions)
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
int rowCount=0;
for ( int row=0; row<[super tableView:tableView numberOfRowsInSection:section]; ++row){
NSIndexPath* path=[NSIndexPath indexPathForRow:row inSection:section];
UITableViewCell* cell=[super tableView:tableView cellForRowAtIndexPath:path];
if (!cell.hidden){
++rowCount;
}
}
return rowCount;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
int realRow=-1;
for ( int row=0; row<[super tableView:tableView numberOfRowsInSection:indexPath.section]; ++row){
NSIndexPath* path=[NSIndexPath indexPathForRow:row inSection:indexPath.section];
UITableViewCell* cell=[super tableView:tableView cellForRowAtIndexPath:path];
if (!cell.hidden){
++realRow;
}
if (realRow==indexPath.row)
return cell;
}
return nil;
}
Use index path to identify the cell in tableview height delegate and return 0
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if someCondition {
if indexPath.row == 1 || indexPath.row == 2 || indexPath.row == 3 {
return 0
}
}else{
if indexPath.row == 4 {
return 0
}
}
return super.tableView(tableView, heightForRowAt: indexPath)
}