uitableview cell highlight - objective-c

I have a table view in which each cell contains a button. I dont use the didSelectRowAtIndexPath delegate but my custom method for the button action. I want that on clicking the button inside each cell, that cell should be highlighted or change colour and return to its normal state(colour) when the button in some other cell is clicked(making this cell highlighted).My button action method is:
- (void)SelectButtonTapped:(UIButton *)button
{
self.tabBarController.tabBar.userInteractionEnabled = YES;
AppDelegate *proDel = [[UIApplication sharedApplication]delegate];
UITableViewCell *cell = (UITableViewCell *)button.superview.superview;
//MyCustomCell *cell = (MyCustomCell *)button.superview.superview;
NSIndexPath *indexPath = [homeTable indexPathForCell:cell];
//cell.backgroundColor = [UIColor lightGrayColor];
//[homeTable setNeedsDisplayInRect:[homeTable rectForRowAtIndexPath:indexPath]];
DetailViewController *objDetail=[[DetailViewController alloc] init];
Home *tempSearchObj=(Home *)[profileArray objectAtIndex:indexPath.row];
objDetail.firstName=tempSearchObj.userName;
objDetail.userImageUrl=tempSearchObj.imageUrl;
objDetail.passedProfileID = tempSearchObj.profileID;
plsSelectLabel.text = [NSString stringWithFormat:#"%#",objDetail.firstName];
proDel.globalName = plsSelectLabel.text;
proDel.globalProfileId = objDetail.passedProfileID;
}
But this doesn't seem to work. Any help would be appreciated!!

Set the cell selection style in cellForRowAtIndexPath as :
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
[cell setSelectionStyle:UITableViewCellSelectionStyleBlue];
}
And :
yourButton.tag = indexPath.row;
Add the following line in your method to highlight the cell :
UIButton *clickButton = (UIButton *)sender;
int addButtonIndex = clickButton.tag;
NSIndexPath *indexPathHighlight = [NSIndexPath indexPathForRow:addButtonIndex inSection:0];
UITableViewCell *newCell = [yourTable cellForRowAtIndexPath:indexPathHighlight];
[newCell setSelected:YES animated:YES];
Unselect previous cell :
NSIndexPath *previousIndexPathHighlighted = [NSIndexPath indexPathForRow:previousTag inSection:0];
UITableViewCell *previousCell = [yourTable cellForRowAtIndexPath:previousIndexPathHighlighted];
[previousCell setSelected:NO animated:YES];
previousTag = clickButton.tag;

The proper way to go about this is that on your cellForRowAtIndex: method you have a way of knowing if your cell needs to look highlighted or not. Then, after clicking on a button and configuring whatever you need to do, you should simply do
NSArray *indexes = [NSArray arrayWithObject:[NSIndexPath indexPathForRow:0 inSection:1]];
[self.tableView reloadRowsAtIndexPaths:indexes withRowAnimation:UITableViewRowAnimationNone];
The other way to go about this, is to access the cell and change it directly. But not with button.superview.superview, but rather
UITableViewCell *cell = [self.tableView cellForRowAtIndex:[NSIndexPath indexPathForRow:0 inSection:1]];

I think the best way to do it is to make a
NSInteger selectedCellIndex;
Set the tags of your buttons in the cellForRowAtIndex method
button.tag = indexPath.row
Set the selectedCellIndex when you click the button and reload the table
selectedCellIndex = button.tag;
[self.tableView reloadData];
Then in the cellForRowAtIndex method check if the index is the same as the selectedCellIndex and add a different color to the cell.
if( indexPath.row == selectedCellIndex ){
//set different colors
}
Remember to do this outside the if( cell == nil ) check, otherwise it wouldn't work.

Related

Set text to textfield of table Cell in objective c outside UITableView delegate methods

