I'd like very much to temporarily highlight a UITableViewCell to draw attention to the fact that the containing data has changed.
there is a UITableViewCell method: -setHighlighted:(BOOL) animated:(BOOL) but I can't make it do anything?
Here is the relevant part of the view controller:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell;
switch (indexPath.section) {
case 0: {
if (indexPath.row == 0) {
cell = [[UITableViewCell alloc ] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:#"currentLoc"];
cell.accessoryType = UITableViewCellAccessoryNone;
cell.textLabel.text = #"This is the special cell";
}
[cell setHighlighted:YES animated:YES];
[cell setHighlighted:NO animated:YES];
//[cell setNeedsDisplay];
} else {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:#"setLocAutomatically"];
cell.accessoryType = UITableViewCellAccessoryNone;
cell.textLabel.text = #"Foo";
}
} break;
case 1: {
cell = [[UITableViewCell alloc ] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:#"selectCity"];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
if (indexPath.row == 0) {
cell.textLabel.text = #"Select a Bar";
} else {
cell.textLabel.text = #"Select a Baz";
}
} break;
}
[cell autorelease];
return cell;
}
See the [cell setHighlight...] above for my attempt.
Much to my frustration, the cell doesn't highlight and I haven't figured out any way to make it work.
Thank you,
Carl C-M
just put the highlighting / background changing / whatever code in:
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
Because you're doing all this in tableView:cellForRowAtIndexPath:, nothing happens to the cell on-screen until after you return the cell. Therefore, setting the cell to be highlighted does nothing visible to the user.
What you want to do is figure out a way to set the cell as highlighted after you return it from the method. Perhaps looking into NSObject's performSelector:withObject:afterDelay: method might do you some good - you could set the cell as highlighted with a delay, so it gets returned, displayed, then highlighted.
Have you thought of altering the UILabel for the cell and simply changing the appearance rather than trying to alter the cell itself. Possible a different text color or bold?
That would allow you to keep the changes within tableView:cellForRowAtIndexPath:
This also ensures the the default appearance of highlighting isn't mixed with your additional message of changed information. Highlighting can mean a lot of things, but text formatting can be used to indicate your specific concept.
UILabel * textLabel = [yourCell textLabel];
// From here you can alter the text
http://developer.apple.com/iphone/library/documentation/UIKit/Reference/UILabel_Class/Reference/UILabel.html
try using the
[tblView selectRowAtIndexPath:myIndex animated:YES scrollPosition:UITableViewScrollPositionTop];
function.
I've got a variation on this that is continuing to stump me. I have a wizard that uses tables to indicate possible selections. Once a selection is made, I'd like to temporarily highlight the selected row, then advance to the next frame in the wizard.
I do the advancement in
- (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
But I can't make the highlight happen.
Any suggestions?
Try this:
[tableView selectRowAtIndexPath:indexPath animated:NO scrollPosition:UITableViewScrollPositionNone];
- (void) tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (//tell if cell is marked) {
[cell setBackgroundColor:[UIColor colorWithRed:158.0/255.0 green:28.0/255.0 blue:36.0/255.0 alpha:1.0]];
[[cell textLabel] setTextColor:[UIColor whiteColor]];
if ([cell detailTextLabel]) {
[[cell detailTextLabel] setTextColor:[UIColor whiteColor]];
}
}
else
{
[cell setBackgroundColor:[UIColor whiteColor]];
[[cell textLabel] setTextColor:[UIColor blackColor]];
if ([cell detailTextLabel]) {
[[cell detailTextLabel] setTextColor:[UIColor blackColor]];
}
}
}
use this in the uitableviewdelegate and then when you want to highlight the cell mark the cell then call reloadData on the tableview
Related
I am still struggling with the sign up page for my iphone app - at the moment I am having problems with the gender field.
My idea was that when the user presses the gender field, a table view containing "Male" and "Female" slides up from the bottom and the user then puts a checkmark next to his actual gender. I do not really understand how to correctly obtain this gender table view though.
Currently I have my GenderTableViewCell which points to both a user interaction enabled label and a GenderTableViewController and then I have set the input view of the first to the table view of the latter. In this way a table with "Male" and "Female" actually do slide up when the gender field is touched but as the table is not in grouped style as I specified it to be in GenderTableViewController.xib I have a feeling that I am not on the right track!!
I have been googling and googling but have not been able to find any similar examples - maybe it is not nice to have a table view sliding up? Should I use a UIPicker instead?
I would use a UIPicker instead. It's going to be much easier to implement, and it is a far more standard experience for the user.
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
[tableView setBackgroundColor:[UIColor clearColor]];
[tableView setSeparatorStyle:UITableViewCellSeparatorStyleNone];
return 2;
}
-(NSInteger)tableView:(UITableView *)table numberOfRowsInSection:(NSInteger)section
{
return 1;
}
-(CGFloat) tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 35;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexpath // set row value for table
{
UITableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:#"anycell"];
if(cell == nil)
{
cell=[[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"anycell"] autorelease];
/// UIImageView *imgView=[[[UIImageView alloc] init] autorelease];
// UIImage *img;
CGRect frame;
frame.origin.x=10;
frame.origin.y=5;
frame.size.width=280;
if(indexpath.section ==0)
{
//img=[UIImage imageNamed:#"textbox1.png"];
frame.size.height=27;
txtname=[[UITextField alloc] initWithFrame:frame];
txtname.delegate=self;
txtname.textColor=[UIColor colorWithRed:211.0/255 green:236.0/255.0 blue:245.0/255.0 alpha:1.0];
txtname.placeholder=#"User Name";
[txtname setAutocorrectionType:UITextAutocorrectionTypeNo];
[txtname setKeyboardType:UIKeyboardTypeURL];
[cell.contentView addSubview:txtname];
}
else if(indexpath.section == 1)
{
frame.size.height=27;
txtpassword=[[UITextField alloc] initWithFrame:frame];
txtpassword.delegate=self;
txtpassword.textColor=[UIColor colorWithRed:211.0/255 green:236.0/255.0 blue:245.0/255.0 alpha:1.0];
txtpassword.secureTextEntry=TRUE;
txtpassword.placeholder=#"Password";
[cell.contentView addSubview:txtpassword];
}
else
{
frame.size.height=27;
//frame.size.width=200;
btnSave=[[UIButton alloc] initWithFrame:frame];
[btnSave setImage:[UIImage imageNamed:#"user-save.png"] forState:UIControlStateNormal];
[btnSave addTarget:self action:#selector(saveClicked) forControlEvents:UIControlEventTouchUpInside];
[cell.contentView addSubview:btnSave];
}
}
if(indexpath.section == 0)
txtname.text=appDelegate.setObj.username;
else if(indexpath.section == 1)
txtpassword.text=appDelegate.setObj.password;
UIImageView *imgView=[[[UIImageView alloc] init] autorelease];
imgView.image=[UIImage imageNamed:#"textbox1.png"];
cell.backgroundView =imgView;
cell.selectionStyle=UITableViewCellSelectionStyleNone;
return cell;
}
I have a UITableView that I want to use to allow multiple selections. I have rolled together most of the functionality, but am having one small problem.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSLog(#"Selected");
UITableViewCell *selectedCell = [tableView cellForRowAtIndexPath:indexPath];
if ([selectedCell accessoryType] == UITableViewCellAccessoryNone) {
[selectedCell setBackgroundColor:[UIColor grayColor]];
[selectedCell setAccessoryType:UITableViewCellAccessoryCheckmark];
[[selectedCell textLabel] setTextColor:[UIColor whiteColor]];
} else {
[selectedCell setAccessoryType:UITableViewCellAccessoryNone];
[selectedCell setBackgroundColor:[UIColor clearColor]];
[[selectedCell textLabel] setTextColor:[UIColor blackColor]];
}
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
This is the code I am using to keep the cell selected, however when the user taps on the cell, the aaccessory view turns white and then turns back to blue.
What is the best way for me to keep the accessory view white?
Thanks
I believe easy way to achieve this is by creating custom imageview with checkmark image(you need to get it as white checkmark) and set it as accessory view when selected.
This will avoid the standard behavior of the accessoryview and achieve your goal.
Most of the views in my app are UITableVlews inside a UIViewController. My App feels like it's lagging when trying to scroll through the tables. I was wondering (1.) if it is better to create the cell objects in the table view, or create them at runtime and add them to the cells subview?
examples:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
case 3:
{
NSNumber *tetherState = [[mobIntDict objectForKey:#"State"] intValue];
NSNumber *currValState = [[NSNumber numberWithInt:1023] intValue];
tetherSw = [[UISwitch alloc] initWithFrame:CGRectMake(197, 8, 94, 27)];
tetherSw.tag = kDefaultSwTag;
if(tetherState == currValState){
tetherSw.on = YES;
}else{
tetherSw.on = NO;
}
[tetherSw addTarget:self action:#selector(tetherSwAction:) forControlEvents:UIControlEventValueChanged];
[cell.contentView addSubview:tetherSw];
cell.textLabel.text = #"Tether";
[tetherSw release];
}
break;
}
-OR-
-(void)viewDidLoad{
tetherSw = [[[UISwitch alloc] initWithFrame:CGRectMake(197, 8, 94, 27)] autorelease];
tetherSw.tag = kDefaultSwTag;
[tetherSw addTarget:self action:#selector(tetherSwAction:) forControlEvents:UIControlEventValueChanged];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
case 3:
{
[cell addSubView:tetherSw];
}
}
It doesn't matter. Your cell is complex and therefore your view lags.
If you want performance, avoid the UISwitch. Toggle the cell's checkmark instead. In fact, just avoid any fancy table view cell subclasses or custom backgrounds, to reduce the size of the view hierarchy.
Are you properly de-queuing and reusing cells?
It would optimise things a lot if you reused a cell, say a #"SwitchCell", that would speed up scrolling a lot. Currently a lot of time will be spent adding the switch to the cell's content view (laying out of views etc,) and performing other tasks that only need to happen once in a cells lifetime, instead of every time a new cell appears while scrolling.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// Create cell
static NSString *CellIdentifier = #"SwitchCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
UISwitch *tetherSw = [[UISwitch alloc] initWithFrame:CGRectMake(197, 8, 94, 27)];
tetherSw.tag = kDefaultSwTag;
[tetherSw addTarget:self action:#selector(tetherSwAction:) forControlEvents:UIControlEventValueChanged];
[cell.contentView addSubview:tetherSw];
[tetherSw release];
}
// Setup for each cell
cell.textLabel.text = #"Tether";
NSNumber *tetherState = [[mobIntDict objectForKey:#"State"] intValue];
NSNumber *currValState = [[NSNumber numberWithInt:1023] intValue];
UISwitch *tetherSw = (UISwitch *)[cell.contentView viewWithTag: kDefaultSwTag];
tetherSw.on = (tetherState == currValState);
// Return
return cell;
}
See the docs for dequeueReusableCellWithIdentifier for more information on dequeuing.
Also, make sure that there is no transparency in any of your cell's subviews. This causes a lot of lagging. Make sure any labels or anything else you add has opaque = YES and a background color set.
Actually, my tables are setup just fine. A solid restore did the trick, and my app runs without the afore-mentioned "LAG"
I'm getting really desperate trying to add a UIImageView to UITableViewCell.backgroundView. All my efforts have resulted in this crappy rendering:
alt text http://img.skitch.com/20091123-ch8wk6pdxqkrn9tpftnhusigcy.jpg
It looks like the cell's label's white background is sitting on top of cell's background and covering portions of it.
I tried setting the label's background color to clear, or some other color and it does not have any event. It is always white.
The reason I know it's the text label's background causing this white area is that if I don't do [cell setText:#"Cell text here"]; the white area is gone and I see just the cell's background image.
Here's the code that I'm using. The table view is added in the .xib file and UITableView is added to UIViewController:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [myCollection.items count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSUInteger rowIndex = indexPath.row;
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
cell.backgroundView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"darkCellBackground.png"]];
cell.selectedBackgroundView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"darkCellBackground.png"]];
}
[cell setText:#"Cell text here"];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// Navigation logic may go here. Create and push another view controller.
// AnotherViewController *anotherViewController = [[AnotherViewController alloc] initWithNibName:#"AnotherView" bundle:nil];
// [self.navigationController pushViewController:anotherViewController];
// [anotherViewController release];
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
return NO;
}
I'm sure I'm doing something wrong but cant quite figure out what.
The solution is here: Changing UITableViewCell textLabel background color to clear
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
[[cell textLabel] setBackgroundColor:[UIColor clearColor]];
[[cell detailTextLabel] setBackgroundColor:[UIColor clearColor]];
}
What you want is:
cell.backgroundColor = [UIColor colorWithPatternImage:[[UIImage imageNamed:#"some.png"]stretchableImageWithLeftCapWidth:320 topCapHeight:44]];
Did you try setting the cell's textLabel to not be opaque?
cell.textLabel.opaque = NO;
Or, if your background is a solid color where the label is, you could set the label's background color to the appropriate color.
Deprecation sidenote:
[UITableViewCell setText:] is deprecated in OS 3.0 - you shouldn't use it (if you're building for 3.0+) as it could disappear in the future. Instead, you should use UITableViewCell's textLabel property to set the text of the UILabel directly.
Memory management sidenote:
You're leaking two instances of UIImageView for every UITableViewCell you create using this code. These lines
cell.backgroundView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"darkCellBackground.png"]];
cell.selectedBackgroundView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"darkCellBackground.png"]];
should be changed to this
cell.backgroundView = [[[UIImageView alloc] initWithImage:[UIImage imageNamed:#"darkCellBackground.png"]] autorelease];
cell.selectedBackgroundView = [[[UIImageView alloc] initWithImage:[UIImage imageNamed:#"darkCellBackground.png"]] autorelease];
Or you could use release instead of autorelease (doing it properly; don't try to just substitute release for autorelease, of course). Either way, the UITableViewCell takes ownership of the background views and because you alloc'd the objects you need to release your ownership of the objects.
Maybe you should take a look at this:
How can I set the background color of a cell in UITableView on iphone?
-(void) tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
cell.backgroundView=[[UIImageView alloc] initWithImage:[UIImage imageNamed:#"list-view-bg.png"] highlightedImage:[UIImage imageNamed:#"list-view-bg.png"]];
}
Set the table view background to clear color
i'm using a default style table,
i want to add more rows to the table, how can i customize it?
code:
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle
reuseIdentifier:CellIdentifier] autorelease];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
// Leave cells empty if there's no data yet
if (nodeCount > 0)
{
// Set up the cell...
ARecord *aRecord = [self.entries objectAtIndex:indexPath.row];
cell.textLabel.text = aRecord.lDate;
cell.detailTextLabel.text = aRecord.WNum;
// Only load cached images; defer new downloads until scrolling ends
//(!aRecord.appIcon) - use icon
if (!aRecord.appIcon)
{
if (self.tableView.dragging == NO && self.tableView.decelerating == NO)
{
[self startIconDownload:aRecord forIndexPath:indexPath];
}
// if a download is deferred or in progress, return a placeholder image
cell.imageView.image = [UIImage imageNamed:#"Placeholder.png"];
}
else
{
cell.imageView.image = aRecord.appIcon;
}
}
return cell;
}
Not sure that I understand the question. The number of sections and rows in the table are controlled by the table view's UITableViewDataSource (in most code examples, that protocol is implemented by the view's controller, but it could be a separate object).
The code you've posted comes into play much later in the process: after the view has determined how many rows are present, total, and which are currently on-screen, and needs to render those rows. But, in general, it and the other methods of the UITableViewDelegate protocol are how you'd customize the appearance and behavior of the table. (Along with the properties of the view itself.)
The number of rows in the tableview is determined by what you return in
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
if you return 500 there, you'll have a 500 row table.
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [tblArray count];
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *CellIdentifer=[NSString stringWithFormat:#"%i",indexPath.row];
UITableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:CellIdentifer];
if(cell==nil){
cell=[self myCustomCell:CellIdentifer dicToSet:[tblArray objectAtIndex:indexPath.row]];
[cell setAccessoryType:UITableViewCellAccessoryDisclosureIndicator];
}
return cell;
}
-(UITableViewCell*)myCustomCell:(NSString*)CellIdentifer dicToSet:(NSDictionary*)dicToSet
{
UITableViewCell *cell=[[[UITableViewCell alloc] initWithFrame:CGRectMake(0, 0, 320, 44) reuseIdentifier:CellIdentifer] autorelease];
UIImageView *imgV=[[UIImageView alloc] initWithFrame:CGRectMake(2, 2, 40, 40)];
[imgV setImage:[UIImage imageNamed:[dicToSet valueForKey:#"Photo"]]];
[cell addSubview:imgV];
[imgV release];
return cell;
}