I am using a slide in menu style which loads a UITableView. - ECSlidingViewController
I have about 7 cells in a table view setup as follows:
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = (UITableViewCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
cell.contentView.backgroundColor = [UIColor colorWithRed:75.0/255.0 green:83.0/255.0 blue:102.0/255.0 alpha:1.0];
UIView *topSplitterBar = [[UIView alloc] initWithFrame:CGRectMake(0, 0, cell.bounds.size.width, 1)];
topSplitterBar.backgroundColor = [UIColor colorWithRed:62.0/255.0 green:69.0/255.0 blue:85.0/255.0 alpha:1];
[cell.contentView addSubview:topSplitterBar];
cell.textLabel.backgroundColor = [UIColor clearColor];
cell.textLabel.textColor = [UIColor colorWithRed:196.0/255.0 green:204.0/255.0 blue:218.0/255.0 alpha:1];
cell.textLabel.font = [UIFont systemFontOfSize:18.0f];
cell.textLabel.shadowColor = [UIColor colorWithRed:27.0/255.0 green:31.0/255.0 blue:41.0/255.0 alpha:1];
cell.textLabel.shadowOffset = CGSizeMake(0, 1);
UIView *selectedBg = [[UIView alloc] initWithFrame:cell.frame];
selectedBg.backgroundColor = [UIColor colorWithRed:50.0/255.0 green:56.0/255.0 blue:73.0/255.0 alpha:1];
cell.selectedBackgroundView = selectedBg;
What would be the best way to show a cell as the selectedBg if that is the currently displayed controller?
I can access the following for example:
if ([self.slidingViewController.topViewController isKindOfClass:[MESHomeViewController class]]) {
However, I am not sure where would be best practice to set this up? I can do it in the switch case for the cell label setup... For example:
switch ( indexPath.row ) {
case 0: {
if ([self.slidingViewController.topViewController isKindOfClass:[MESHomeViewController class]]) {
cell.contentView.backgroundColor = [UIColor colorWithRed:50.0/255.0 green:56.0/255.0 blue:73.0/255.0 alpha:1];
}
cell.textLabel.text = NSLocalizedString(#"LMGames", #"Left Menu - Games");
break ;
However, when a new item is selected from the menu I would need to reload the table each time, is that good? Completing a self.tableView reloadData each time a cell is selected, or is there a better way to approach this?
Two ideas for you:
Set the selectedBg in the didSelectRowAtIndexPath method in order to set the selected cell.
Keep an integer reference to the currently selected row and the previously selected row and then refresh only those rows by using a method similar to: How to reload and animate just one UITableView cell/row?
I hope that helps!
Related
I'm working with RESIDEMENU,and trying to add a line between cells of LeftMenuViewController,here is my 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];
cell.backgroundColor = [UIColor clearColor];
cell.textLabel.font = [UIFont fontWithName:#"HelveticaNeue" size:21];
cell.textLabel.textColor = [UIColor whiteColor];
cell.textLabel.highlightedTextColor = [UIColor lightGrayColor];
cell.selectedBackgroundView = [[UIView alloc] init];
}
NSArray *titles = #[#"Home", #"Calendar", #"Profile", #"Settings", #"Log Out"];
NSArray *images = #[#"IconHome", #"IconCalendar", #"IconProfile", #"IconSettings", #"IconEmpty"];
cell.textLabel.text = titles[indexPath.row];
cell.imageView.image = [UIImage imageNamed:images[indexPath.row]];
UIView * lineView= [[UIView alloc]initWithFrame:CGRectMake(10, 0, cell.contentView.bounds.size.width, 3)];
lineView.backgroundColor=[UIColor redColor];
[cell.contentView addSubview:lineView];
return cell;
}
I can see these lines at first, but when I touch any cell, the cell is highlighted ,and the line of this cell disappear weirdly.any way to fix it?
snapshot before :
snapshot when click a cell:
UITableViewCell changes the background color of all sub views when cell is selected or highlighted.
You have three options :
No selection style
cell.selectionStyle = UITableViewCellSelectionStyleNone;
Subclass UITableViewCell and overriding Tableview cell's setSelected:animated and/or setHighlighted:animated
Add the line as a layer
CALayer* layer = [CALayer layer];
layer.frame = CGRectMake(10, 0, cell.contentView.bounds.size.width, 3);
layer.backgroundColor = [UIColor redColor].CGColor;
[cell.contentView.layer addSublayer:layer];
Another workaround is overwriting setBackgroundColor: and expose similar method to change its backgroundColor.
#interface
- (void)setPersistentBackgroundColor:(UIColor*)color;
#implementation
- (void)setPersistentBackgroundColor:(UIColor*)color
{
super.backgroundColor = color;
}
- (void)setBackgroundColor:(UIColor *)color
{
// [super setBackgroundColor:color];
// prohibit from changing its background color.
}
In my cellForRowAtIndexPath method I am using following if statements:
if ([taskitem.isCritical isEqualToString:#"iscritical"]){
cell.textLabel.textColor = [UIColor whiteColor];
cell.textLabel.backgroundColor = [UIColor redColor];
}
else if ([taskitem.isUrgent isEqualToString:#"isurgent"]){
cell.textLabel.textColor = [UIColor whiteColor];
cell.textLabel.backgroundColor = [UIColor blueColor];
}
else if ([taskitem.isCompletedOK isEqualToString:#"iscompleted"]){
cell.textLabel.textColor = [UIColor whiteColor];
cell.textLabel.backgroundColor = [UIColor greenColor];
UIButton *doneButton4 = [[UIButton alloc]initWithFrame:CGRectMake(0, 10, 12, 12)];
[doneButton4 setImage:[UIImage imageNamed:#"done"]forState:UIControlStateNormal];
[cell addSubview:doneButton4];
}
else {
cell.textLabel.textColor = [UIColor blackColor];
}
cell.textLabel.text = taskitem.taskName;
The problem is that the if statements are changing their behaviour if the user taps on any of the sections headers.
Do you find any error on my code that could be the reason of this weird behaviour or should I search for another reason in another method?
It looks like you're probably having a cell reuse problem. You need to make sure that anything you do in one case, is done for each case (or undone).
For example, in first your three conditions, you set the text colour and the background colour. But in the fourth case (the else) you only set the text colour, leaving the background colour to be whatever it was on this cell the last time it was used. You need to set the background colour in the else case as well. (Optionally, you can set all items back to defaults before the if).
You have a second problem here, with the third case, that creates and adds a button to the cell. But in the other cases, you do not remove that button if it exists. So when you get a cell that was used for a completed item earlier, you'll end up with a button that doesn't belong. Even if the cell is used for another completed item, you'll get two buttons on the same cell. One on top of the other (so it likely won't be visible, but it's still a problem).
Try using this code:
UIButton* oldButton = [cell viewWithTag:253];
if (oldButton)
{
[oldButton removeFromSuperview];
}
if ([taskitem.isCritical isEqualToString:#"iscritical"]) {
cell.textLabel.textColor = [UIColor whiteColor];
cell.textLabel.backgroundColor = [UIColor redColor];
}
else if ([taskitem.isUrgent isEqualToString:#"isurgent"]) {
cell.textLabel.textColor = [UIColor whiteColor];
cell.textLabel.backgroundColor = [UIColor blueColor];
}
else if ([taskitem.isCompletedOK isEqualToString:#"iscompleted"]) {
cell.textLabel.textColor = [UIColor whiteColor];
cell.textLabel.backgroundColor = [UIColor greenColor];
UIButton *doneButton4 = [[UIButton alloc] initWithFrame:CGRectMake(0, 10, 12, 12)];
[doneButton4 setImage:[UIImage imageNamed:#"done"] forState:UIControlStateNormal];
doneButton4.tag = 253;
[cell addSubview:doneButton4];
}
else {
cell.textLabel.textColor = [UIColor blackColor];
cell.textLabel.backgroundColor = [UIColor whiteColor];
}
cell.textLabel.text = taskitem.taskName;
I don't recommend using tags like this in production code, but it's a quick way to see if it solves your problems. In real code, use a UITableViewCell subclass with a property for the done button that you can just show and hide. Ideally you're not creating it each time as that's an expensive operation and could slow down your scrolling performance.
Create doneButton4 in (cell == nil) when reuse cells in table view
- (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];
UIButton *doneButton4 = [[UIButton alloc]initWithFrame:CGRectMake(0, 10, 12, 12)];
[doneButton4 setImage:[UIImage imageNamed:#"done"]forState:UIControlStateNormal];
[cell addSubview:doneButton4];
doneButton4.tag=100;
}
UIButton *doneButton4=(UIButton*)[cell viewWithTag:100];
doneButton4.hidden=YES;
if ([taskitem.isCritical isEqualToString:#"iscritical"]){
cell.textLabel.textColor = [UIColor whiteColor];
cell.textLabel.backgroundColor = [UIColor redColor];
}
else if ([taskitem.isCritical isEqualToString:#"isurgent"]){
cell.textLabel.textColor = [UIColor whiteColor];
cell.textLabel.backgroundColor = [UIColor blueColor];
}
else if ([taskitem.isCritical isEqualToString:#"iscompleted"]){
cell.textLabel.textColor = [UIColor whiteColor];
cell.textLabel.backgroundColor = [UIColor greenColor];
doneButton4.hidden=NO;
}
else {
cell.textLabel.textColor = [UIColor blackColor];
}
cell.textLabel.text = taskitem.taskName;
}
I am using a UITableView as a preference screen, where rows represent user selections.
I am maintaining the selection using NSUserDefaults. My issue is that I am trying to create a special look for the cell, which I do by building a special color and using it in the following code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"UITableViewCell"];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"UITableViewCell"];
}
cell.textLabel.text = [myArray objectAtIndex:[indexPath row]];
UIView *selectionColor = [[UIView alloc] init];
selectionColor.backgroundColor = [UIColor colorWithRed:(200/255.0) green:(200/255.0) blue:(200/255.0) alpha:0.6];
cell.selectedBackgroundView = selectionColor;
cell.textLabel.textColor = [UIColor grayColor];
return cell;
}
Based on this, when a user click occurs, it displays the grayish color that I am building in this event, which is what I want. When the user deselects it, the greyish background color is gone.
Now I need to add the NSUserDefaults, to check whether that cell is already saved. The events becomes this now:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"UITableViewCell"];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"UITableViewCell"];
}
cell.textLabel.text = [myArray objectAtIndex:[indexPath row]];
UIView *selectionColor = [[UIView alloc] init];
selectionColor.backgroundColor = [UIColor colorWithRed:(200/255.0) green:(200/255.0) blue:(200/255.0) alpha:0.6];
cell.selectedBackgroundView = selectionColor;
cell.textLabel.textColor = [UIColor grayColor];
if([[NSUserDefaults standardUserDefaults] valueForKey:selectedOption]) {
//Here, how can I make the cell look grayish in the background?
//If I do cell.selected = true// the cell shows a black background color
}
return cell;
}
If I call cell.selected = true the cell has a black background and not really what I am looking for.
I am at a loss as to where I should perform this customization.
Update :
Following rdelmar's answer I updated the cellForRowAtIndexPath and added the customisation code
if (myArray[indexPath.Row][selectionState] == YES){
UIView *selectionColor = [[UIView alloc] init];
selectionColor.backgroundColor = [UIColor colorWithRed:(200/255.0) green:(200/255.0) blue:(200/255.0) alpha:0.6];
cell.selectedBackgroundView = selectionColor;
cell.textLabel.textColor = [UIColor grayColor];
}else{
cell.selectedBackgroundView = nil;
cell.textLabel.textColor = [UIColor blackColor];
}
Still didn;'r resolve the issue, meaning that it would pass the verification l(selectionState == yes, and hit the code to change the color of the background view, but when displaying it would still be unchanged.
I found this method willDisplayCell, and I moved the code about customaisation there, still didn';t work !!
- (UITableViewCell *)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (myArray[indexPath.Row][selectionState] == YES){
UIView *selectionColor = [[UIView alloc] init];
selectionColor.backgroundColor = [UIColor colorWithRed:(200/255.0) green:(200/255.0) blue:(200/255.0) alpha:0.6];
cell.selectedBackgroundView = selectionColor;
}
else{
cell.selectedBackgroundView = nil;
cell.textLabel.textColor = [UIColor blackColor];
}
return cell;
}
Am I supposed to intercept another event or method?
I'm not sure you want to do this in the user defaults -- if you do, you'll have to somehow keep track of what index in your array (that supplies the data for the cells) a selected cell corresponds to.
I would change the structure of myArray to be an array of dictionaries with two keys, one for the data, and one for the selection state of the cell. You would update the value of the cell state in didSelectRowAtIndexPath and didDeselectRowAtIndexPath. Then, in cellForRowAtIndexPath, check the value of that cell state key (lets call it selectionState):
if (myArray[indexPath.Row][selectionState] == YES){
UIView *selectionColor = [[UIView alloc] init];
selectionColor.backgroundColor = [UIColor colorWithRed:(200/255.0) green:(200/255.0) blue:(200/255.0) alpha:0.6];
cell.selectedBackgroundView = selectionColor;
cell.textLabel.textColor = [UIColor grayColor];
}else{
cell.selectedBackgroundView = nil;
cell.textLabel.textColor = [UIColor blackColor];
}
Of course, you'll have to save the array itself to disk to make the cell state value persistent.
Searching thorugh some posts I have tried without success to set the background of some dynamically generated cells to transparent.
In the storyboard I have a prototype table, under which I have an image. In storyboard I have set alpha to 0.3 for the prototype table, so that the image is partially visible. It renders as desired.
The problem is that the cells add an extra layer of color, so that the image is still visible, but a little less (as if the alpha was 0.6 for example). Actually, it seems like there are three layers. The table, the cell (which darkens the bg a little) and then another small rectangle inside each row around the text (which darkens the bg even more).
I've edited the function that generates the cells like so (based on what I've understood from the threads on this topic):
NSString *cellIdentifier = #"ItemCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellIdentifier];
cell.textLabel.text = [self.labels objectAtIndex:indexPath.row]; // gets the text of the cell from an array
cell.textLabel.textColor = [UIColor colorWithRed:0.80 green:0.80 blue:0.80 alpha:1.0];
UIView *backView = [[UIView alloc] initWithFrame:CGRectZero];
backView.backgroundColor = [UIColor clearColor];
// I've also trued with = [UIColor colorWithRed:0. green:0 blue:0 alpha:0.0]
cell.backgroundView = backView;
The problem is that I still get that extra layer.
See, I have done changes somewhere in your code and try to use it.
[tableView setOpaque:NO];
NSString *cellIdentifier = #"ItemCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
//if cell is already created then reuse it no need to create unnecessarily.
if(cell= nil){//otherwise create new cells.
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellIdentifier];
UIView *backView = [[UIView alloc] initWithFrame:CGRectZero];
backView.backgroundColor = [UIColor clearColor];
cell.backgroundView = backView;
}
cell.textLabel.text = [self.labels objectAtIndex:indexPath.row];
cell.textLabel.textColor = [UIColor colorWithRed:0.80 green:0.80 blue:0.80 alpha:1.0];
[tableView setOpaque:NO];
[tableView setBackgroundColor:[UIColor clearColor]];
I got an app with UITableView. Every cell has accessory. But i cant set backgroundColor ti this cells.
I tried to set backgrounColors in this ways:
cell.contentView.backgroundColor =[UIColor redColor];
cell.backgroundView.backgroundColor = [UIColor redColor];
cell.backgroundColor = [UIColor redColor];
But only contentView work. How can i do it? Thnx
the second way cell.backgroundView.backgroundColor = [UIColor redColor]; is not that wrong. Unfortunately there is no backgroundView until you create one. You have to create an UIView and set it as background of the cell.
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell"];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:#"Cell"];
UIView *background = [[UIView alloc] initWithFrame:CGRectZero];
background.backgroundColor = [UIColor redColor];
cell.backgroundView = background;
}