Avoid UIButton inverted colours when selected - ios

I have a UIButton with a different image for normal and selected state. Also I need to change the tint of the button depending on the app's theme.
But when I set the button to selected State to switch the image, it inverts its colours.
- (void)setLike:(BOOL)selected {
self.likeButton.selected = selected;
if (selected) {
self.likeButton.tintColor = [Theme getTintColor];
} else {
self.likeButton.tintColor = [Theme getLightColor];
}
}
Normal State
Actual Selected
Desired Selected
Note: I can't change the image because this code is used in another places in the app with different selected and unselected images.
- (void)setLike:(BOOL)selected {
if (selected) {
[self.likeButton setImage:[UIImage imageNamed:#"Liked"] forState:UIControlStateNormal];
self.likeButton.tintColor = [Theme getTintColor];
} else {
[self.likeButton setImage:[UIImage imageNamed:#"Like"] forState:UIControlStateNormal];
self.likeButton.tintColor = [Theme getLightBaseColor];
}
}

In Interface Builder find your button, and change it's Type from System to Custom. This should remove the effect of enlarging&reversing image for selected status.
Open your Assets file where both images for Normal and Selected statuses are defined. Set the Render As for Normal image to Original Image, and for Selected image to Template Image. This should result in applying your app's default tint only to selected status.

I would try to keep track of the state in a property and then have an additional properties for returning the correct image for the current state. You can then set these upon viewDidLoad or viewDidAppear.
I don't know your exact situation so here is an example.
Example:
#property (nonatomic) BOOL isLiked;
...
- (void)viewDidAppear {
// likeButton
[self.likeButton setBackgroundImage:[self imageForCurrentState] forState:UIControlStateNormal];
}
...
- (UIImage)imageForCurrentState {
if (isLiked) {
return [UIImage imageNamed:#"Liked"];
} else {
return [UIImage imageNamed:#"Like"];
}
}

Related

Blue image for buttons

I have buttons in my costoum cell , and i'm setting the images from code . But something strange is happening. My images are blue .
BOOL isTheObjectThere = [self.favoriteArry containsObject:self.tableData[indexPath.row]];
if (isTheObjectThere==TRUE) {
cell.favBtn.hidden = NO;
[cell.favBtn setImage:[UIImage imageNamed:#"favorite_star.png"] forState:UIControlStateNormal];
cell.favBtn.tag = indexPath.row;
[cell.favBtn addTarget:self action:#selector(unfavoriteBtn:) forControlEvents:UIControlEventTouchUpInside];
As mentioned in the comments, you should create the button with a UIButtonTypeCustom type in case it's currently set to UIButtonTypeSystem and you want to avoid the tint color from taking over. Alternatively, you can set the image rendering mode to make sure you always get the original image and not a tinted one:
[[UIImage imageNamed:#"favorite_star.png"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]

iOS - How to Detect if Button is Pressed Twice

I have a button that you can press and the text of that button will change. I want to be able to detect when the user clicks the button again, so that the button text will change back to its original text. How would I be able to do that? Here is the code I have so far.
//Set Text and alignment for the buttons
[nocavities setTitle:#"No cavities\n5 points" forState:UIControlStateNormal];
nocavities.titleLabel.textAlignment = NSTextAlignmentCenter;
-(IBAction)nocavitiesaction:(id)sender {
[sender setTitle:#"Whenever you visit our office cavity-free, you will receive 5 points!" forState:UIControlStateNormal];
}
I feel like in the IBAction I should change the state to
UIControlStateNormalPressed
but I'm not sure.
You can set a counter inside the IBAction
Something like this:
-(IBAction)nocavitiesaction:(id)sender {
static int count = 0;
count ++;
if(count % 2 != 0){
//Set title 1
}else{
//Set title 2
}
}
Open xib file and select the button.
Under the attributes inspector you will find "State Config", select "Default" from dropdown.
Change the title of button to "No cavities\n5 points"
Change State Config to "Selected"
Change title to "Whenever you visit our office cavity-free, you will receive 5 points!"
Now toggle these titles by.
- (IBAction)nocavitiesaction:(id)sender
{
UIButton * button = sender;
button.selected = !button.selected;
}
like this.
declare global int flag=1;
-(IBAction)methodName:(id)sender
{
if(flag==1)
{
//set title 1
flag=2;
}
else
{
//set title 2
flag=1
}
}
There's no UIControlStateNormalPressed state, but there is a UIControlStateSelected. You can set a title for both the selected and normal states, then manually set the UIButton to its selected state like so:
- (void)viewDidLoad {
[self.button setTitle:#"Whenever you visit our office cavity-free, you will receive 5 points!" forState:UIControlStateNormal];
[self.button setTitle:#"No cavities\n5 points" forState:UIControlStateSelected];
}
- (IBAction)nocavitiesaction:(UIButton*)sender {
sender.selected = !sender.selected;
}
Note: I've changed the parameter from id to UIButton to avoid having to convert id to UIButton to check its selected state. And the UIButton should be of type "Custom" if you'd like to prevent the background tint while selected.

iOS seating plan layout

I am creating an iOS app with a seating plan layout.
Trying to use an object-oriented approach, I created a class for TableLayoutObjects as they have different properties.
And to lay these TableLayoutObjects out on the screen I am representing them as UIButtons that are created as I loop through the array of TableLayoutObjects.
- (void) loadTables
{
for (TableLayoutObjects *layoutObjs in arrTableLayoutObjects)
{
if ([layoutObjs.shape isEqualToString:#"r"]) {
// rectangle
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
......
if(layoutObjs.isInteractable) {
[button addTarget:self action:#selector(tableTouchedDown:) forControlEvents:UIControlEventTouchDown];
[button addTarget:self action:#selector(tableTouchedUpInside:) forControlEvents:UIControlEventTouchUpInside];
}
} else {
// text only. use label
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(layoutObjs.posX, layoutObjs.posY, layoutObjs.width, layoutObjs.height)];
......
}
}
}
My event handlers look like the below for now.
// reverts back to original color and perform other instructions
- (void) tableTouchedUpInside:(UIButton *) button
{
button.layer.backgroundColor = [UIColor colorWithWhite:0.2f alpha:.5f].CGColor;
}
My question is: how do I identify the UIButtons to their TableLayoutObjects? In the event handler after I change the colour of the button, I will also want to get or set some properties of the selected TableLayoutObjects. How can I do that?
I think your example is a perfect fit for implementing a UICollectionView. Solution with the buttons is less clean and more complex.
You can set the tag of the button to the index into the arrTableLayoutObjects array of the associated item.
Alternatively, create a custom class which takes the table as a parameter and is the target of the button. This object now has direct access to the button and the table item.

How to make Uibutton selected

I have a UIButton which remains selected when I select that button. Here is my code:
- (IBAction)cloudclick:(UIButton *)sender {
UIImage *bgImage = [UIImage imageNamed:#"black_cloud.png"];
UIButton *tmpButton = (UIButton *)[self.view viewWithTag:sender.tag];
[tmpButton setBackgroundImage:bgImage forState:UIControlStateSelected];
}
But it does not remain selected when I click the button. It changes the background but it does not remain as selected button.
you have to write one line after your code
- (IBAction)cloudclick:(UIButton *)sender {
...
[tmpButton setSelected:YES];
}
use this line of code
sender.selected=!sender.selected;
and set different image for diff states at the time alloc if you are making button from code otherwise set images from xib's.
The various states: UIControlStateNormal, UIControlStateSelected, and (UIControlStateSelected | UIControlStateHighlighted) are all actually distinct. If you want your shadowImage to apply both in the (only) highlighted state and in the highlighted+selected state, you must also set:
[button setBackgroundImage: bgImage forState:(UIControlStateHighlighted | UIControlStateSelected)]
in Swift 5
sender.isSelected.toggle()

Change Color of MPVolumeView Route Button iOS 7

I am designing a Music app for iOS 7 and I want to put the "AirPlay" route selector button directly in my app. I am able to get the button placed just fine, however it doesn't show up because the icon is white and my background is white.
Is there a way to change the color of the Route Button?
Here is the code I'm using to create the button.
self.airPlayButton = [[MPVolumeView alloc] initWithFrame:CGRectZero];
self.airPlayButton.showsVolumeSlider = NO;
[self.airPlayButton sizeToFit];
self.airPlayButton.backgroundColor = [UIColor myGreenColor];
[self addSubview:self.airPlayButton];
Basically the picture below is what I want, except I want the icon green instead of just it's background.
in reviewing Adams answer I like more clarity in that task. So I safe-guarded that code a bit:
Objective-C:
for( UIView *wnd in volumeView.subviews ) {
if( [wnd isKindOfClass:[UIButton class] ]) {
UIButton *button = (UIButton*) wnd;
UIImage *img = button.currentImage;
UIImage *img2 = [img imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
[volumeView setRouteButtonImage: img2 forState:UIControlStateNormal];
break;
}
}
Swift:
for view in volumeView.subviews {
if view.isKindOfClass(UIButton) {
let buttonOnVolumeView : UIButton = view as! UIButton
volumeView.setRouteButtonImage(buttonOnVolumeView.currentImage?.imageWithRenderingMode(.AlwaysTemplate), forState: .Normal)
break;
}
}
Now it reacts on the tintColor property of volumeView and if Apple decides to add another button or change the sequence this code will still work.
To expand on lanbo's answer, you can also get the original image of the Route Button and create a copy that uses the UIImageRenderingMode.AlwaysTemplate rendering mode. That way it heeds the current tintColor.
In Swift:
let volumeView = MPVolumeView()
if let routeButton = volumeView.subviews.last as? UIButton,
let routeButtonTemplateImage = routeButton.currentImage?.imageWithRenderingMode(.AlwaysTemplate)
{
volumeView.setRouteButtonImage(routeButtonTemplateImage, forState: .Normal)
}
Create your own image and Try
setRouteButtonImage:forState:
Assigns a button image to the specified control states.
- (void)setRouteButtonImage:(UIImage *)image forState:(UIControlState)state
Parameters
image - The image to associate with the specified states.
state - The control state with which to associate the image.
Discussion
Use this to customize the appearance of the route button when it is enabled, disabled, highlighted, and so on.
Available in iOS 6.0 and later.

Resources