Accessing -willDisplayCell method of moreNavigationController's UITableView - iphone

After setting the backgroundView of UITableView in moreNavigationController like so...
UITableView *moreTableView = (UITableView *)tabBarController.moreNavigationController.topViewController.view;
[moreTableView setBackgroundView:[[UIImageView alloc] initWithImage:[UIImage imageNamed:#"bg.png"]]];
...the cells of that UITableView changed their backgroundColor from white to clear (transparent). I've tried setting it back to white with the following lines of code...
for (UITableViewCell *cell in [moreTableView visibleCells]) {
[cell setBackgroundColor:[UIColor whiteColor]];
}
...but unfortunately this does not work, so I guess the only solution would be to set that backgroundColor in the -willDisplayCell: method. Can anyone tell me how to access that method? Any help would be greatly appreciated.

If you have a custom cell then the back ground colour of the cell can be set in a subclass of UITabeViewCell, otherwise you should try to add this logic to the tableView:cellForRowAtIndexPath: method of the UITableView's datasource.
What you are doing in your loop will only effect the visible cells, since they will be reused and if the background is being set to clear dynamically then you'll always have your background overridden.

Related

Changing a cell's color while in "highlighted" state

How can I change the default (blue) color that appears on a table view's cell when it is tapped?
(Just the overlay color, as when You tap on an option in Settings.app and it gets blue before taking You there)
selectedBackgroundView
The view used as the background of the cell when it is selected.
#property(nonatomic, retain) UIView *selectedBackgroundView
from UITableViewCell Class Reference
Make an UIView, set whatever backgroundColor you wish and set it as a selectedBackgroundView for your cell.
you can use any of them
[cell setSelectionStyle:UITableViewCellSelectionStyleNone];
//or
[cell setSelectionStyle:UITableViewCellSelectionStyleGray];
Maybe this will help you

How can I stop my custom UITableViewCell backgroundImage from being stretchable?

If I create a background image for my table cell in the init method of my UITableViewCell subclass, the image comes out exactly how I drew it, and tableView:heightForRowAtIndexPath: simply adds a gap around it.
But if instead I create the background image in my tableView's tableView:cellForRowAtIndexPath: method and set it, changing the cell height will now stretch the image.
I need to create the background views in the cellForRowAtIndexPath method, as the background changes for different rows. How can I make my image's size fixed again?
Have you tried setting the contentMode to UIViewContentModeCenter for the backgroundView of the cell?
put it here
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
cell.backgroundView.contentMode = UIViewContentModeCenter;
}
You could create something with:
UIView *cellBackView = [[[UIView alloc] initWithFrame:CGRectZero] autorelease];
<insert image>;
cell.backgroundView = cellBackView;
My guess is the backgroundView gets strechted automatically, but you could make sure the image isn't stretched on that view by setting a width and height. This way, you can do whatever you like with that view.

UIImageView Animation Stopping in UITableView

I have a UIImageView inside of a UITableViewCell. The UIImageView animates. For some odd reason, when the cell goes out of view, the animation stops. The UIImageView is never initialized again and the UIImageView is never explicitly told to - (void)stopAnimating; so I'm not sure why it's stopping.
Here's the interesting parts of my cellforRowAtIndexPath:. As you can
cell = (BOAudioCell *)[tableView dequeueReusableCellWithIdentifier:AudioCellIdentifier];
if (!cell) {
cell = [[[BOAudioCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:AudioCellIdentifier] autorelease];
BOPlayControl *playControl = [(BOAudioCell *)cell playControl];
[[playControl playbackButton] addTarget:self action:#selector(playbackButtonTapped:) forControlEvents:UIControlEventTouchUpInside];
}
int index = [indexPath row];
BOModel *model = [models objectAtIndex:index];
[[(BOAudioCell *)cell titleLabel] setText:[model title]];
[[(BOAudioCell *)cell favoriteButton] addTarget:self action:#selector(favoriteButtonTapped:) forControlEvents:UIControlEventTouchUpInside];
As you can tell, I'm not setting the appropriate animation begin point for the cell because there is not a built in way with a UIImageView.
You should have exposed the UIImageView on your cell and started the animation in the cellForRowAtIndexPath method or do an override of the prepareForReuse method of the UITableViewCell and started the animation in that method.
prepareForReuse is called every time your reusable cell is dequeued from the reusable queue. Just to note, if you were to use this, do not forget to invoke the superclass implementation.
When the cell goes off-screen, it will be released, and the subview (the image view) will be released as well, causing the animation to be stopped.
Keep a -retain-ed instance of that image view somewhere to avoid this.
I wrote a workaround. I'm just using a NSTimer to coordinate manually animating the UIImageView. It works great.

Cocoa-Touch: How to: custom UITableViewCell with UIColor clearColor background

I have a UITableView with custom cells.
I have MyTableViewCell : UITableViewCell and MyTableViewCellContentView : UIView classes.
What I'm doing is basically what is done in the AdvancedTableViewCells demo app from Apple with a slight change, on some rows I want to use a clearColor background to show the table's background behind the painted text.
So in MyTableView's cellForRowAtIndexPath I'm doing:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"MyCell";
MyTableViewCell *cell = (MyTableViewCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[MyTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
cell.someValue = indexPath.section;
[cell finishedSetup];
return cell;
}
And in my MyTableViewCell's finishedSetup:
cellContentView = [[MyTableViewCellContentView alloc] initWithFrame:CGRectMake(0, 0, 320, 80) cell:self];
cellContentView.autoresizingMask = UIViewAutoresizingNone;
cellContentView.contentMode = UIViewContentModeRedraw;
[self.contentView addSubview:cellContentView];
And in MyTableViewCellContentView I implement the drawRect method. And plan to not use any subviews but draw my custom content just as the Apple example does in the CompositeSubviewBasedApplication.
The problem is that for a few sections I want to use a clearColor backgroundColor. This works, until a cell with a non-clearColor backgroundColor is reused to draw a clearColor cell, at which time the background is not cleared and will still have the old color.
How can I make the background redraw?
Edit:
I forgot to mention, I'm setting the background color in MyTableViewCellContentView's init after calling super's init. Setting it via:
self.backgroundColor = [UIColor clearColor];
I've verified that this in fact does get called and is called as expected with clearColor or redColor.
I've also tried setting the table cell's background color, it didn't help.
Edit #2: Here's my drawRect method:
- (void)drawRect:(CGRect)rect {
[super drawRect:rect];
static int i = 0;
[[NSString stringWithFormat:#"Cell %d", ++i] drawAtPoint:CGPointMake(3, 3) withFont:[UIFont boldSystemFontOfSize:16]];
}
To make the background color setting take effect you need to do the setting in tableView:willDisplayCell:forRowAtIndexPath - the OS will not alter anything you set here. The reason is that some additional setup of the cell gets done by the OS after you return it from tableView:cellForRowAtIndexPath. If you can, get a look at session 101 from WWDC 09 presented by Jason Beaver.
I haven't found out why it was happening. But I've tried a different strategy. I'm no longer reusing table cells, since I don't have that many of them.
Instead I'm creating all cells at startup and actually get a boost in performance when showing them since this way there is no additional setup needed when scrolling.

UITableViewCell / UISegmentedControl border issue

I'm trying to get a UISegmentedControl in a group UITableViewCell much like in the wifi settings in the Setting Application. The problem I'm having is I'm getting a double border. I get one border for the UISegmentedControl and one for the UITableViewCell.
I'm guessing I need to remove the border from the UITableViewCell. How can I go about doing that?
I just noticed this is still getting answers. As it happens I've had to do this for another project and since I asked this question I've learned a lot more about iPhone dev. Here is how I solved it recently. It's all about making the frame the correct size. This should do it for a standard table.
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"CellIdentifier"];
if(cell == nil)
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"CellIdentifier"] autorelease];
UISegmentedControl *segmentedControl = [[UISegmentedControl alloc] initWithFrame:CGRectMake(-1.0f, -1.0f, 302.0f, 46.0f)];
[cell.contentView addSubview:segmentedControl];
In the case of the Wi-Fi settings, I suspect what they've done is made the "Forget this Network" button, the "IP Address" label, and the "DHCP/BootP/Static" segmented control all part of the table's header view. If you need to do this in the middle of your table (as opposed to at the top or bottom, for which you'd use the tableHeaderView and tableFooterView properties respectively), I'd suggest using the delegate methods -tableView:viewForHeaderInSection: with -tableView:heightForHeaderInSection, or the corresponding Footer variants. With any of those, you'd set up a custom view for that "section" of your table view (using either a clear background color or [UIColor groupTableBackgroundColor]), containing a label and a segmented control arranged so that they match up with the rest of the table sections.
Using the technique in this post to remove the background opacity of the UITableViewCell worked more easily for me to get only the UISegmentedControl to show in the table row.
I've got slightly further with this. So far I've subclassed UITableViewCell. I created a nib with a UISegmentedControl in it and I set the UITableViewCell background alpha to 0. It still doesn't look quite right, but it's better than before.
My solution is to allow the segmented control to resize to fit, and to hide the table view's background in tableView:willDisplayCell:forRowAtIndexPath:.
This yields results identical to the "Settings.app > WiFi > Your Network > IP Address" Segmented Control without hard-coding any layout metrics:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier] autorelease];
}
UISegmentedControl *control = [[UISegmentedControl alloc] initWithItems:[NSArray arrayWithObjects:#"One", #"Two", #"Three", nil]];
control.segmentedControlStyle = UISegmentedControlStylePlain;
control.autoresizingMask = (UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight);
control.frame = cell.contentView.bounds;
[cell.contentView addSubview:control];
[control release];
}
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
cell.backgroundView.alpha = 0.0;
}
The trick appears to be to size the UISegmentedControl to the size of the backgroundView of the control, not the contentView. I was able to do it programmatically by doing the following:
// Size to cover the entire background
self.contentView.frame = self.backgroundView.frame;
self.myControl.frame = self.contentView.bounds;
Note that if you are using an accessory, you need to account for the accessoryView as well.
The reason is that the view hierarchy is as follows:
self (the UITableViewCell or subclass)
backgroundView
contentView
(your controls go here)
accessoryView
In portrait layout, the backgroundView's frame is {{9, 0}, {302, 44}}, whereas the contentView's frame is slightly smaller, at {{10, 1}, {300, 42}}. This gives the cell its 1px "border" when the table style is grouped. You have to resize both the contentView and your control to get the appropriate size.
(NOTE: While Apple actually has several examples of a UISegmentedControl in the UICatalog sample code project in the SDK, they effectively "cheat" by using a UIViewController and setting the main view's background color to the table background color.)