I am new to objective C,and have made a demo app.
In this app I am having a UITableView which contains textField.When I taps a button(sign in using Facebook), after successfully login from Facebook it come back to my TableView screen,at that time i want to set values came from Facebook response to UITableView's textFields, but I am unable to do it as TableView's delegate method is calling only once.
Can anybody please help me to set text to tableView's textField outside its delegate method?
code
NSString *cellIdentifier = [[signInTableData objectAtIndex:2] objectForKey:#"cellIdentifier"];
signUpCustomCell *cell = (signUpCustomCell *)[signUpTable dequeueReusableCellWithIdentifier:cellIdentifier];
//NSLog(#"=====my username cell====%#",indexPath);
if(cell == nil)
{
cell = (signUpCustomCell *)[[signUpCustomCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
}
cell.backgroundColor = [UIColor clearColor];
cell.tableField.delegate = self;
CGRect frmTxt = cell.tableField.frame;
frmTxt.size.width = signUpTable.frame.size.width + TRAIL_MARGIN_CELL_CONTENT;
cell.tableField.frame = frmTxt;
cell.tableField.text = #"hello test";
If you know at which row your UITextField is then you can query UITableView for a cell at given IndexPath.
NSIndexPath *ip = [NSIndexPath indexPathForRow:0 inSection:0];
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:ip];
You'll need to cast that cell to what ever custom cell you are using to access the UITextField inside and your custom UITableViewCell should have a property that points to the UITextField or a method that would update the text.
-(void)viewWillAppear or -(void)viewDidApper overrides in your UIViewController subclass could be the places to do that, after you have loaded your data to the UITableView.
You need to set values into UITextField in delegate
cellForRowAtIndexPath as it is rendered for every cell of UITableView.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"yourcellidentifier"];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"yourcellidentifier"] autorelease];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
cell.yourTextView.text= textforRow;
return cell;
}

tablview with holdgesture in cells un-highlighting

I have my table view and the cells within it have the UILongPressGestureRecognizer added to them. The issue is that once a cell it touched it gets highlighted, but once my long gesture starts (holding the button) the highlighting goes away. The gesture works and its still being held but its a little confusing to the user because they dont know if its still being held. How can I make the cell stay highlighted throughout the hold.
some code:
- (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];
//add long press gesture for the audio AB (eventually VC and TP as well) list
//so that users can hold the cell and after 5 seconds have the dialpad for editing that entry
UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc]
initWithTarget:self
action:#selector(handleLongPress:)];
longPress.minimumPressDuration = 1;
[cell addGestureRecognizer:longPress];
}
cell.textLabel.text = [self.tableArray objectAtIndex:indexPath.row];
return cell;
}
- (void)handleLongPress:(UILongPressGestureRecognizer*)sender
{
//used to get indexPath of cell pressed
UITableViewCell *cell = (UITableViewCell *)[sender view];
//get the indexPath of cell pressed
NSIndexPath *indexPath = [self.myTableView indexPathForCell:cell];
//use the index press to figure out the proper join to hold
self.sharedJoinNumber = indexPath.row+286 ;
}
I did get this problem fixed by using
//highlight the apprioriate cell
[self.myTableView selectRowAtIndexPath:indexPath animated:FALSE scrollPosition:UITableViewScrollPositionNone];
right after - (void)handleLongPress:(UILongPressGestureRecognizer*)sender
however now if the hold is canceled the next cell clicked needs to be double taped to be highlighted. Basically the next tap after the longpress is cancelled doesnt get noticed. but i think this is a separate questing which i will file accordingly. the above code does fix my problem

Setting rowHeight in UITableView in viewDidAppear

This is the current working code.
But this should be simpler, I guess.
If I use the commented code I get a wrong height size.
Anyone some suggestions?
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
TableViewCell *cell = (TableViewCell *)[[self tableView]dequeueReusableCellWithIdentifier:CellClassName];
// TableViewCell *cell = [[[TableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellClassName] autorelease];
if (!cell)
{
NSArray *topLevelItems = [cellLoader instantiateWithOwner:self options:nil];
cell = [topLevelItems objectAtIndex:0];
// cell = [[[TableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellClassName] autorelease];
}
NSLog(#"cell height %f", cell.bounds.size.height);
[[self tableView] setRowHeight:cell.bounds.size.height] ;
}
Yes, you can definitely simplify it. Just call your own implementation of -tableView:cellForRowAtIndexPath: and use the cell that you get back from that, i.e.
UITableView *table = self.tableView;
NSIndexPath *index = [NSIndexPath indexPathForRow:0 inSection:0];
UITableViewCell *cell = [self tableView:table cellForRowAtIndexPath:index];
[table setRowHeight:cell.bounds.size.height]
Voilà: no more duplicated code.
On another note, you might want to do this in -viewDidLoad or -viewWillAppear: if your view controller is going to appear with animation. Doing it in -viewDidAppear: will cause the table’s row height to visibly jump when the view-presentation animation finishes.

