开发者

How to use a UIButton as a toggle switch

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 mode it should go in selected mode or otherwise vice-a-versa. Also it开发者_StackOverflow中文版 will have a different image and when it is selected it will have a different image when it is not.

I am not able to do it programatically, is there any good easy way to do this.


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.


In your header file add:

IBOutlet UIButton *toggleButton;
BOOL toggleIsOn;

@property (nonatomic, retain) IBOutlet UIButton *toggleButton;

In the implementation:

- (IBACtion)toggle:(id)sender
{
  if(toggleIsOn){
    //do anything else you want to do.
  }
  else {
    //do anything you want to do.
  }
  toggleIsOn = !toggleIsOn;
  [self.toggleButton setImage:[UIImage imageNamed:toggleIsOn ? @"on.png" :@"off.png"] forState:UIControlStateNormal];
}

then link your button with the IBActions and the IBOutlet and initialize toggleIsOn to NO.


In the interface:

@interface TransportViewController : UIViewController {

    UIButton *button;
}
@property(nonatomic, retain) UIButton *button;

In the implementation:

- (void)loadView {

[super loadView];

    ...

    [self setButton:[UIButton buttonWithType:UIButtonTypeCustom]];
    [button addTarget:self action:@selector(onClick:) forControlEvents:UIControlEventTouchUpInside];
    [button setImage:[UIImage imageNamed:@"image1"] forState:UIControlStateNormal];
    [button setImage:[UIImage imageNamed:@"image2"] forState:UIControlStateSelected];
}

- (void) onClick:(UIButton *)sender {

    [sender setSelected:!sender.selected];
}


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
        // ... 

    }
}


For Swift 3

@IBAction func playPause(sender : UIButton){


   if sender.isSelected {
      player.pause()
   }else{
      player.play()
  }
  sender.isSelected = !sender.isSelected
}


- (IBAction)buttonTapped:(UIButton *)sender {


   //first time sender.selected is No
    if (sender.selected) {
        //code here
        sender.selected=NO;
    }
    else{
    //code here
        sender.selected=YES;
    }
}


The only problem here is that you have to use 2 images to achieve toggling. Also you can't use highlighted property because of UIButton (UIControl) automatically sets this property under the hood, to be exact in touchBegan:, touchMoved:, etc. methods. The best way I offer is to simple use subclassing:

@interface ToggleButton : UIButton

@end

@implementation ToggleButton

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
    [super touchesBegan:touches withEvent:event];
    self.highlighted = self.selected = !self.selected;
}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
    [super touchesMoved:touches withEvent:event];
    self.highlighted = self.selected;
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
    [super touchesEnded:touches withEvent:event];
    self.highlighted = self.selected;
}

- (void)setSelected:(BOOL)selected{
    [super setSelected:selected];
    self.highlighted = selected;
}

@end

This is quite enough to make your toggle working


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)
    }
}


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)
  }
}


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.


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
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