I am using a UIButton of custom type and what I want is use it like a toggle switch with the change of image. Like when it is clicked if previously it was not in selected mo
I believe this post has a better solution : iPhone UIButton with UISwitch functionality
UIButton has toggling built in. There is a selected property that you can set and change the skins based on the state.
My implementation of a UIButton as a Switch.
class ButtonSwitch: UIButton {
override func sendAction(_ action: Selector, to target: Any?, for event: UIEvent?) {
if allControlEvents == .touchUpInside {
isSelected.toggle()
}
super.sendAction(action, to: target, for: event)
}
}
I made this class, changing the class to PGToggleButton in the Interface builder will do it. It uses the images for Default and Highlighted state, and has a public property to get/set the actual state.
PGToggleButton.h
@interface PGToggleButton : UIButton
@property (nonatomic, getter=isOn) BOOL on;
-(void)toggle;
@end
PGToggleButton.m
#import "PGToggleButton.h"
@interface PGToggleButton ()
@property (nonatomic, strong) UIImage *offStateImage;
@property (nonatomic, strong) UIImage *onStateImage;
-(void)touchedUpInside:(UIButton*) sender;
@end
@implementation PGToggleButton
@synthesize on = _on;
@synthesize offStateImage = _offStateImage;
@synthesize onStateImage = _onStateImage;
-(void)awakeFromNib
{
[super awakeFromNib];
self.offStateImage = [self imageForState:UIControlStateNormal];
self.onStateImage = [self imageForState:UIControlStateHighlighted];
[self addTarget:self
action:@selector(touchedUpInside:)
forControlEvents:UIControlEventTouchUpInside];
}
-(void)touchedUpInside:(UIButton*) sender
{ [self toggle]; }
-(void)toggle
{ self.on = toggle(_on); }
-(void)setOn:(BOOL) on
{
_on = on;
if (on)
[self setImage:self.onStateImage forState:(UIControlStateNormal)];
else
[self setImage:self.offStateImage forState:(UIControlStateNormal)];
}
@end
In order to do so we can use UIButton Subclass:
class UIToggleButton: UIButton {
fileprivate let onImage: UIImage
fileprivate let offImage: UIImage
fileprivate let target: AnyObject
fileprivate let onAction: Selector
fileprivate let offAction: Selector
var isOn: Bool {
didSet {
let image = isOn ? onImage : offImage
setImage(image, for: UIControlState())
}
}
init(onImage: UIImage,
offImage: UIImage,
target: AnyObject,
onAction: Selector,
offAction: Selector)
{
isOn = false
self.onImage = onImage
self.offImage = offImage
self.target = target
self.onAction = onAction
self.offAction = offAction
super.init(frame: CGRect.zero)
setImage(offImage, for: UIControlState())
addTarget(self, action: #selector(UIToggleButton.tapAction), for: .touchUpInside)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
@objc func tapAction() {
let sel = isOn ? onAction : offAction
isOn = !isOn
_ = target.perform(sel)
}
}
Change button image isn't a difficult task. And you can use some BOOL value to detect if your switch-button is in "ON" state. and in your onBtnClk method you can just change state of your BOOL value and set image for current state.
UIButton
does supports a "toggle" functionality by default. To use this you need to set a different image or even text color in Interface Builder for the State Configuration = Selected
, and use the selected property of UIButton
to toggle its state.
Code:
- (IBAction)yourButtonTouch:(UIButton *)sender {
sender.selected = !sender.selected;
if (sender.selected) {
//...
// Action to be performed when button is selected or
// the first touch
// ...
}
}