didSelectRowAtIndexPath selecting more than one row at a time

I have a UITableView populated with 27 rows. I am trying to change the accessoryType of the selected cell. I do that in the didSelectRowAtIndexPath: delegate method.
The problem I am facing is that, when selecting a row and changing the accessoryType of the cell, the eleventh row from that row also gets modified.
I have tried printing the [indexPath row] value, but it's showing only the row that was selected and not another one.
I am really puzzled by such stuff; please help me out.
ADDED THE CODE cellForRowAtIndexPath method
UITableViewCell *cell;
if ([indexPath row] == 0) {
cell = [tableView dequeueReusableCellWithIdentifier:#"acell"];
}
else {
cell = [tableView dequeueReusableCellWithIdentifier:#"bcell"];
}
cell.selectionStyle = UITableViewCellSelectionStyleNone;
if (cell == nil && [indexPath row] != 0) {
cell = [[[UITableViewCell alloc] initWithStyle:
UITableViewCellStyleSubtitle reuseIdentifier:#"bcell"] autorelease];
}
else if(cell == nil && [indexPath row] == 0){
cell = [[[UITableViewCell alloc] initWithStyle:
UITableViewCellStyleSubtitle reuseIdentifier:#"acell"] autorelease];
}
if ([cell.contentView subviews]){
for (UIView *subview in [cell.contentView subviews]) {
[subview removeFromSuperview];
}
}
if ([indexPath row] == 0) {
cell.textLabel.text = #"Select All";
cell.textLabel.font = [UIFont boldSystemFontOfSize:13.0f];
}
else {
cell.textLabel.text = #"Some Text Here"
cell.detailTextLabel.text = #"Another piece of text here"
}
return cell;
I am doing %10 because the behaviour is repeating after 11th row, hence trying to create new object for every 11th row.
My didSelectRowAtIndexPath methos code is
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
if (cell.accessoryType == UITableViewCellAccessoryCheckmark) {
if ([indexPath row] != 0) {
NSIndexPath *tempIndex = [NSIndexPath indexPathForRow:0 inSection:0];
UITableViewCell *tempCell = [tableView cellForRowAtIndexPath:tempIndex];
tempCell.accessoryType = UITableViewCellAccessoryNone;
}
cell.accessoryType = UITableViewCellAccessoryNone;
}
else{
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
if ([indexPath row] == 0) {
for (int i = 0; i < [dataSource count]; i++) {
NSIndexPath *tempIndex = [NSIndexPath indexPathForRow:i+1 inSection:0];
UITableViewCell *tempCell = [tableView cellForRowAtIndexPath:tempIndex];
if (cell.accessoryType == UITableViewCellAccessoryCheckmark) {
tempCell.accessoryType = UITableViewCellAccessoryCheckmark;
}
else{
tempCell.accessoryType = UITableViewCellAccessoryNone;
}
}
}
Please help me in multiple selection or anyother way to solve the problem of multiple selection.
Thanks in advance!!
Here's one way to do it:
- (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] autorelease];
}
[cell.textLabel setText:[NSString stringWithFormat:#"Row %d", indexPath.row]];
NSIndexPath* selection = [tableView indexPathForSelectedRow];
if (selection && selection.row == indexPath.row) {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
} else {
cell.accessoryType = UITableViewCellAccessoryNone;
}
// Configure the cell.
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView cellForRowAtIndexPath:indexPath].accessoryType = UITableViewCellAccessoryCheckmark;
}
- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView cellForRowAtIndexPath:indexPath].accessoryType = UITableViewCellAccessoryNone;
}
Remember every cell in the table view is actually the same object being re-used. If you don't set the accessory type every time cellForRowAtIndexPath is called, when new cells scroll onto the screen they're going to all have the same accessory.
Multiple Select
For multiple selection it's a bit more complicated.
Your first option: Undocumented API
Note that this only works when the table's in editing mode. Set each cell's editing style to the undocumented UITableViewCellEditingStyleMultiSelect. Once you do that, you can get the table view's selection via an undocumented member of UITableView: indexPathsForSelectedRows. That should return an array of the selected cells.
You can expose this bit of functionality by putting this in a header:
enum {
UITableViewCellEditingStyleMultiSelect = 3,
};
#interface UITableView (undocumented)
- (NSArray *)indexPathsForSelectedRows;
#end
Then set the editing style for each cell like so:
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath {
return UITableViewCellEditingStyleMultiSelect;
}
When the table is in editing mode you'll see the multi-select controls on your cells.
To look through other undocumented API, you can use the nm command line utility like this:
nm /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS4.3.sdk/System/Library/Frameworks/UIKit.framework/UIKit
Your second option: Manage the selection yourself
Have your UITableView subclass contain an array that indicates which cells are selected. Then in cellForRowAtIndexPath, configure the cell's appearance using that array. Your didSelectRowAtIndexPath method should then look something like this:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if ([tableView indexPathIsSelected:indexPath]) {
[tableView removeIndexPathFromSelection:indexPath];
} else {
[tableView addIndexPathToSelection:indexPath];
}
// Update the cell's appearance somewhere here
[tableView deselectRowAtIndexPath:indexPath animated:NO];
}
This assumes you create indexPathIsSelected, removeIndexPathFromSelection, and addIndexPathToSelection methods in your UITableView subclass. These methods should do exactly what their names imply: Add, remove, and check for index paths in an array. You wouldn't need a didDeselectRowAtIndexPath implementation if you go with this option.
Remember every cell in the table view is actually the same object being re-used. If you don't set the accessory type every time cellForRowAtIndexPath is called, when new cells scroll onto the screen they're going to all have the same accessory." - daxnitro
This is where I got caught. I had mine set up so that in my "cellForRowAtIndexPath" function, I would only change the accessory for those specified in my array of checked cells, when what I should have done was update the accessory for all cells in the table.
In other words:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
//normal set up
//retrieve key
NSUserDefaults *settings = [NSUserDefaults standardUserDefaults];
id obj = [settings objectForKey:#yourKey];
//if the array is not populated, keep standard format for all cells
if (obj == nil){
selectedStyles = [[NSMutableArray alloc] initWithObjects:nil];
[cell setAccessoryType:UITableViewCellAccessoryNone]; //no check mark
[cell textLabel].textColor = [[UIColor alloc] initWithRed:0.0/255 green:0.0/255 blue:0.0/255 alpha:1.0]; //keep black color
}
//else retrieve information from the array and update the cell's accessory
else{
//if the cell is in your array, add a checkbox
[cell setAccessoryType:UITableViewCellAccessoryCheckmark]; //add check box
[cell textLabel].textColor = [[UIColor alloc] initWithRed:50.0/255 green:79.0/255 blue:133.0/255 alpha:1.0]; //change color of text label
//if the cell is not in your array, then keep standard format
[cell setAccessoryType:UITableViewCellAccessoryNone]; //no check mark
[cell textLabel].textColor = [[UIColor alloc] initWithRed:0.0/255 green:0.0/255 blue:0.0/255 alpha:1.0]; //keep black color
Hope this helps!

Animating a font size change in a UITableView

Hey Simple little app for educational purposes, its a simple uitableview and I want users to be able to use a uislider to adjust the font size as needed. The code I have now works to change the font but only when the view is updated, ie when i pull up or down the table view to reveal other cells. I'd like the font change to be reflected immediately as a user moves the uislider if possible, here's the code that I have working half way:
-(UITableViewCell *) tableView: (UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *) indexPath {
static NSString *SimpleTableIdentifier = #"SimpleTableIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier: SimpleTableIdentifier];
if (cell == nil)
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier: SimpleTableIdentifier] autorelease];
NSUInteger row = [indexPath row];
cell.text = [listData objectAtIndex:row];
UIImage *image = [UIImage imageNamed:#"star.png"];
cell.font = [UIFont systemFontOfSize:[fontSlider value]];
cell.image = image;
return cell;
}
You could make an IBAction for the fontSlider for the "Value Changed" option as follows:
-(IBAction) refreshResize
{
[self.view setNeedsDisplay];
}
That should work. setNeedsDisplay refreshes the screen.