Change button's background colour - ios

I am working on a project in which I create a subclass for UIButton for setting the gradient background colour.Its working fine but now there are two tabs in a ViewController there is two buttons suppose A and B. I want to change colour of button A when I clicked on Button B same like tabs functionality:
Sub class of UIButton:
// .h_file
#import <UIKit/UIKit.h>
IB_DESIGNABLE
#interface grediantButton : UIButton
#property(nonatomic)IBInspectable UIColor*topColor;
#property(nonatomic)IBInspectable UIColor*bottomColor;
#property(nonatomic)IBInspectable CGFloat cornerRadius;
- (void)customInit;
#end
// .m file
#import "grediantButton.h"
#import "UIColor+myColor.h"
#implementation grediantButton
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
self.topColor = [UIColor clearColor];
self.bottomColor = [UIColor clearColor];
self.cornerRadius = 1;
[self customInit];
}
return self;
}
- (id)initWithCoder:(NSCoder *)aDecoder {
self = [super initWithCoder:aDecoder];
if (self) {
[self customInit];
}
return self;
}
- (void)drawRect:(CGRect)rect {
[self customInit];
}
- (void)setNeedsLayout {
[super setNeedsLayout];
[self setNeedsDisplay];
}
- (void)prepareForInterfaceBuilder {
[self customInit];
}
- (void)customInit {
self.layer.cornerRadius = self.cornerRadius;
CAGradientLayer *gradientLayer = [[CAGradientLayer alloc] init];
gradientLayer.frame = self.bounds;
gradientLayer.cornerRadius = self.cornerRadius;
gradientLayer.colors = [NSArray arrayWithObjects:(id)[self.topColor CGColor], (id)[self.bottomColor CGColor],nil];
[self.layer setMasksToBounds:YES];
[self.layer insertSublayer:gradientLayer atIndex:0];
}
My VC Code:
#pragma mark:AddnewTownshipVC
- (IBAction)addnewTownShip:(id)sender {
[self.addnewTwnBtn setTopColor:[UIColor getTabTopColor]];
[self.addnewTwnBtn setBottomColor:[UIColor getTabBotColor]];
[self.viewalltownBtn setTopColor:[UIColor blackColor]];
[self.viewalltownBtn setBottomColor:[UIColor blackColor]];
}
#pragma mark:viewalltownshipVC
- (IBAction)viewAllTownship:(id)sender {
[self.addnewTwnBtn setTopColor:[UIColor blackColor]];
[self.addnewTwnBtn setBottomColor:[UIColor blackColor]];
[self.viewalltownBtn setTopColor:[UIColor getTabTopColor]];
[self.viewalltownBtn setBottomColor:[UIColor getTabBotColor]];
}
Tabs is like:
what happen when I click on black one tab

You should set state for UIButton multiple states.
For example, set different background images for different states.
[button setBackgroundImage:naomalImage forState:UIControlStateNormal];
[button setBackgroundImage:selectedImage forState:UIControlStateSelected];
And then, just control states.
- (IBAction)addnewTownShip:(id)sender {
button.selected = YES;
}
...

Thank you all for response.
I solved my issue by change some code in my - (void)customInit method
- (void)customInit {
self.layer.cornerRadius = self.cornerRadius;
CAGradientLayer *gradientLayer = [[CAGradientLayer alloc] init];
gradientLayer.frame = self.bounds;
gradientLayer.cornerRadius = self.cornerRadius;
gradientLayer.colors = [NSArray arrayWithObjects:(id)[self.topColor CGColor], (id)[self.bottomColor CGColor],nil];
[self.layer setMasksToBounds:YES];
if([[self.layer sublayers] objectAtIndex:0]){
[self.layer replaceSublayer:[[self.layer sublayers] objectAtIndex:0] with:gradientLayer];
}else{
[self.layer insertSublayer:gradientLayer atIndex:0];
}
}
and call this method in
#pragma mark:AddnewTownshipVC
- (IBAction)addnewTownShip:(grediantButton*)sender {
[sender setTopColor:[UIColor getTabTopColor]];
[sender setBottomColor:[UIColor getTabBotColor]];
[sender customInit];
[self.viewalltownBtn setTopColor:[UIColor blackColor]];
[self.viewalltownBtn setBottomColor:[UIColor blackColor]];
[self.viewalltownBtn customInit];
// sender.isSelected = true;
// self.viewalltownBtn.isSelected = false;
}
#pragma mark:viewalltownshipVC
- (IBAction)viewAllTownship:(grediantButton*)sender {
[self.addnewTwnBtn setTopColor:[UIColor blackColor]];
[self.addnewTwnBtn setBottomColor:[UIColor blackColor]];
[self.addnewTwnBtn customInit];
[sender setTopColor:[UIColor getTabTopColor]];
[sender setBottomColor:[UIColor getTabBotColor]];
[sender customInit];
}

