Saturday, October 10, 2015

Custom UISwitch in iOS

I wanted to create Custom UISwitch in my iOS game. Initially I just waned to change size, font and color and for that I used UICustomSwitch from Hardy Macia found at here. It's quite easy to use and customisable, but then I wanted to switch to use custom image instead of standard one. For that I need to modify code a bit, below is the code which use custom image to create UISwitch. BTW this is how it looks


Header is same as original implementation, but I removed unnecessary properties and added left and right images required to display on and off images for switch.
@interface UICustomSwitch : UISlider {
    BOOL on;
    UIImageView* leftImage;
    UIImageView* rightImage;
 
    BOOL touchedSelf;
}

@property(nonatomic,getter=isOn) BOOL on;
@property (nonatomic, retain) UIImageView* leftImage;
@property (nonatomic, retain) UIImageView* rightImage;

- (void)setOn:(BOOL)on animated:(BOOL)animated;

@end
Now lets see implementation. Below is code for initialising the UISwitch with custom rect. You can also see we are adding On and Off image as left and right subview to switch.
-(id)initWithFrame:(CGRect)rect
{    
    if ((self=[super initWithFrame:rect])) {
 [self awakeFromNib];
    }
    return self;
}

-(void)awakeFromNib
{
    [super awakeFromNib];
 
    self.backgroundColor = [UIColor clearColor];
    
    [self setThumbImage:[Util imageNamed:@"switch"] 
        forState:UIControlStateNormal];
    [self setMinimumTrackTintColor:[UIColor clearColor]];
    [self setMaximumTrackTintColor:[UIColor clearColor]];
    
    self.minimumValue = 0;
    self.maximumValue = 1;
    self.continuous = NO;
 
    self.on = NO;
    self.value = 0.0;
 
    self.leftImage = [[UIImageView alloc] initWithFrame:self.frame];
    self.leftImage.image = [Util imageNamed:@"on"];
    [self addSubview: self.leftImage];
    [self.leftImage release];
    
    self.rightImage = [[UIImageView alloc] initWithFrame:self.frame];
    self.rightImage.image = [Util imageNamed:@"off"];
    [self addSubview: self.rightImage];
    [self.rightImage release];
}

Now you should be able to see UISwitch with custom images, we now need to add code required to on and off switch from code and change image accordingly.
- (void)setOn:(BOOL)turnOn animated:(BOOL)animated;
{
    on = turnOn;
 
    if (animated) {
 [UIView beginAnimations:@"UICustomSwitch" context:nil];
 [UIView setAnimationDuration:0.2];
    }
 
    if (on) {
 self.value = 1.0;
        self.rightImage.hidden = YES;
        self.leftImage.hidden = NO;
    } else {
 self.value = 0.0;
        self.rightImage.hidden = NO;
        self.leftImage.hidden = YES;
    }
 
    if (animated) {
 [UIView commitAnimations]; 
    }
}


Now finally we also have to add code to enable interaction.
- (void)endTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event
{
    [super endTrackingWithTouch:touch withEvent:event];
    touchedSelf = YES;
    [self setOn:on animated:YES];
}

- (void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event
{
    [super touchesBegan:touches withEvent:event];
    touchedSelf = NO;
    on = !on;
}

- (void)touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event
{
    [super touchesEnded:touches withEvent:event]; 
    if (!touchedSelf) {
 [self setOn:on animated:YES];
 [self sendActionsForControlEvents:UIControlEventValueChanged];
    }
}
That's it, I hope this will help.