Change the selected cell background colour using UIAppearance - ios

I need to change the selected cell background colour for all the cells in my app. As I know there is a way to use UIAppearance protocol for this purposes. Is it possible to realize this by the category for UITableViewCell?

Using appearance proxy you can colour all cells. Don't know if you can target specific category.
To do the colouring put following code in your AppDelegate.m file:
Put [self customCellBackground];
in - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions
and somewhere at the end:
- (void)customCellBackground {
UIView *cellBackgroundView =[[UIView alloc] init];
cellBackgroundView.backgroundColor = [UIColor blackColor];
[[UITableViewCell appearance] setSelectedBackgroundView:cellBackgroundView];}

As null's answer is not for selected cell backgrounds and Armands L.'s answer did not work consistently for me (selecting cells by 'user-tap' did work, but programmatical cell selection showed strange results (like sometimes the selected background was not visible, or did not fill the cell's height properly...).
I found a custom solution that worked:
Subclass UITableViewCell
Initialize self.selectedBackgroundView in init and
Add custom UIColor property with UI_APPEARANCE_SELECTOR for custom selected background color
.h file:
#property (nonatomic) UIColor* selectedCellBackgroundColor UI_APPEARANCE_SELECTOR;
.m file:
in init method(s):
self.selectedBackgroundView = [[UIView alloc] init];
and last but not least the setter function for the color:
- (void) setSelectedCellBackgroundColor:(UIColor*) color {
_selectedCellBackgroundColor = color;
self.selectedBackgroundView.backgroundColor = color;
}

You can't do this direct to UITableViewCell, but you can do it for its contentView:
[[UIView appearanceWhenContainedIn:[UITableViewCell class], nil] setBackgroundColor:[UIColor redColor]];
Note that it will change all the subViews bg color.
Another option is writing a category or subclass the UITableViewCell with UI_APPEARANCE_SELECTOR mark, check this question:
iOS: Using UIAppearance to define custom UITableViewCell color

Related

Change UITabBar tint colors in the More menu

I'm trying to change the blue colour from icons in the more menu. I tried almost everything I found on Stack Overflow, but nothing worked.
I tried this solution, but is not working.
The only option I found to change the colour was
[[UIView appearance] setTintColor:[UIColor redColor]];
but it changes all colours in the app.
The code is just a new project with storyboard, so I just added the views on the storyboard.
Thanks for helping.
Edit: After I added the code:
UIImage *myImage = [[UIImage imageNamed:#"music.png"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
self.tabBarItem = [[UITabBarItem alloc] initWithTitle:#"New Title" image:myImage selectedImage:[UIImage imageNamed:#"music.png"]];
The image is changed when the view is selected, but it's still blue.
To do what you need, you should use images by creating UITabBarItem for each controller and add an image and a selected image.
See Apple Documentation about UITabBarItem
Otherwise looks here, from #Aaron Brager :
How to set UITabBarItem's unselected tint, ***including system items*** (iOS7)
UITabBarController unselected icon image tint
Edit after seing the full code
First there is many mistakes in your project, assets should be in xcassets folder, in view didload write your code after the 'super viewDidLoad]', etc.
About your problem, in your viewDidLoad method in the FirstViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
// Your code start here, not before the super
[[UITabBar appearance] setTintColor:[UIColor redColor]];
// Get table view of more new viewController
UITableView *view =(UITableView*)self.tabBarController.moreNavigationController.topViewController.view;
view.tintColor = [UIColor redColor]; // Change the image color
if ([[view subviews] count]) {
for (UITableViewCell *cell in [view visibleCells]) {
cell.textLabel.textColor = [UIColor redColor]; // Change the text color
}
}
}
This is the Swift version of Ludovic's answer.
Keep in mind that this version only changes the tint color, since the original answer did the text color change in a very hacky way. For changing it properly, you'd have to override moreNavigationController and its cellForRowAt function.
tabBarController?.tabBar.tintColor = .red
if let moreTableView = tabBarController?.moreNavigationController.topViewController?.view as? UITableView {
moreTableView.tintColor = .red
}
to change color of this button
moreNavigationController.navigationBar.tintColor = .white

Changing Background of Edit Button - UITableView iOS7

I have a UITableView which when edited looks as follows :
Is it possible to somehow change the background behind the delete symbol so that it is not white ?
I hope this help you
UIView *cellBackView = [[[UIView alloc] initWithFrame:CGRectZero] autorelease];
cellBackView.backgroundColor = [UIColor clearColor];
cell.cellBackgroundView = backView;
The problem ist that contentView gets shifted to the right when you are in editing mode, and because of this all its subviews will move to the right as well.
If your background is an imageView you should not add is as subview to contentView, set it as backgroundView of the cell instead.
Since you can't setup backgroundView from interface builder I would recommend to create a custom subclass of your cell and put the background creation into awakeFromNib.
- (void)awakeFromNib {
[super awakeFromNib];
self.backgroundView = [[UIImageView alloc] initWithImage:...];
}

UITableViewCell selectedBackgroundView does not work

My UITableViewCells are all pre-defined "Subtitle" style. I want to set the background image for a selected cell to another picture. I tried every which way to implement this and all methods discussed on stackoverflow seem to fail.
I tried again for some other, easier way to change the selectedBackgroundView property, like:
cell.selectedBackgroundView = [[UIView alloc] initWithFrame:cell.bounds] ;
cell.selectedBackgroundView.backgroundColor = [UIColor yellowColor];
But it doesn't work as well. What's wrong with that ?
As I understand you want to set selected background image to your cell?
cell.selectedBackgroundView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"backgroundImage.png"]];
EDIT:
As i know UITableViewCell can not be highlighted after selection in such common cases:
There is somewhere set cell.selectionStyle = UITableViewCellSelectionStyleNone;
You implemented willSelectRowAtIndexPath and it returns nil;
There is set [self.tableView setAllowsSelection:NO];
May be you set self.tableView.userInteractionEnabled = NO; or cell.userInteractionEnabled = NO;
You subclassed UITableViewCell and implemented such methods not correct setSelected:animated: or setHighlighted:animated
May be share your cellForRowAtIndexPath method code to investigate the problem
You can change the highlight color in several ways.
Change the selectionStyle property of your cell. If you change it to UITableViewCellSelectionStyleGray, it will be gray.
you can also check that property in your tableView:didSelectRowAtIndexPath:
//do something like this for color
cell.selectionStyle= UITableViewCellSelectionStyleGray;
// for image
cell.selectedBackgroundView=[[UIImageView alloc]initWithImage:[UIImage imageNamed:#"imageName"]];
Change the selectedBackgroundView property. Actually what creates the blue gradient is a view. You can create a view and draw what ever you like, and use the view as the background of your table view cells.
best of luck..
In my case the problem appeared after compiling on Xcode 13 - sdk iOS 15+
with any change to the code. Eventually I subclassed the cell and add the code:
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
[super setSelected:selected animated:animated];
[self.contentView insertSubview:self.selectedBackgroundView
atIndex:0];
self.selectedBackgroundView.hidden = !selected;
}

iOS - Custom UITableViewCell subviews within selectedBackgroundView

I have set up a custom UITableViewCell with multiple labels and an image, and I've (finally) got it to look how I want it to look.
I can't seem to figure out how to get the selection to look how I want it to look, however. I have implemented the setSelected method, which allows me to change the background color just fine, but what I would really like is to set the background color to black and display a colored rectangle on the left-hand side of the selected cell (10 pixels wide and the height of the cell).
The colored box would be a color set programmatically, so although I could easily set the selectedBackgroundView to be a UIImageView, this will not work in this case.
The following code will not display the selectedViewColor UIView at all when the cell is selected:
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
UIView *selectedView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.selectedBackgroundView.bounds.size.width, self.selectedBackgroundView.bounds.size.height)];
[selectedView setBackgroundColor:[UIColor blackColor]];
UIView *selectedView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 10, self.selectedBackgroundView.bounds.size.height)];
[selectedViewColor setBackgroundColor:[UIColor redColor]];
[selectedView addSubview:selectedViewColor];
self.selectedBackgroundView = selectedView;
[super setSelected:selected animated:animated];
}
This code seems pretty basic, so I assume there is an issue with displaying any type of subview within the selectedBackgroundView.
Any alternatives or advice would be greatly appreciated.
There's a few things that could be done better with this code. Reinitialising two views in the setSelected method is pretty inefficient. You're actually blanking out everything in the cell when you select it with this code (which I'm guessing is not what you want). And finally, you're treating selectedBackgroundView as if it's the only view that gets displayed when you select the cell (according to Apple's documentation, it is displayed over the backgroundView).
Try the following (Edited) -
Put this code where you create the cell (presumably, cellForRowAtIndexPath:)
UIView* container = [[UIView alloc] initWithFrame:CGRectMake(0, 0, cell.backgroundView.bounds.size.width, cell.backgroundView.bounds.size.height)]; // we need this because in cells, the background views always take up the maximum width, regardless of their frames.
container.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0]; // make it transparent - we only want the square subview to be seen.
UIView *selectedViewColor = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 10, self.selectedBackgroundView.bounds.size.height)];
[selectedViewColor setBackgroundColor:[UIColor redColor]];
[container addSubview:selectedViewColor]
cell.selectedBackgroundView = container;
This will make your red square appear when (and only when) the cell is selected, over the other views in the cell. From Apple's docs:
UITableViewCell adds the value of this property as a subview only when the cell is selected. It adds the selected background view as a subview directly above the background view (backgroundView) if it is not nil, or behind all other views.
Second, use the following code in your cell:
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
[super setSelected:selected animated:animated];
if(selected == YES)
{
self.backgroundView.backgroundColor = [UIColor blackColor];
}
else
{
self.backgroundView.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0] // replace this with whatever's appropriate - a return to the unselected state.
}
}
This will ensure that your background turns black when the cell is selected (without otherwise interfering with what's displayed. Hopefully these changes should also resolve the issue you're having.
In addition to Xono's answer above, following up on his comment on the answer above:
One thing I've come across a couple of times while researching this subject is a possibility that the code behind UITableViewCell may actually set the backgroundColor of all subviews to transparent when a cell is selected.
It does indeed do this if your cell's SelectionStyle is anything but None. And it does it in both the setHighlighted and setSelected calls of UITableViewCell.
My first solution was to subclass UITableViewCell and override both these methods, not calling the base class method and doing my own animations. This is not ideal as your now re-implenting (probably badly) standard iOS animations.
Looking into it further though, the standard methods animate the opacity of the whole view, not the subviews (they only set the color of the subviews). So the best approach is to still call the base class methods, and then just re-set your subview colors back to whatever they should be. Even though your setting them instantaneously, because their superview is still animating its opacity, it still fades in and out correctly:
public override void SetHighlighted(bool highlighted, bool animated)
{
base.SetHighlighted(highlighted, animated);
SelectedBackgroundView.Subviews[0].BackgroundColor = SelectionColor;
}
public override void SetSelected(bool selected, bool animated)
{
base.SetSelected(selected, animated);
SelectedBackgroundView.Subviews[0].BackgroundColor = SelectionColor;
}
This is c# MonoTouch code, but it applies equally well to obj-c.
Note that in my case I always have exactly 1 subview, hence the hardcoded 0 indexer. This may differ depending on your view structure.
You can override method "setBackgroundColor" for your subviews and add another method with the same functionality. At this case UITableCell won't be able to change backgroundColor after selection.
- (void)setBackgroundColor:(UIColor *)backgroundColor {
}
- (void)setColor:(UIColor *)color {
[super setBackgroundColor:color];
}
Basing on #Xono 's answer, I made this solution to the problem:
Inside of the initWithStyle:reuseIdentifier: method I added a separator view:
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
CGRect selectionViewFrame = self.contentView.bounds;
UIView *selectionView = [[UIView alloc] initWithFrame:selectionViewFrame];
[selectionView setBackgroundColor:[UIColor colorWithWhite:1. alpha:0.65]];
self.selectedBackgroundView = selectionView;
self.vwSelectedSeparator = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.contentView.frame.size.width, 1.)];
[self.vwSelectedSeparator setBackgroundColor:[UIColor colorWithHexString:#"aaa"]];
[self.vwSelectedSeparator setAutoresizingMask:UIViewAutoresizingFlexibleWidth];
[selectionView addSubview:self.vwSelectedSeparator];
[self setAutoresizingMask:UIViewAutoresizingFlexibleWidth];
}
return self;
}
And then in setSelected:animated: method I added these lines:
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
if (selected) {
[self.vwSelectedSeparator setBackgroundColor:[UIColor colorWithHexString:#"aaa"]];
}
}
Works like a charm for both ios6 and ios7 for me. I hope this helps.

Change background on a UITableView embedded in a UIViewController on iOS 5

I am trying to change the grey gradient background on an embedded UITableView to the color I have set on the parent view in the Storyboard.
I have been looking around, and found the following threads:
Change iPhone tableview (style grouped) background color while preserving texture
How can I set the background of UITableView (the tableview style is “Grouped”) to use an image?
UITableView backgroundColor always gray on iPad
I have an IBOutlet in the parent controller connecting the two views.
My implementation looks as follows:
- (void)viewDidLoad {
[super viewDidLoad];
[activeShipmentsTable setBackgroundView:nil];
[activeShipmentsTable setBackgroundView:[[[UIView alloc] init] autorelease]];
[activeShipmentsTable setBackgroundColor:UIColor.clearColor];
}
What am I doing wrong?
Thanks.
Try setting et the background color on the table's background view, not the table itself.
UIView *view = [[[UIView alloc] init] autorelease];
view.backgroundColor = [UIColor redColor];
self.tableView.backgroundView = view;

Resources