I am new to iOS development. I am using tableView with of dynamic height. The height of tableViewCell increases or decreases on the click for this I am using this code...
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if ([self.selectedPath isEqual:indexPath])
{
return 250;
}
else
{
return 44;
}
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
onSelectCount++;
self.selectedPath = indexPath;
[tableView reloadRowsAtIndexPaths:#[indexPath] withRowAnimation: UITableViewRowAnimationLeft];
self.selectedRowIndex = [NSNumber numberWithInteger:indexPath.row];
[self.tableView1 deselectRowAtIndexPath:indexPath animated:YES];
//First we check if a cell is already expanded.
//If it is we want to minimize make sure it is reloaded to minimize it back
if( onSelectCount==1 )
{
NSLog(#"num=%d",onSelectCount);
NSLog(#"First Condition");
[tableView beginUpdates];
NSIndexPath *previousPath = [NSIndexPath indexPathForRow:self.selectedRowIndex.integerValue inSection:0];
self.selectedRowIndex = [NSNumber numberWithInteger:indexPath.row];
self.selectedPath=indexPath;
[tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:previousPath] withRowAnimation:UITableViewRowAnimationFade];
[tableView endUpdates];
}
if(self.selectedPath.row!=indexPath.row)
{
[tableView beginUpdates];
[tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:selectedPath] withRowAnimation:UITableViewRowAnimationFade];
[tableView endUpdates];
selectedPath=indexPath;
onSelectCount=0;
[self tableView:tableView didSelectRowAtIndexPath:selectedPath];
}
if(self.selectedRowIndex.integerValue == indexPath.row && onSelectCount==2)
{
[tableView beginUpdates];
self.selectedRowIndex = [NSNumber numberWithInteger:-1];
[tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
onSelectCount=0;
[tableView endUpdates];
}
}
Now I want to add some label to show some information on the tableViewCell but when I click on the cell it resizes perfectly but label on the cell does not resize.Please tell me how can I resize the UILabels with the Cell height. Any help will be appreciated...
Use the method - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath to achieve this. It is also good to move the whole logic for changing the height for the cells from didSelectRow to cellForRowAtIndexPath.
To answer your question:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
CGRect sizeRect = cell.textLabel.frame;
sizeRect.size.height = cell.contentView.frame.size.height;
cell.textLabel.frame = sizeRect;
return cell;
}
where textLabel is the name of your label.
The basic idea is that you take the frame of the label, then set it's height to the height of cell's view and then set the new size to the label.
Related
I have a UITableView that is made up of a number of custom UITableViewCells.
When the table didSelectRowAtIndexPath method fires, if the indexPath.row is equal to 2, I want to update a UILabel within the cell at this row.
My thinking was to use something along the following lines;
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if(indexPath.row == 2){
myCustomCellView *cell = [self.essentialsTableView cellForRowAtIndexPath:indexPath];
cell.myUILabel.text = #"my text";
[tableView reloadData];
}
}
The problem here is that cellForRowAtIndexPath returns an object of type UITableViewCell, not myCustomCellView.
Can anyone advise how i might access and update properties of cells within the didSelectRowAtIndexPath method?
Define one Bool value say "secondRowIsClicked". Set it to No in your viewWillApper or viewDidAppear function.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if(indexPath.row == 2)
{
secondRowIsClicked = YES;
[tableView reloadData];
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// Your code
if (secondRowIsClicked == YES)
{
cell.myUILabel.text = #"my text";
}
}
try with bellow code..
myCustomCellView *cell = (myCustomCellView *) [self.essentialsTableView cellForRowAtIndexPath:indexPath];
you can reload UITableViewCell with its indexPath like bellow..
[self.tableView reloadRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationNone];
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
myCustomCellView *cell = [self.essentialsTableView cellForRowAtIndexPath:indexPath];
UILabel *yourLabel=[cell.contentViews.subviews viewWithTag:indexPath.row+1];
//do whatever you want with your label;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// Your code
cell.myUILabel.text = #"my text";
cell.myUILabel.tag=indexpath.row+1;
}
typecast UITableViewCell to your custom cell
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if(indexPath.row == 2){
myCustomCellView *cell = (myCustomCellView *)[self.essentialsTableView cellForRowAtIndexPath:indexPath];
cell.myUILabel.text = #"my text";
[tableView reloadData];
}
}
you need to upadte the datasoure and den call the reload the tableview
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if(indexPath.row == 2){
//update the array which is used as the data provider in cell for row at index path.
[tableView reloadData];
}
}
myCustomCellView is a subClass of UITableViewCell.
So just typcast the cell
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if(indexPath.row == 2){
myCustomCellView *cell = (myCustomCellView *)[self.essentialsTableView cellForRowAtIndexPath:indexPath];
cell.myUILabel.text = #"my text";
[tableView reloadData];
}
}
More info:
As per Apple coding guide lines do not user class name start with lower case letter
instead of myCustomCellView use MyCustomCellView
In my UITableView, i need to get the event of the user, so when the cell is selected(checked), i put btn_checked.png and when it's unchecked, i put the btn_unchecked.png.
I guess, what i try to do should be in the didSelectRowAtIndexPath method, so this is my code:
- (void)tableView:(UITableView *)tableView
didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSArray *listData =[self->tableContents objectForKey:
[self->sortedKeys objectAtIndex:[indexPath section]]];
UITableViewCell* theCell = [tableView cellForRowAtIndexPath:indexPath];
UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"btn_unchecked.png"]];
theCell.accessoryView = imageView;
}
My snippet code doesn't work, so the btw_unchecked.png isn't placed when the row is checked, also, i need to get the event of checked/unchecked to place the right image to the right event.
Thanx in advance.
As an example, this code snippet will toggle the cell's checkmark when the cell is tapped. The pattern is to force a selective reload from the table's datasource when the delegate method is invoked.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// Dequeue the cell... then:
static NSString *CellIdentifier = #"tvcOEList";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
cell.accessoryType = (cell.accessoryType == UITableViewCellAccessoryNone) ? UITableViewCellAccessoryCheckmark : UITableViewCellAccessoryNone;
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:YES];
}
You can use following code.
[cell.contentView addSubview:imageView];
i hope this will help you..
My UITableViewCell will not delete when I call the method. I can get it to print out the cell it is supposed to delete, but it will not remove itself, and it won't remove itself from the array.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *thisCell = [tableView cellForRowAtIndexPath:indexPath];
[customData removeObjectIdenticalTo:thisCell.textLabel.text];
NSLog(#"%#", customData);
[thisCell removeFromSuperview];
[tabler reloadData];
}
you need this: [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
I'm trying to add checkmarks to items when the user select rows in a table view. However, the view is not refreshed and the checkmarks do no show up:
- (void)tableView:(UITableView *)tv didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell* oldCell = [self tableView:tv cellForRowAtIndexPath:[NSIndexPath indexPathForRow:selectedIndex inSection:0]];
oldCell.accessoryType = UITableViewCellAccessoryNone;
if (indexPath.section == 0) {
selectedIndex = indexPath.row;
}
UITableViewCell* newCell = [self tableView:tv cellForRowAtIndexPath:indexPath];
newCell.accessoryType = UITableViewCellAccessoryCheckmark;
[tv deselectRowAtIndexPath:indexPath animated:NO];
}
What could be a reason for that?
Call cellForRowAtIndexPath directly on the tv object instead of through self to make sure you get a proper cell reference back:
- (void)tableView:(UITableView *)tv didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *oldCell = [tv cellForRowAtIndexPath:[NSIndexPath indexPathForRow:selectedIndex inSection:0]];
oldCell.accessoryType = UITableViewCellAccessoryNone;
if (indexPath.section == 0) {
selectedIndex = indexPath.row;
}
UITableViewCell *newCell = [tv cellForRowAtIndexPath:indexPath];
newCell.accessoryType = UITableViewCellAccessoryCheckmark;
[tv deselectRowAtIndexPath:indexPath animated:NO];
}
Also make sure that in cellForRowAtIndexPath, you have this logic:
...
if (indexPath.row == selectedIndex)
cell.accessoryType = UITableViewCellAccessoryCheckmark;
else
cell.accessoryType = UITableViewCellAccessoryNone;
...
return cell;
otherwise, a checkmark will remain on a cell after it scrolls off the screen and comes back on screen even after you've selected another cell.
I'm using a UITableView to allow selection of one (of many) items. Similar to the UI when selecting a ringtone, I want the selected item to be checked, and the others not. I would like to have the cell selected when touched, then animated back to the normal color (again, like the ringtone selection UI).
A UIViewController subclass is my table's delegate and datasource (not UITableViewController, because I also have a toolbar in there).
I'm setting the accessoryType of the cells in cellForRowAtIndexPath:, and updating my model when cells are selected in didSelectRowAtIndexPath:. The only way I can think of to set the selected cell to checkmark (and clear the previous one) is to call [tableView reloadData] in didSelectRowAtIndexPath:. However, when I do this, the animating of the cell deselection is weird (a white box appears where the cell's label should be). If I don't call reloadData, of course, the accessoryType won't change, so the checkmarks won't appear.
I suppose I could turn the animation off, but that seems lame. I also toyed with getting and altering the cells in didSelectRowAtIndexPath:, but that's a big pain.
Any ideas? Abbreviated code follows...
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell* aCell = [tableView dequeueReusableCellWithIdentifier:kImageCell];
if( aCell == nil ) {
aCell = [[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:kImageCell];
}
aCell.text = [imageNames objectAtIndex:[indexPath row]];
if( [indexPath row] == selectedImage ) {
aCell.accessoryType = UITableViewCellAccessoryCheckmark;
} else {
aCell.accessoryType = UITableViewCellAccessoryNone;
}
return aCell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView deselectRowAtIndexPath:indexPath animated:YES];
selectedImage = [indexPath row]
[tableView reloadData];
}
I solved it like hatfinch suggested in his edit. My code sample make sure there's only one row checked but I'm sure you can tweak it if thats not what you need.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
int newRow = [indexPath row];
int oldRow = [lastIndexPath row];
if (newRow != oldRow)
{
UITableViewCell *newCell = [tableView cellForRowAtIndexPath:
indexPath];
newCell.accessoryType = UITableViewCellAccessoryCheckmark;
UITableViewCell *oldCell = [tableView cellForRowAtIndexPath:
lastIndexPath];
oldCell.accessoryType = UITableViewCellAccessoryNone;
lastIndexPath = indexPath;
}
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
I had this exact same problem and never solved it.
In the end it was moot for me because I had to listen for changes in the model (the selection could change outwith the user's control if a connection was lost) so I just changed the model and let the notification reload the data, but it didn't look too pretty (it was like a non-animated deselection, but one run loop iteration late!)
I suspect the only way to do it is, as you suggest, keeping a cache of references to the cells themselves. This shouldn't be too messy if you write a UITableViewCell subclass to encapsulate the logic, overriding -prepareForReuse.
Still, not pretty, and if the ringtone guys at Apple had to do it this way, they ought to have pressed the UITableView team harder to fix it!
EDIT:
Well, what do you know?! This is really easy after all. -[UITableView cellForRowAtIndexPath] will give you the actual cells (or nil if they're offscreen) and you can just change the accessoryType.
I have a cleaner way of doing it.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
if (cell.accessoryType == UITableViewCellAccessoryNone) {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
} else {
cell.accessoryType = UITableViewCellAccessoryNone;
}
}
I'm using this simple and nice working mechanism with reloadRowsAtIndexPaths.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSArray *rowsArray = [NSArray arrayWithObjects:indexPath, selectedIndexPath, nil];
self.selectedIndexPath = indexPath;
[tableView reloadRowsAtIndexPaths:rowsArray withRowAnimation:UITableViewRowAnimationNone];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
.... skipped usual code .....
if ([selectedIndexPath compare:indexPath] == NSOrderedSame) {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
} else {
cell.accessoryType = UITableViewCellAccessoryNone;
}
return cell;
}
This will work as desired...
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
int newRow = [indexPath row];
int oldRow = [lastIndexPath row];
if (newRow == oldRow){
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
if (cell.accessoryType == UITableViewCellAccessoryNone) {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
} else {
cell.accessoryType = UITableViewCellAccessoryNone;
}
lastIndexPath = indexPath;
}
if (newRow != oldRow)
{
UITableViewCell *newCell = [tableView cellForRowAtIndexPath:indexPath];
newCell.accessoryType = UITableViewCellAccessoryCheckmark;
UITableViewCell *oldCell = [tableView cellForRowAtIndexPath:lastIndexPath];
oldCell.accessoryType = UITableViewCellAccessoryNone;
lastIndexPath = indexPath;
}
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *oldCell = [tableView cellForRowAtIndexPath:index];
oldCell.accessoryType = UITableViewCellAccessoryNone;
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
cell.accessoryType = UITableViewCellAccessoryCheckmark;
index = indexPath;
}