I'd like my button to remain highlighted after the user taps it. If the user taps the button again I'd like it to become de-selected/unhighlighted. I'm not sure how to go about doing this in swift. I'm currently setting the button highlight image and selected image to the same .png using interface builder.
When I run the app and tap the button, it changes to my highlight image for as long as my finger remains on the button.
Use below code
declare isHighLighted as instance variable
//write this in your class
var isHighLighted:Bool = false
override func viewDidLoad() {
let button = UIButton(type: .system)
button.setTitle("Your title", forState: UIControlState.Normal)
button.frame = CGRectMake(0, 0, 100, 44)
self.view.addSubview(button as UIView)
button.addTarget(self, action: "buttonClicked:", forControlEvents: UIControlEvents.TouchUpInside)
}
func buttonClicked(sender:UIButton)
{
dispatch_async(dispatch_get_main_queue(), {
if isHighLighted == false{
sender.highlighted = true;
isHighLighted = true
}else{
sender.highlighted = false;
isHighLighted = false
}
});
}
I would recomend to use selected state instead of highlighted the below code demonstarate with selected state
override func viewDidLoad() {
let button = UIButton(type: .system)
button.setTitle("Your title", forState: UIControlState.Normal)
button.frame = CGRectMake(0, 0, 100, 44)
self.view.addSubview(button as UIView)
//set normal image
button.setImage(normalImage, forState: UIControlState.Normal)
//set highlighted image
button.setImage(selectedImage, forState: UIControlState.Selected)
button.addTarget(self, action: "buttonClicked:", forControlEvents: UIControlEvents.TouchUpInside)
}
func buttonClicked(sender:UIButton)
{
sender.selected = !sender.selected;
}
func buttonPressed(_ sender: UIButton) {
// "button" is a property
if button.isSelected {
button.setImage(UIImage(named: "filled-heart"), for: .normal)
button.isSelected = false
}else {
button.setImage(UIImage(named: "empty-heart"), for: .selected)
button.isSelected = true
}
}
func highlightButton(button: UIButton) {
button.highlighted = true
}
#IBAction func touched(sender: UIButton) {
let timer = NSTimer.scheduledTimerWithTimeInterval(0.0, target: self, selector: Selector("highlightButton(sender)"), userInfo: nil, repeats: true)
}
this one worked fine for me!
func buttonColorChanger(sender : UIButton ) {
if button.isSelected == false
{
button.backgroundColor = UIColor.purple
print("selected")
button.setTitle("selected", for: .normal)
button.setTitleColor(UIColor.white, for: .normal)
button.isSelected = true
}else{
button.backgroundColor = UIColor.white
print("unselected")
button.isSelected = false
}
}
Swift 5:
#IBAction func toggleButton(_ sender: UIButton) {
sender.isSelected = !sender.isSelected
}
Related
Hey I'm new in iOS Development, I have a problem to make two button selected and unselected state and then store value of a gender. I want when user choose gender the other gender will be disable. Can anyone help me?
My button code
let menButton: UIButton = {
let button = UIButton(type: .system)
button.setTitle("Men", for: .normal)
button.setTitleColor(.white, for: .normal)
button.backgroundColor = .yellow
button.isSelected = false
button.isEnable = true
button.addTarget(self, action: #selector(handlePickGender), for: .touchUpInside
return button
}()
let womenButton: UIButton = {
let button = UIButton(type: .system)
button.setTitle("Women", for: .normal)
button.setTitleColor(.white, for: .normal)
button.backgroundColor = .blue
button.isSelected = false
button.isEnable = true
button.addTarget(self, action: #selector(handlePickGender), for: .touchUpInside
return button
}()
try this:
#objc func handlePickGender(sender: UIButton) {
menButton.setTitleColor(UIColor.yellow, for: .normal)
womenButton.setTitleColor(UIColor.yellow, for: .normal)
sender.setTitleColor(UIColor.blue, for: .normal)
//store gender
let selectedGender = sender.title(for: .normal)
}
First, create enum for Gender and add the Male and Female as the cases for that enum.
enum Gender {
case male
case female
}
Have the switch for toggling the UIButton states.
func chooseGender(_ gender: Gender) {
switch gender {
case .male:
// code for select and unselect
case .female:
// code for select and unselect
}
}
From the UIButton, use the isEnabled property for enable and disable.
If you are trying to create toggle buttons.
you can set button image for state.
button.setImage(UIImage(named: "unselected"), for: .normal)
button.setImage(UIImage(named: "selected"), for: .selected)
#IBAction func buttonPressed(sender: UIButton) {
button.selected = !button.selected
}
OR you can set background color for button
#IBAction func buttonPressed(sender: UIButton) {
button.selected = !button.selected
if button.selected {
button.backgroundColor = .blue
} else {
button.backgroundColor = .clear
}
}
I'm looking to implement a button that can be used as a tickbox and enablers the user to toggle the tickbox in an on/off fashion (unticked/ticked). Currently I've set up my button using the attributes inspector including the 'Title' as "X" and the 'Text Color' is red.
Once loaded the button appears a red "X", once tapped it turns to a green tick.
My question is... how do you enable the button to be tapped again to revert back to the red X (it's original state), an continue in a loop whenever tapped?
#IBAction func check2(_ sender: UIButton) {
sender.setTitle("✓", for: .normal)
sender.setTitleColor(UIColor.green, for: UIControlState.normal)
}
Thank you
Track the state with a variable and update the appearance based on the state:
class ViewController: UIViewController{
#IBOutlet weak var button: UIButton!
var isChecked = true
#IBAction func check2(_ sender: UIButton) {
isChecked = !isChecked
if isChecked {
sender.setTitle("✓", for: .normal)
sender.setTitleColor(.green, for: .normal)
} else {
sender.setTitle("X", for: .normal)
sender.setTitleColor(.red, for: .normal)
}
}
}
Updated for Swift 3
lazy var toggleBT: UIButton = {
let button = UIButton()
button.frame = CGRect(x: 40, y: 100, width: 200, height: 40)
button.backgroundColor = .orange
button.isSelected = false // optional(because by default sender.isSelected is false)
button.setTitle("OFF", for: .normal)
button.setTitleColor(.white, for: .normal)
button.titleLabel?.font = .boldSystemFont(ofSize: 14)
button.addTarget(self, action: #selector(handleToggleBT), for: .touchUpInside)
return button
}()
func handleToggleBT(sender: UIButton) {
sender.isSelected = !sender.isSelected
if sender.isSelected {
print(sender.isSelected)
toggleBT.setTitle("ON", for: .normal)
}
else {
print(sender.isSelected)
toggleBT.setTitle("OFF", for: .normal)
}
} // don't forget to add this button as a subView for eg. view.addSubview(toggleBT)
Updated code for swift5
#IBAction func check2(_ sender: UIButton) {
sender.isSelected = !sender.isSelected //By default sender.isSelected is false
if sender.isSelected {
sender.setTitle("✓", for: .normal)
sender.setTitleColor(UIColor.green, for: .normal)
} else {
sender.setTitle("x", for: .normal)
sender.setTitleColor(UIColor.red, for: .normal)
}
}
how can I add action to button programmatically. I need to add show action to buttons in mapView. thanks
let button = UIButton(type: UIButtonType.Custom) as UIButton
You can go for below code
`
let btn: UIButton = UIButton(frame: CGRect(x: 100, y: 400, width: 100, height: 50))
btn.backgroundColor = UIColor.green
btn.setTitle("Click Me", for: .normal)
btn.addTarget(self, action: #selector(buttonAction), for: .touchUpInside)
btn.tag = 1
self.view.addSubview(btn)
for action
#objc func buttonAction(sender: UIButton!) {
let btnsendtag: UIButton = sender
if btnsendtag.tag == 1 {
dismiss(animated: true, completion: nil)
}
}
let button = UIButton(type: UIButtonType.Custom) as UIButton
button.addTarget(self, action: "action:", forControlEvents: UIControlEvents.TouchUpInside)
//then make a action method :
func action(sender:UIButton!) {
print("Button Clicked")
}
You need to add a Target to the button like Muhammad suggest
button.addTarget(self, action: "action:", forControlEvents: UIControlEvents.TouchUpInside)
But also you need a method for that action
func action(sender: UIButton) {
// Do whatever you need when the button is pressed
}
For swift 5 users can do by this simple way
cell.followButton.tag = 10
cell.followButton.addTarget(self, action: #selector(buttonAction), for: .touchUpInside)
#objc func buttonAction(sender: UIButton!) {
let id = sender.tag
print(id)
}
in addition to the above, the new ios14 introduce
if #available(iOS 14.0, *) {
button.addAction(UIAction(title: "Click Me", handler: { _ in
print("Hi")
}), for: .touchUpInside)
} else {
// Fallback on earlier versions
}
override func viewDidLoad() {
super.viewDidLoad()
let btn = UIButton()
btn.frame = CGRectMake(10, 10, 50, 50)
btn.setTitle("btn", forState: .Normal)
btn.setTitleColor(UIColor.redColor(), forState: .Normal)
btn.backgroundColor = UIColor.greenColor()
btn.tag = 1
btn.addTarget(self, action: "btnclicked:", forControlEvents: .TouchUpInside) //add button action
self.view.addSubview(btn)
}
For Swift 4 use following:
button.addTarget(self, action: #selector(AwesomeController.coolFunc(_:)), for: .touchUpInside)
//later in your AswesomeController
#IBAction func coolFunc(_ sender:UIButton!) {
// do cool stuff here
}
I was able to create a UIBarButton item that can go back programmatically using the following code:
func backAction() -> Void {
self.navigationController?.popViewControllerAnimated(true)
}
override func viewDidLoad() {
super.viewDidLoad()
let backButton = UIBarButtonItem(title: "Back", style: UIBarButtonItemStyle.Plain, target: self, action: "backAction")
self.navigationItem.leftBarButtonItem = backButton
}
The problem is that the back button doesn't have the left pointing arrow:
Is there a way to make it look like a regular back button with the arrow like this:
I would also like to know if there is a way to make the button title names as the title of the previous view controller, if that's possible.
Thanks
Below is the code by using UIButton with image you can add it as a customView for UIBarButtonItem
override func viewDidLoad() {
super.viewDidLoad()
var backbutton = UIButton(type: .Custom)
backbutton.setImage(UIImage(named: "BackButton.png"), forState: .Normal) // Image can be downloaded from here below link
backbutton.setTitle("Back", forState: .Normal)
backbutton.setTitleColor(backbutton.tintColor, forState: .Normal) // You can change the TitleColor
backbutton.addTarget(self, action: "backAction", forControlEvents: .TouchUpInside)
self.navigationItem.leftBarButtonItem = UIBarButtonItem(customView: backbutton)
}
func backAction() -> Void {
self.navigationController?.popViewControllerAnimated(true)
}
Download Link
For setting the title of backbutton with the previous view controller title you have to pass the Title as a String while presenting the controller make change to above code as
var titleStrFromPreviousController: String // This value has to be set from previous controller while presenting modal controller
backbutton.setTitle(titleStrFromPreviousController, forState: .Normal)
This may help.
Swift 3
override func viewDidLoad() {
super.viewDidLoad()
addBackButton()
}
func addBackButton() {
let backButton = UIButton(type: .custom)
backButton.setImage(UIImage(named: "BackButton.png"), for: .normal) // Image can be downloaded from here below link
backButton.setTitle("Back", for: .normal)
backButton.setTitleColor(backButton.tintColor, for: .normal) // You can change the TitleColor
backButton.addTarget(self, action: #selector(self.backAction(_:)), for: .touchUpInside)
self.navigationItem.leftBarButtonItem = UIBarButtonItem(customView: backButton)
}
#IBAction func backAction(_ sender: UIButton) {
let _ = self.navigationController?.popViewController(animated: true)
}
Updated for Swift 4.2 - thanks to sam bing and silentbeep
Made some modifications on some colors and action's selector.
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = .blue
self.navigationItem.title = title
self.navigationController?.navigationBar.barTintColor = .white
self.navigationItem.leftBarButtonItem = UIBarButtonItem(customView: makeBackButton())
}
func makeBackButton() -> UIButton {
let backButtonImage = UIImage(named: "backbutton")?.withRenderingMode(.alwaysTemplate)
let backButton = UIButton(type: .custom)
backButton.setImage(backButtonImage, for: .normal)
backButton.tintColor = .blue
backButton.setTitle(" Back", for: .normal)
backButton.setTitleColor(.blue, for: .normal)
backButton.addTarget(self, action: #selector(self.backButtonPressed), for: .touchUpInside)
return backButton
}
#objc func backButtonPressed() {
dismiss(animated: true, completion: nil)
// navigationController?.popViewController(animated: true)
}
You can do by embedding your view in a navigation controller.
Here is an image showing how to do that:
Hope it helps :D
For future searches, I wanted to add that you can now use the default icon by this code:
override public func viewDidLoad() {
// create chevron image
let config = UIImage.SymbolConfiguration(pointSize: 25.0, weight: .medium, scale: .medium)
let image = UIImage(systemName: "chevron.left", withConfiguration: config)
// create back button
let backButton = UIButton(type: .custom)
backButton.addTarget(self, action: #selector(self.close(_:)), for: .touchUpInside)
backButton.setImage(image, for: .normal)
backButton.setTitle("Back", for: .normal)
backButton.setTitleColor(backButton.tintColor, for: .normal)
self.navigationItem.leftBarButtonItem = UIBarButtonItem(customView: backButton)
}
#IBAction func close(_ sender: UIButton) {
self.navigationController?.dismiss(animated: true, completion: nil)
}
The first answer works great however the image is a bit too big so use the preview and scale it down to width:13 and height: 22, also set its rendering mode to .alwaysTemplate and change the UIButton's tint to white, while also adding two spaces before the string : " Back". This will result in something that is quiet similar to the navigation bar back button, the image could be better in terms of size and placement.
Edited code:
func addBackButton() {
let backButtonImage = UIImage(named: "BackButton.png")?.withRenderingMode(.alwaysTemplate)
let backButton = UIButton(type: .custom)
backButton.setImage(backButtonImage, for: .normal)
backButton.tintColor = .white
backButton.setTitle(" Back", for: .normal)
backButton.setTitleColor(.white, for: .normal)
backButton.addTarget(self, action: #selector(self.backAction(_:)), for: .touchUpInside)
self.navigationItem.leftBarButtonItem = UIBarButtonItem(customView: backButton)
}
I changed one last line of code from selected answer and it works for me.
override func viewDidLoad() {
super.viewDidLoad()
addBackButton()
}
func addBackButton() {
let backButton = UIButton(type: .custom)
backButton.setImage(UIImage(named: "BackButton.png"), for: .normal) // Image can be downloaded from here below link
backButton.setTitle("Back", for: .normal)
backButton.setTitleColor(backButton.tintColor, for: .normal) // You can change the TitleColor
backButton.addTarget(self, action: #selector(self.backAction(_:)), for: .touchUpInside)
self.navigationItem.leftBarButtonItem = UIBarButtonItem(customView: backButton)
}
#IBAction func backAction(_ sender: UIButton) {
let _ = self.dismiss(animated: true, completion: nil)
}
Swift 5
override func viewDidLoad() {
super.viewDidLoad()
let backbutton = UIButton(type: .custom)
backbutton.setImage(UIImage(named: "BackButton.png"), for: .normal) // Image can be downloaded from here below link
backbutton.setTitle("Back", for: .normal)
backbutton.setTitleColor(backbutton.tintColor, for: .normal) // You can change the TitleColor
backbutton.addTarget(self, action: Selector(("backAction")), for: .touchUpInside)
self.navigationItem.leftBarButtonItem = UIBarButtonItem(customView: backbutton)
}
func backAction() -> Void {
self.navigationController?.popViewController(animated: true)
}
I have a button on custom tableviewcell. I've been able add action to this button by add target like below code:
var playButton = cell.contentView.viewWithTag(5) as? UIButton
var sender : UIButton = UIButton()
playButton?.addTarget(self, action: "playPost:", forControlEvents: UIControlEvents.TouchUpInside)
playButton?.layer.setValue(object["previewUrl"] as? String, forKey: "songUrl")
playButton?.layer.setValue(indexPath.row, forKey: "index")
But, how can I change it's title whenever I clicked this button?
If your function is playPost(), you could change the value passed in (which is the sender of the function, by default) like this:
func playPost(sender: UIButton) {
sender.setTitle("New title", forState: UIControlState.Normal);
}
You can Change UIButton title by using setTitle Method
Example
var button = UIButton(frame: CGRect(x: 50, y: 50, width: 200, height: 100))
button.backgroundColor = UIColor.blackColor()
button.setTitle("Start", forState: UIControlState.Normal)
button.addTarget(self, action: "pressButton:", forControlEvents: UIControlEvents.TouchUpInside)
self.view.addSubview(button)
func pressButton(sender:UIButton)
{
if sender.titleLabel?.text == "Start"
{
sender.setTitle("Stop", forState: UIControlState.Normal)
}
else
{
sender.setTitle("Start", forState: UIControlState.Normal)
}
}