simply go to the attribute inspector in storyboard see in bottom in it there has background colour you can change with it.
see here :-
https://i.stack.imgur.com/A6ecY.png

Related

Objective-C highlight UIButton when selected / unselected

I have a UIButton inside a UIView, when the UIButton is selected I would like have a background colour of dark gray...is this possible?
UIView *toolbar = [[UIView alloc]initWithFrame:CGRectMake(10, 50, 40, 160)];
[toolbar setBackgroundColor:[UIColor colorWithWhite: 0.70 alpha:0.5]];
toolbar.layer.cornerRadius = 5;
UIButton *penTool = [UIButton buttonWithType:UIButtonTypeCustom];
penTool.frame = CGRectMake(5, 0, 30, 30);
[penTool setImage:[UIImage imageNamed:#"pen-but" inBundle:currentBundle compatibleWithTraitCollection:nil] forState:UIControlStateNormal];
[penTool addTarget:self action:#selector(drawButtonTapped:) forControlEvents:UIControlEventTouchUpInside];
penTool.autoresizingMask = UIViewAutoresizingNone;
penTool.exclusiveTouch = YES;
penTool.tag = 1;
[toolbar addSubview:penTool];
What if you can do this?
[button setBackgroundColor:[UIColor greenColor]
forState:UIControlStateSelected];
Let's give a great API for every state, not just selected, just like UIButton default API's ability to change image and title for every state.
BGButton.h
#import <UIKit/UIKit.h>
#interface BGButton : UIButton
- (void)setBackgroundColor:(UIColor *)backgroundColor
forState:(UIControlState)state;
#end
BGButton.m
#import "BGButton.h"
#implementation BGButton {
NSMutableDictionary *_stateBackgroundColor;
}
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
_stateBackgroundColor = [[NSMutableDictionary alloc] init];
}
return self;
}
- (void)setBackgroundColor:(UIColor *)backgroundColor {
[super setBackgroundColor:backgroundColor];
/*
* If user set button.backgroundColor we will set it to
* normal state's backgroundColor.
* Check if state is on normal state to prevent background being
* changed for incorrect state when updateBackgroundColor method is called.
*/
if (self.state == UIControlStateNormal) {
[self setBackgroundColor:backgroundColor forState:UIControlStateNormal];
}
}
- (void)setBackgroundColor:(UIColor *)backgroundColor
forState:(UIControlState)state {
NSNumber *key = [NSNumber numberWithInt:state];
[_stateBackgroundColor setObject:backgroundColor forKey:key];
}
/*
* state is synthesized from other flags. So we can't use KVO
* to listen for state changes.
*/
- (void)setSelected:(BOOL)selected {
[super setSelected:selected];
[self stateDidChange];
}
- (void)setEnabled:(BOOL)enabled {
[super setEnabled:enabled];
[self stateDidChange];
}
- (void)setHighlighted:(BOOL)highlighted {
[super setHighlighted:highlighted];
[self stateDidChange];
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
[super touchesBegan:touches withEvent:event];
[self stateDidChange];
}
- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
[super touchesMoved:touches withEvent:event];
[self stateDidChange];
}
- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
[super touchesEnded:touches withEvent:event];
[self stateDidChange];
}
- (void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
[super touchesCancelled:touches withEvent:event];
[self stateDidChange];
}
- (void)stateDidChange {
[self updateBackgroundColor];
}
- (void)updateBackgroundColor {
NSNumber *key = [NSNumber numberWithInt:self.state];
self.backgroundColor = [_stateBackgroundColor objectForKey:key];
}
#end
You can use it like the default UIButton API
BGButton *button = [[BGButton alloc] init];
[button setBackgroundColor:[UIColor greenColor]
forState:UIControlStateSelected];
[button setBackgroundColor:[UIColor blueColor]
forState:UIControlStateHighlighted];
[button setBackgroundColor:[UIColor orangeColor]
forState:UIControlStateDisabled];
Even if you use
button.backgroundColor = [UIColor redColor];
You will stay safe, it will be translated into
[button setBackgroundColor:[UIColor redColor]
forState:UIControlStateNormal];
if you have this code
[self.view addSubview:toolbar];
then just implement your button selector
-(void)drawButtonTapped:(UIButton*)button{
if (button.selected) {
button.backgroundColor = [UIColor clearColor];
button.selected = NO;
}else{
button.backgroundColor = [UIColor darkGrayColor];
button.selected = YES;
}
}
I don't know why guys would go through such trouble when we have this functionality built-in inside UIButton. All you need to do is use UIButtonTypeSystem That's all.
[UIButton buttonWithType:UIButtonTypeSystem]
Seriously, there's nothing more to it. Have a look at it's behavior in the screenshots.
INTERFACE BUILDER
RUN TIME
Want to change color, set tintColor to color of your choice.
ADVANTAGES
Covers titles with dynamic lengths. Not applied on all button width.
When selected, title color is transparent, your background can be seen through, try to use an image as a background.
Let's hope you have at least iOS7 as deployment target. UIButtonTypeSystem was introduce with revised UI design guidelines of iOS7 and has been there for almost 3 years.
Good Luck!
I used a UIButton subclass here:
#import "CustomButton.h"
#interface CustomButton()
#property (nonatomic,strong) UIColor *originalColor;
#end
#implementation CustomButton
- (void)didMoveToSuperview
{
self.originalColor = self.superview.backgroundColor;
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
self.superview.backgroundColor = [UIColor grayColor];
}
- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
CGPoint location = [touch locationInView:self];
if ([self hitTest:location withEvent:nil]) {
self.superview.backgroundColor = [UIColor grayColor];
self.originalColor = self.superview.backgroundColor;
}
else
{
self.superview.backgroundColor = self.originalColor;
}
}
- (void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
self.superview.backgroundColor = self.originalColor;
}
#end
If you subclass your button from this class, It should give you the desired effect. This also gives you the highlight effect. If you wish you can disable it by removing the line on touchesBegan.
Just try to Override the UIButton with the following Method...
- (void)setHighlighted:(BOOL)highlighted {
[super setHighlighted:highlighted];
if (highlighted) {
self.backgroundColor = [UIColor darkGray];
}
}
I think you'll be want to change the selectedImage for flexibility not the background.
Add another image (e.g. pen-but-selected) in the project. Add this 2nd line for setImage:
[penTool setImage:[UIImage imageNamed:#"pen-but-selected" inBundle:currentBundle compatibleWithTraitCollection:nil] forState:UIControlStateSelected];
- (void)drawButtonTapped:(UIButton *)button {
button.selected = !button.selected;
}
If you still want to change background color. #jamil's answer would work. Make sure the buttonImage has transparent part so you can see the buttonBackground through the buttonImage.
Try using a boolean, or some other reference to the selection state of the button. You could also make use of a 'highlightColour' as well as the 'selectedColour' if you wanted closer control (should probably do this for better UX).
bool buttonIsSelected = false;
UIColor * selectedColour = [UIColor redColor];
UIColor * defaultColour = [UIColor blueColor];
UIButton * button = [UIButton new];
button.frame = CGRectMake(0,0,100,100);
button.backgroundColor = [UIColor redColor];
[self.view addSubview:button];
[button addTarget:self action:#selector(buttonTouchUp:) forControlEvents:UIControlEventTouchUpInside];
[button addTarget:self action:#selector(buttonTouchCancel:) forControlEvents:UIControlEventTouchCancel];
[button addTarget:self action:#selector(buttonTouchDown:) forControlEvents:UIControlEventTouchDown];
-(void)buttonTouchUp:(UIButton *)button {
if (buttonIsSelected){
buttonIsSelected = false;
button.backgroundColor = defaultColour;
} else {
buttonIsSelected = true;
button.backgroundColor = selectedColour;
}
}
-(void)buttonTouchCancel:(UIButton *)button {
button.backgroundColor = defaultColour;
if (buttonIsSelected){
button.backgroundColor = selectedColour;
}
}
-(void)buttonTouchDown:(UIButton *)button {
button.backgroundColor = selectedColour;
}
-(void)OnSelect:(UIButton*)button{
if (button.selected) {
button.backgroundColor = [UIColor blue];
button.selected = NO;
}else{
button.backgroundColor = [UIColor darkGrayColor];
button.selected = YES;
}
}
use the above this will work..
-(void)buttonTapped:(UIButton*)button{
button.selected =! button.selected;
if (button.selected)
button.backgroundColor = [UIColor grayColor];
else
button.backgroundColor = [UIColor clearColor];
}

Subclassed UISegmentedControl titleTextAttributes not always applied

Scenario
I have a peculiar bug in my subclassed UISegmentedControl. What I have simply done is subclassed a UISegmentedControl to remove the default indicators of selection/deselection and used a custom CALayer as an indicator for the same. At the same time, I have modified the titleTextAttributes to complement the UI.
Problem
When the view first appears and default selected index is 0, it looks like this:
When I try to change the selectedSegmentIndex to 1 it becomes:
Where it should look like this (corrected once you change the selectedSegmentIndex a few times):
This behaviour of titleTextAttributes not changing is random, however 2 cases when this happens 100% of the time are:
View appears, and you select segment at index 1
Select last segment, and then select segment 0
I have not found subclassing notes in the UISegmentedControl official docs.
Sample project HERE.
NOTE: If you use only 2 segments, you will never the see the title of the segment at index 1 on selection.
Indeed it's a weird behavior.
You can workaround it adding an explicit call to [self setNeedsLayout] after changing the indication layer frame.
//
// RBLSegmentedControl.m
// Rabbler
//
// Created by Utkarsh Singh on 05/11/15.
// Copyright © 2015 Neeraj SIngh. All rights reserved.
//
#import "NPSegmentedControl.h"
#interface NPSegmentedControl ()
#property (nonatomic, retain) CALayer* selectedIndicationLayer;
#end
#implementation NPSegmentedControl
- (instancetype)initWithItems:(NSArray *)items {
if (self = [super initWithItems:items]) {
self.selectedIndicationLayer.frame = CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width / items.count, self.frame.size.height);
[self addTarget:self action:#selector(segmentedControlDidChange) forControlEvents:UIControlEventValueChanged];
NSDictionary* selectedAttributes = #{NSFontAttributeName:[UIFont fontWithName:#"HelveticaNeue-Light" size:15],
NSForegroundColorAttributeName:[UIColor whiteColor]};
NSDictionary* deselectedAttributes = #{NSFontAttributeName:[UIFont fontWithName:#"HelveticaNeue-Light" size:15],
NSForegroundColorAttributeName:[UIColor redColor]};
NSDictionary* highlightedAttributes = #{NSFontAttributeName:[UIFont fontWithName:#"HelveticaNeue-Light" size:15],
NSForegroundColorAttributeName:[[UIColor redColor] colorWithAlphaComponent:0.6f]};
[self setTitleTextAttributes:deselectedAttributes forState:UIControlStateNormal];
[self setTitleTextAttributes:selectedAttributes forState:UIControlStateSelected];
[self setTitleTextAttributes:highlightedAttributes forState:UIControlStateHighlighted];
}
return self;
}
- (void) segmentedControlDidChange {
[self animateSegmentSelectionChange];
if (self.delegate && [self.delegate respondsToSelector:#selector(segmentedControlDidChangeSelectedSegment:)]) {
[self.delegate segmentedControlDidChangeSelectedSegment:self.selectedSegmentIndex];
}
}
- (void) animateSegmentSelectionChange {
[UIView animateWithDuration:0.25
delay:0
options:(UIViewAnimationOptionCurveEaseInOut | UIViewAnimationOptionBeginFromCurrentState)
animations:^{
CGRect frame = self.selectedIndicationLayer.frame;
frame.origin.x = self.selectedSegmentIndex * [UIScreen mainScreen].bounds.size.width / self.numberOfSegments;
self.selectedIndicationLayer.frame = frame;
[self setNeedsLayout]; // <--
} completion:nil];
}
- (CALayer *) selectedIndicationLayer {
if (!_selectedIndicationLayer) {
_selectedIndicationLayer = [CALayer layer];
_selectedIndicationLayer.backgroundColor = [[UIColor redColor] CGColor];
_selectedIndicationLayer.cornerRadius = self.frame.size.height /2;
_selectedIndicationLayer.borderColor = [UIColor whiteColor].CGColor;
_selectedIndicationLayer.borderWidth = 1.5f;
[self.layer insertSublayer:_selectedIndicationLayer atIndex:0];
}
return _selectedIndicationLayer;
}
- (void) setSelectedSegmentIndex:(NSInteger)selectedSegmentIndex {
[super setSelectedSegmentIndex:selectedSegmentIndex];
[self animateSegmentSelectionChange];
}
- (void) setIndicatorColor:(UIColor *)indicatorColor {
self.selectedIndicationLayer.backgroundColor = indicatorColor.CGColor;
}
#end
I change your selectedIndicationLayer to this and it fix the problem
- (CALayer *) selectedIndicationLayer {
if (!_selectedIndicationLayer) {
_selectedIndicationLayer = [CALayer layer];
_selectedIndicationLayer.backgroundColor = [[UIColor redColor] CGColor];
_selectedIndicationLayer.cornerRadius = self.frame.size.height /2;
_selectedIndicationLayer.borderColor = [UIColor whiteColor].CGColor;
_selectedIndicationLayer.borderWidth = 1.5f;
}
if ([self.layer.sublayers containsObject:_selectedIndicationLayer]) {
[_selectedIndicationLayer removeFromSuperlayer];
}
[self.layer insertSublayer:_selectedIndicationLayer atIndex:0];
return _selectedIndicationLayer;
}
Just edit your following method.
- (CALayer *) selectedIndicationLayer {
if (!_selectedIndicationLayer) {
_selectedIndicationLayer = [CALayer layer];
_selectedIndicationLayer.backgroundColor = [[UIColor redColor] CGColor];
_selectedIndicationLayer.cornerRadius = self.frame.size.height /2;
_selectedIndicationLayer.borderColor = [UIColor whiteColor].CGColor;
_selectedIndicationLayer.borderWidth = 1.5f;
}
[self.layer insertSublayer:_selectedIndicationLayer atIndex:0];
return _selectedIndicationLayer;
}

Custom View in static table view released early

I'm using Interface Builder to design a static table view:
The orange bar is a custom subclassed view. Each other view is retained the same way, but for some reason only my custom view disappears. Trying to access it's properties later leads to a null for things I explicitly set, but no EXEC_BAD_ACCESS's.
Custom View code:
#import "EditableLabel.h"
#implementation EditableLabel
#synthesize font;
#synthesize maxSize;
#synthesize textColor;
- (void)awakeFromNib{
[self innerInit];
}
- (id)initWithFrame:(CGRect)frame
{
NSLog(#"got init");
self = [super initWithFrame:frame];
if (self) {
[self innerInit];
}
return self;
}
-(void)innerInit{
self.font = [UIFont systemFontOfSize:[UIFont systemFontSize]]; //default sys font, set this for pretty
self.maxSize = self.frame.size; //set this for pretty too
self.textColor = [UIColor blackColor];
self.isEditting = NO;
self.button = [UIButton buttonWithType:UIButtonTypeSystem];
self.button.frame = CGRectMake(0, 0, self.frame.size.width, self.frame.size.height);
self.button.userInteractionEnabled=YES;
self.button.hidden=NO;
self.button.titleLabel.font=font;
[self.button setTitleColor:textColor forState:UIControlStateNormal];
[self.button addTarget:self action:#selector(edit) forControlEvents:UIControlEventTouchUpInside];
[self.button setContentVerticalAlignment:UIControlContentVerticalAlignmentCenter];
[self.button setContentHorizontalAlignment:UIControlContentHorizontalAlignmentCenter];
[self addSubview:self.button];
self.editField = [[UITextField alloc] initWithFrame:self.button.frame];
self.editField.font=font;
self.editField.textColor = textColor;
self.editField.userInteractionEnabled=YES;
self.editField.hidden=YES;
self.editField.borderStyle = UITextBorderStyleRoundedRect;
[self.editField addTarget:self action:#selector(finishEditting) forControlEvents:UIControlEventEditingDidEnd];
[self.editField setContentVerticalAlignment:UIControlContentVerticalAlignmentCenter];
[self.editField setContentHorizontalAlignment:UIControlContentHorizontalAlignmentCenter];
[self addSubview:self.editField];
[self bringSubviewToFront:self.button];
}
-(void)setTextFieldDelegate:(id)viewcontroller{
self.editField.delegate = viewcontroller;
}
-(void)edit{
[self flipWithCompletionBlock:^(BOOL done){
if (done){
self.isEditting=YES;
self.button.enabled=NO;
}
}];
}
-(void)finishEditting{
[self flipWithCompletionBlock:^(BOOL done){
if (done){
self.isEditting=NO;
self.button.enabled=YES;
[self.button setTitle:self.editField.text forState:UIControlStateNormal];
}
}];
}
-(NSString*)text{
return self.button.titleLabel.text;
}
-(void)setText:(NSString*)text{
self.editField.text=text;
[self.button setTitle:text forState:UIControlStateNormal];
}
-(UIColor*)backgroundColor{
return self.button.backgroundColor;
}
-(void)setBackgroundColor:(UIColor *)backgroundColor{
[self.button setBackgroundColor:backgroundColor];
[self.editField setBackgroundColor:backgroundColor];
}
-(void)setAlignmentVertical:(UIControlContentVerticalAlignment)vert horizontalAlignment:(UIControlContentHorizontalAlignment)horiz{
[self.button setContentHorizontalAlignment:horiz];
[self.button setContentVerticalAlignment:vert];
[self.editField setContentHorizontalAlignment:horiz];
[self.editField setContentVerticalAlignment:vert];
}
- (void)flipWithCompletionBlock:(void (^)(BOOL))block{
[UIView transitionWithView:self
duration:.3
options:UIViewAnimationOptionTransitionFlipFromTop
animations:^{
if (self.isEditting){
self.editField.hidden=YES;
self.button.hidden=NO;
[self bringSubviewToFront:self.button];
}
else {
self.button.hidden=YES;
self.editField.hidden=NO;
[self bringSubviewToFront:self.editField];
}
} completion:block];
}
#end
in my view controller.h I have #property (strong, nonatomic) IBOutlet EditableLabel *userNameEditField;, and every other view is retained fine. For some reason, only my subclass is released.

NSString drawAtPoint on a subview

I have a subclassed UITextView for placeholder and background image.
Here's the code
BKCUTextView.h
#import <UIKit/UIKit.h>
#interface BKCUTextView : UITextView
- (void)setPlaceholder:(NSString *)placeholder;
- (void)setPlaceholderColor:(UIColor *)placeholderColor;
- (void)setBackgroundImage:(UIImage *)img;
#end
BKCUTextView.m
#import "BKCUTextView.h"
#interface BKCUTextView()
{
NSString * _placeholder;
UIColor * _normalColor;
UIColor * _placeholderColor;
BOOL _needToShowPlaceholder;
UIImageView * _bgImageView;
}
#end
#implementation BKCUTextView
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self)
{
[self _initEvents];
}
return self;
}
- (void)drawRect:(CGRect)rect
{
if(_needToShowPlaceholder) { [_placeholder drawAtPoint:CGPointMake(0, 0) withFont:self.font]; }
}
- (void)setTextColor:(UIColor *)textColor
{
_normalColor = textColor;
}
- (void)setPlaceholderColor:(UIColor *)placeholderColor
{
_placeholderColor = placeholderColor;
}
- (void)setPlaceholder:(NSString *)placeholder
{
_needToShowPlaceholder = YES;
_placeholder = placeholder;
}
-(void)setBackgroundImage:(UIImage *)img
{
if(_bgImageView == nil)
{
_bgImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
[self addSubview:_bgImageView];
[self sendSubviewToBack:_bgImageView];
[self bringSubviewToFront:self];
}
[_bgImageView setImage:img];
}
- (void)_initEvents
{
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(_textChanged:) name:UITextViewTextDidChangeNotification object:self];
}
-(void)_textChanged:(NSNotification *)noti
{
_needToShowPlaceholder = (self.text.length == 0);
if(_needToShowPlaceholder) { self.textColor = _placeholderColor; }
else { self.textColor = _normalColor; }
[self setNeedsDisplay];
}
instance
BKCUTextView * tv = [[BKCUTextView alloc] initWithFrame:CGRectMake(5, 55, 300, 50)];
[tv setBackgroundColor:[UIColor darkGrayColor]];
[tv setTextColor:[UIColor whiteColor]];
[tv setPlaceholderColor:[UIColor grayColor]];
[tv setPlaceholder:#"placeholder here!"];
[tv setBackgroundImage:[UIImage imageNamed:#"btn_coin_prs.png"]];
[self.view addSubview:tv];
[self.view bringSubviewToFront:tv];
each property - backgroundImage and placeholderText - works fine, but when I set them together, the placeholder is drawn under the backgroundImage.
How can I bring the text above the back image?
Try this method [self bringSubviewToFront:];
Hope it will help!

Set Selected State of CAGradient UIButton in iOS

Hi I have made a custom button in code using corner radius CAGradientLayer and border colour in one of my view controllers like the below:
phoneButton = [CustomButton buttonWithType:UIButtonTypeCustom];
phoneButton.frame = CGRectMake(6, 363, 99, 48);
phoneButton.titleLabel.font = [UIFont fontWithName:#"Futura-Medium" size:14];
phoneButton.titleLabel.shadowColor = [UIColor colorWithWhite:0.0 alpha:1.0];
phoneButton.titleLabel.shadowOffset = CGSizeMake(0, 1);
[phoneButton setTitle:#"Phone" forState:UIControlStateNormal];
[phoneButton addTarget:self action:#selector(phone) forControlEvents:UIControlEventTouchUpInside];
gradient = [CAGradientLayer layer];
gradient.frame = phoneButton.bounds;
gradient.cornerRadius = 8;
gradient.borderColor = [[UIColor whiteColor]CGColor];
gradient.borderWidth = 2.0;
gradient.colors = [NSArray arrayWithObjects:(id)[[sharedManager cellGradientEnd] CGColor], (id)[[sharedManager cellGradientStart] CGColor], nil];
[phoneButton.layer insertSublayer:gradient atIndex:0];
[self.view addSubview:phoneButton];
Now I would like to set the selected/highlighted color of the button on selection. How do I do this. I read make a UIbutton subclass and override setSelected but I dont have a clue how to do it. Here is customButton subclass.m
#import "CustomButton.h"
#implementation CustomButton
#synthesize sharedManager;
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
sharedManager = [[MySingleton alloc]init];
}
return self;
}
-(void) setHighlighted:(BOOL)highlighted {
if(highlighted) {
NSLog(#"Highlighted");
} else {
NSLog(#"Not Highlighted");
}
[super setHighlighted:highlighted];
}
-(void) setSelected:(BOOL)selected {
if(selected) {
NSLog(#"Selected");
} else {
NSLog(#"Not Selected");
}
[super setSelected:selected];
}
#end
Or just dim the button on selection would be good? I should add that the button is not in a Xib.
I figured it out just by creating a selected Gradient and unselected Gradient state of the button in subclass.m now it is all working great!
- (CustomButton *)buttonWithType:(UIButtonType)type
{
return [self buttonWithType:UIButtonTypeCustom];
}
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
}
return self;
}
- (id)initWithCoder:(NSCoder *)coder
{
//Call the parent implementation of initWithCoder
self = [super initWithCoder:coder];
//Custom drawing methods
if (self)
{
[self drawBackgroundLayer];
[self drawHighlightBackgroundLayer];
highlightBackgroundLayer.hidden = YES;
}
return self;
}
-(void)loadSingleton{
sharedManager = [[MySingleton alloc]init];
}
- (void)layoutSubviews
{
// Set gradient frame (fill the whole button))
backgroundLayer.frame = self.bounds;
// Set inverted gradient frame
highlightBackgroundLayer.frame = self.bounds;
[super layoutSubviews];
}
- (void)drawBackgroundLayer
{
[self loadSingleton];
// Check if the property has been set already
if (!backgroundLayer)
{
backgroundLayer = [CAGradientLayer layer];
backgroundLayer.cornerRadius = 8;
backgroundLayer.borderWidth = 1.5;
backgroundLayer.borderColor = [UIColor whiteColor].CGColor;
backgroundLayer.colors = [NSArray arrayWithObjects:(id)[[sharedManager cellGradientEnd] CGColor], (id)[[sharedManager cellGradientStart] CGColor], nil];
// Add the gradient to the layer hierarchy
[self.layer insertSublayer:backgroundLayer atIndex:0];
}
}
- (void)drawHighlightBackgroundLayer
{
[self loadSingleton];
if (!highlightBackgroundLayer)
{
highlightBackgroundLayer = [CAGradientLayer layer];
highlightBackgroundLayer.cornerRadius = 8;
highlightBackgroundLayer.borderWidth = 1.5;
highlightBackgroundLayer.borderColor = [UIColor whiteColor].CGColor;
highlightBackgroundLayer.colors = [NSArray arrayWithObjects:(id)[[sharedManager cellSelectedGradientEnd] CGColor], (id)[[sharedManager cellSelectedGradientStart] CGColor], nil];
[self.layer insertSublayer:highlightBackgroundLayer atIndex:1];
}
}
and setting the selected state on or off
- (void)setHighlighted:(BOOL)highlighted
{
NSLog(#"Selected");
// Disable implicit animation
[CATransaction begin];
[CATransaction setDisableActions:YES];
// Hide/show inverted gradient
highlightBackgroundLayer.hidden = !highlighted;
[CATransaction commit];
[super setHighlighted:highlighted];
}
Have you tried invoking super and then invoking setNeedsDisplay on self?
It should cause your display functionality to be invoked at the appropriate time, and in that code you should be checking for selected/highlighted.
If I understand correctly what you are trying to do, I would suggest the following approach:
move the CAGradientLayer inside of your CustomButton implementation (so it would become a CustomGradientButton);
when you want to set the selected state for the custom button, change the CAGradientLayer gradientColors by changing their saturation and brightness.
By doing this, your button will change its appearance in the selected state.
A way to modify saturation and brightness could be through this UIColor category of mine:
#interface UIColor (LighterDarkerColor)
- (UIColor*)colorWithSaturation:(float)saturationFactor
brightness:(float)brightnessFactor;
#end
#implementation UIColor (LighterDarkerColor)
- (UIColor*)colorWithSaturation:(float)saturationFactor
brightness:(float)brightnessFactor {
float hue = 0.0;
float saturation = 0.0;
float brightness = 0.0;
float alpha = 0.0;
if ([self getHue:&hue saturation:&saturation brightness:&brightness alpha:&alpha])
return [UIColor colorWithHue:hue saturation:saturation*saturationFactor
brightness:brightness*brightnessFactor alpha:alpha];
return self;
}
#end
You could do, e.g.:
UIColor* selectedColorStart = [[sharedManager cellGradientStart] colorWithSaturation:0.65 brightness:1.2];
to get a less saturated, brighter version of your cellGradientStart color. Then in your setSelected method you would modify your CAGradientLayer:
gradient.colors = [NSArray arrayWithObjects:(id)[selectedColorEnd CGColor], (id)[selectedColorStart CGColor], nil];
This approach works for me, although you need to fine-tune your selection of saturation and brightness working for your case.

Resources